Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
coopwire-hypothesis
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
孙灵跃 Leon Sun
coopwire-hypothesis
Commits
2b18c185
Commit
2b18c185
authored
Jun 11, 2021
by
Lyza Danger Gardner
Committed by
Lyza Gardner
Jun 14, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove unused local Dialog components and styles
parent
29bd7b79
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
0 additions
and
504 deletions
+0
-504
ConfirmDialog.js
src/shared/components/ConfirmDialog.js
+0
-39
Dialog.js
src/shared/components/Dialog.js
+0
-159
ConfirmDialog-test.js
src/shared/components/test/ConfirmDialog-test.js
+0
-39
Dialog-test.js
src/shared/components/test/Dialog-test.js
+0
-185
annotator.scss
src/styles/annotator/annotator.scss
+0
-3
_index.scss
src/styles/shared/_index.scss
+0
-1
_Dialog.scss
src/styles/shared/components/_Dialog.scss
+0
-74
sidebar.scss
src/styles/sidebar/sidebar.scss
+0
-4
No files found.
src/shared/components/ConfirmDialog.js
deleted
100644 → 0
View file @
29bd7b79
import
{
LabeledButton
}
from
'@hypothesis/frontend-shared'
;
import
Dialog
from
'./Dialog'
;
/**
* @typedef ConfirmDialogProps
* @prop {string} title - Title of the dialog
* @prop {string} message - Main text of the message
* @prop {string} confirmAction - Label for the "Confirm" button
* @prop {() => any} onConfirm - Callback invoked if the user clicks the "Confirm" button
* @prop {() => any} onCancel - Callback invoked if the user cancels
*/
/**
* A prompt asking the user to confirm an action.
*
* @param {ConfirmDialogProps} props
*/
export
default
function
ConfirmDialog
({
title
,
message
,
confirmAction
,
onConfirm
,
onCancel
,
})
{
return
(
<
Dialog
title
=
{
title
}
onCancel
=
{
onCancel
}
buttons
=
{[
<
LabeledButton
key
=
"ok"
onClick
=
{
onConfirm
}
variant
=
"primary"
>
{
confirmAction
}
<
/LabeledButton>
,
]}
>
<
p
>
{
message
}
<
/p
>
<
/Dialog
>
);
}
src/shared/components/Dialog.js
deleted
100644 → 0
View file @
29bd7b79
import
{
LabeledButton
,
useElementShouldClose
,
}
from
'@hypothesis/frontend-shared'
;
import
{
Fragment
}
from
'preact'
;
import
{
useEffect
,
useLayoutEffect
,
useRef
,
useState
}
from
'preact/hooks'
;
import
classNames
from
'classnames'
;
let
idCounter
=
0
;
/**
* Return an element ID beginning with `prefix` that is unique per component instance.
*
* This avoids different instances of a component re-using the same ID.
*
* @param {string} prefix
*/
function
useUniqueId
(
prefix
)
{
const
[
id
]
=
useState
(()
=>
{
++
idCounter
;
return
`
${
prefix
}
-
${
idCounter
}
`
;
});
return
id
;
}
/**
* @typedef {import("preact").ComponentChildren} Children
*
* @typedef DialogProps
* @prop {Children} children - The content of the dialog.
* @prop {import("preact/hooks").Ref<HTMLElement>} [initialFocus] -
* Child element to focus when the dialog is rendered.
* @prop {Children} [buttons] -
* Additional `Button` elements to display at the bottom of the dialog.
* A "Cancel" button is added automatically if the `onCancel` prop is set.
* @prop {string} [contentClass] - CSS class to apply to the dialog's content
* @prop {'dialog'|'alertdialog'} [role] - The aria role for the dialog (defaults to" dialog")
* @prop {string} title - The title of the dialog.
* @prop {() => any} [onCancel] -
* A callback to invoke when the user cancels the dialog. If provided, a
* "Cancel" button will be displayed.
* @prop {string} [cancelLabel] - Label for the cancel button
*/
/**
* HTML control that can be disabled.
*
* @typedef {HTMLElement & { disabled: boolean }} InputElement
*/
/**
* A modal dialog wrapper with a title. The wrapper sets initial focus to itself
* unless an element inside of it is specified with the `initialFocus` ref.
* Optional action buttons may be passed in with the `buttons` prop but the
* cancel button is automatically generated when the on `onCancel` function is
* passed.
*
* Canonical resources:
*
* https://www.w3.org/TR/wai-aria-practices/examples/dialog-modal/dialog.html
* https://www.w3.org/TR/wai-aria-practices/examples/dialog-modal/alertdialog.html
*
* If the dialog's content, specified by the `children` prop, contains a paragraph
* (`<p>`) element, that element will be identified as the dialog's accessible
* description.
*
* @param {DialogProps} props
*/
export
default
function
Dialog
({
children
,
contentClass
,
initialFocus
,
onCancel
,
cancelLabel
=
'Cancel'
,
role
=
'dialog'
,
title
,
buttons
,
})
{
const
dialogTitleId
=
useUniqueId
(
'dialog-title'
);
const
dialogDescriptionId
=
useUniqueId
(
'dialog-description'
);
const
rootEl
=
useRef
(
/** @type {HTMLDivElement | null} */
(
null
));
useElementShouldClose
(
rootEl
,
true
,
()
=>
{
if
(
onCancel
)
{
onCancel
();
}
});
useEffect
(()
=>
{
const
focusEl
=
/** @type {InputElement|undefined} */
(
initialFocus
?.
current
);
if
(
focusEl
&&
!
focusEl
.
disabled
)
{
focusEl
.
focus
();
}
else
{
// Modern accessibility guidance is to focus the dialog itself rather than
// trying to be smart about focusing a particular control within the
// dialog. See resources above.
rootEl
.
current
.
focus
();
}
// We only want to run this effect once when the dialog is mounted.
//
// eslint-disable-next-line react-hooks/exhaustive-deps
},
[]);
// Try to assign the dialog an accessible description, using the content of
// the first paragraph of text in it.
//
// A limitation of this approach is that it doesn't update if the dialog's
// content changes after the initial render.
useLayoutEffect
(()
=>
{
const
description
=
rootEl
.
current
.
querySelector
(
'p'
);
if
(
description
)
{
description
.
id
=
dialogDescriptionId
;
rootEl
.
current
.
setAttribute
(
'aria-describedby'
,
dialogDescriptionId
);
}
},
[
dialogDescriptionId
]);
return
(
<
Fragment
>
<
div
className
=
"Dialog__background"
/>
<
div
className
=
"Dialog__container"
>
<
div
tabIndex
=
{
-
1
}
ref
=
{
rootEl
}
role
=
{
role
}
aria
-
labelledby
=
{
dialogTitleId
}
aria
-
modal
=
{
true
}
className
=
{
classNames
(
'Dialog__content'
,
contentClass
)}
>
<
h1
className
=
"Dialog__title"
id
=
{
dialogTitleId
}
>
{
title
}
<
span
className
=
"u-stretch"
/>
{
onCancel
&&
(
<
button
aria
-
label
=
"Close"
className
=
"Dialog__cancel-btn"
onClick
=
{
onCancel
}
>
✕
<
/button
>
)}
<
/h1
>
{
children
}
<
div
className
=
"u-stretch"
/>
<
div
className
=
"Dialog__actions"
>
{
onCancel
&&
(
<
LabeledButton
icon
=
"cancel"
onClick
=
{
onCancel
}
>
{
cancelLabel
}
<
/LabeledButton
>
)}
{
buttons
}
<
/div
>
<
/div
>
<
/div
>
<
/Fragment
>
);
}
src/shared/components/test/ConfirmDialog-test.js
deleted
100644 → 0
View file @
29bd7b79
import
{
mount
}
from
'enzyme'
;
import
mockImportedComponents
from
'../../../test-util/mock-imported-components'
;
import
ConfirmDialog
,
{
$imports
}
from
'../ConfirmDialog'
;
describe
(
'ConfirmDialog'
,
()
=>
{
beforeEach
(()
=>
{
$imports
.
$mock
(
mockImportedComponents
());
});
afterEach
(()
=>
{
$imports
.
$restore
();
});
it
(
'renders dialog'
,
()
=>
{
const
confirm
=
sinon
.
stub
();
const
cancel
=
sinon
.
stub
();
const
wrapper
=
mount
(
<
ConfirmDialog
title
=
"Delete annotation?"
message
=
"Do you want to delete this annotation?"
confirmAction
=
"Do it!"
onConfirm
=
{
confirm
}
onCancel
=
{
cancel
}
/
>
);
const
dialog
=
wrapper
.
find
(
'Dialog'
);
assert
.
equal
(
dialog
.
prop
(
'title'
),
'Delete annotation?'
);
assert
.
equal
(
dialog
.
children
().
text
(),
'Do you want to delete this annotation?'
);
assert
.
equal
(
dialog
.
prop
(
'onCancel'
),
cancel
);
assert
.
equal
(
mount
(
dialog
.
prop
(
'buttons'
)[
0
]).
prop
(
'onClick'
),
confirm
);
});
});
src/shared/components/test/Dialog-test.js
deleted
100644 → 0
View file @
29bd7b79
import
{
mount
}
from
'enzyme'
;
import
{
createRef
}
from
'preact'
;
import
Dialog
from
'../Dialog'
;
import
{
checkAccessibility
}
from
'../../../test-util/accessibility'
;
describe
(
'Dialog'
,
()
=>
{
it
(
'renders content'
,
()
=>
{
const
wrapper
=
mount
(
<
Dialog
>
<
span
>
content
<
/span
>
<
/Dialog
>
);
assert
.
isTrue
(
wrapper
.
contains
(
<
span
>
content
<
/span>
))
;
});
it
(
'adds `contentClass` value to class list'
,
()
=>
{
const
wrapper
=
mount
(
<
Dialog
contentClass
=
"foo"
>
<
span
>
content
<
/span
>
<
/Dialog
>
);
assert
.
isTrue
(
wrapper
.
find
(
'.Dialog__content'
).
hasClass
(
'foo'
));
});
it
(
'renders buttons'
,
()
=>
{
const
wrapper
=
mount
(
<
Dialog
buttons
=
{[
<
button
key
=
"foo"
name
=
"foo"
/>
,
<
button
key
=
"bar"
name
=
"bar"
/>
,
]}
/
>
);
assert
.
isTrue
(
wrapper
.
contains
(
<
button
key
=
"foo"
name
=
"foo"
/>
));
assert
.
isTrue
(
wrapper
.
contains
(
<
button
key
=
"bar"
name
=
"bar"
/>
));
});
it
(
'renders the title'
,
()
=>
{
const
wrapper
=
mount
(
<
Dialog
title
=
"Test dialog"
/>
);
const
header
=
wrapper
.
find
(
'h1'
);
assert
.
equal
(
header
.
text
().
indexOf
(
'Test dialog'
),
0
);
});
it
(
'closes when Escape key is pressed'
,
()
=>
{
const
onCancel
=
sinon
.
stub
();
const
container
=
document
.
createElement
(
'div'
);
document
.
body
.
appendChild
(
container
);
mount
(
<
Dialog
title
=
"Test dialog"
onCancel
=
{
onCancel
}
/>,
{
attachTo
:
container
,
});
const
event
=
new
Event
(
'keydown'
);
event
.
key
=
'Escape'
;
document
.
body
.
dispatchEvent
(
event
);
assert
.
called
(
onCancel
);
container
.
remove
();
});
it
(
'closes when close button is clicked'
,
()
=>
{
const
onCancel
=
sinon
.
stub
();
const
wrapper
=
mount
(
<
Dialog
title
=
"Test dialog"
onCancel
=
{
onCancel
}
/>
)
;
wrapper
.
find
(
'.Dialog__cancel-btn'
).
simulate
(
'click'
);
assert
.
called
(
onCancel
);
});
it
(
`defaults cancel button's label to "Cancel"`
,
()
=>
{
const
wrapper
=
mount
(
<
Dialog
onCancel
=
{
sinon
.
stub
()}
/>
)
;
assert
.
equal
(
wrapper
.
find
(
'LabeledButton'
).
text
().
trim
(),
'Cancel'
);
});
it
(
'adds a custom label to the cancel button'
,
()
=>
{
const
wrapper
=
mount
(
<
Dialog
onCancel
=
{
sinon
.
stub
()}
cancelLabel
=
"hello"
/>
);
assert
.
equal
(
wrapper
.
find
(
'LabeledButton'
).
text
().
trim
(),
'hello'
);
});
describe
(
'initial focus'
,
()
=>
{
let
container
;
beforeEach
(()
=>
{
container
=
document
.
createElement
(
'div'
);
document
.
body
.
appendChild
(
container
);
});
afterEach
(()
=>
{
container
.
remove
();
});
it
(
'focuses the `initialFocus` element'
,
()
=>
{
const
inputRef
=
createRef
();
mount
(
<
Dialog
initialFocus
=
{
inputRef
}
>
<
input
ref
=
{
inputRef
}
/
>
<
/Dialog>
,
{
attachTo
:
container
}
);
assert
.
equal
(
document
.
activeElement
,
inputRef
.
current
);
});
it
(
'focuses the dialog if `initialFocus` prop is missing'
,
()
=>
{
const
wrapper
=
mount
(
<
Dialog
>
<
div
>
Test
<
/div
>
<
/Dialog>
,
{
attachTo
:
container
}
);
assert
.
equal
(
document
.
activeElement
,
wrapper
.
find
(
'[role="dialog"]'
).
getDOMNode
()
);
});
it
(
'focuses the dialog if `initialFocus` ref is `null`'
,
()
=>
{
const
wrapper
=
mount
(
<
Dialog
initialFocus
=
{{
current
:
null
}}
>
<
div
>
Test
<
/div
>
<
/Dialog>
,
{
attachTo
:
container
}
);
assert
.
equal
(
document
.
activeElement
,
wrapper
.
find
(
'[role="dialog"]'
).
getDOMNode
()
);
});
it
(
'focuses the dialog if `initialFocus` element is disabled'
,
()
=>
{
const
inputRef
=
createRef
();
const
wrapper
=
mount
(
<
Dialog
initialFocus
=
{
inputRef
}
>
<
button
ref
=
{
inputRef
}
disabled
=
{
true
}
/
>
<
/Dialog>
,
{
attachTo
:
container
}
);
assert
.
equal
(
document
.
activeElement
,
wrapper
.
find
(
'[role="dialog"]'
).
getDOMNode
()
);
});
});
it
(
"marks the first `<p>` in the dialog's content as the accessible description"
,
()
=>
{
const
wrapper
=
mount
(
<
Dialog
>
<
p
>
Enter
a
URL
<
/p
>
<
/Dialog
>
);
const
content
=
wrapper
.
find
(
'[role="dialog"]'
).
getDOMNode
();
const
paragraphEl
=
wrapper
.
find
(
'p'
).
getDOMNode
();
assert
.
ok
(
content
.
getAttribute
(
'aria-describedby'
));
assert
.
equal
(
content
.
getAttribute
(
'aria-describedby'
),
paragraphEl
.
id
);
});
it
(
"does not set an accessible description if the dialog's content does not have a `<p>`"
,
()
=>
{
const
wrapper
=
mount
(
<
Dialog
>
<
button
>
Click
me
<
/button
>
<
/Dialog
>
);
const
content
=
wrapper
.
find
(
'[role="dialog"]'
).
getDOMNode
();
assert
.
isNull
(
content
.
getAttribute
(
'aria-describedby'
));
});
it
(
'should pass a11y checks'
,
checkAccessibility
({
// eslint-disable-next-line react/display-name
content
:
()
=>
(
<
Dialog
title
=
"Test dialog"
>
<
div
>
test
<
/div
>
<
/Dialog
>
),
})
);
});
src/styles/annotator/annotator.scss
View file @
2b18c185
...
@@ -10,9 +10,6 @@
...
@@ -10,9 +10,6 @@
// -----------------
// -----------------
@use
'@hypothesis/frontend-shared/styles'
;
@use
'@hypothesis/frontend-shared/styles'
;
// Shared button styles (TEMPORARY)
@use
'../shared'
;
// Annotator-specific components.
// Annotator-specific components.
@use
'./components/AdderToolbar'
;
@use
'./components/AdderToolbar'
;
@use
'./components/Buckets'
;
@use
'./components/Buckets'
;
...
...
src/styles/shared/_index.scss
deleted
100644 → 0
View file @
29bd7b79
@use
'./components/Dialog'
;
src/styles/shared/components/_Dialog.scss
deleted
100644 → 0
View file @
29bd7b79
@use
"@hypothesis/frontend-shared/styles/mixins/focus"
;
@use
"../variables"
as
var
;
$title-font-size
:
19px
;
.Dialog__container
{
display
:
flex
;
position
:
fixed
;
left
:
0
;
top
:
0
;
width
:
100%
;
height
:
100%
;
}
.Dialog__background
{
background-color
:
black
;
bottom
:
0
;
left
:
0
;
opacity
:
0
.5
;
position
:
fixed
;
right
:
0
;
top
:
0
;
}
.Dialog__content
{
@include
focus
.
outline-on-keyboard-focus
;
display
:
flex
;
flex-direction
:
column
;
max-height
:
90vh
;
max-width
:
700px
;
// default for older browsers
max-width
:
min
(
700px
,
90vw
);
background-color
:
white
;
border-radius
:
3px
;
margin
:
auto
;
padding
:
20px
;
}
.Dialog__title
{
display
:
flex
;
align-items
:
center
;
font-size
:
$title-font-size
;
}
.Dialog__cancel-btn
{
@include
focus
.
outline-on-keyboard-focus
;
border
:
0
;
background
:
none
;
color
:
var
.
$color-grey-6
;
// Given the button a large hit target and ensure the 'X' label is large
// enough to see easily and aligned with the right edge of the dialog.
// Add negative margins so that the button does not force the dialog to
// grow in height.
font-size
:
$title-font-size
;
padding
:
5px
;
margin
:
-10px
0px
;
&
:hover
{
cursor
:
pointer
;
color
:
var
.
$color-brand
;
}
}
.Dialog__actions
{
display
:
flex
;
flex-direction
:
row
;
justify-content
:
flex-end
;
margin-top
:
10px
;
&
>
*
:not
(
:first-child
)
{
margin-left
:
5px
;
}
}
src/styles/sidebar/sidebar.scss
View file @
2b18c185
...
@@ -11,10 +11,6 @@
...
@@ -11,10 +11,6 @@
// -----------------
// -----------------
@use
'@hypothesis/frontend-shared/styles'
;
@use
'@hypothesis/frontend-shared/styles'
;
// Temporary shared styles
// FIXME: Currently needed for Dialog styling
@use
'../shared'
;
// Custom button styling for the application
// Custom button styling for the application
@use
'./buttons'
;
@use
'./buttons'
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment