Introduce focus traps for ModalHost, add button role to DropZone
This commit is contained in:
parent
adaeb81c32
commit
48229332ea
8 changed files with 371 additions and 294 deletions
|
@ -1003,6 +1003,30 @@ Signal Desktop makes use of the following open source projects.
|
|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
## focus-trap-react
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 David Clark
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
## form-data
|
||||
|
||||
Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors
|
||||
|
|
|
@ -96,6 +96,7 @@
|
|||
"fast-glob": "3.2.1",
|
||||
"filesize": "3.6.1",
|
||||
"firstline": "1.2.1",
|
||||
"focus-trap-react": "8.8.1",
|
||||
"form-data": "3.0.0",
|
||||
"fs-extra": "5.0.0",
|
||||
"fuse.js": "3.4.4",
|
||||
|
|
|
@ -47,7 +47,10 @@ export const DropZone: React.ComponentType<Props> = props => {
|
|||
}, [isDragActive, onDragActive]);
|
||||
|
||||
return (
|
||||
<div {...getRootProps({ className: getClassName(props, isDragActive) })}>
|
||||
<div
|
||||
{...getRootProps({ className: getClassName(props, isDragActive) })}
|
||||
role="button"
|
||||
>
|
||||
<input {...getInputProps()} />
|
||||
<svg viewBox="0 0 36 36" width="36px" height="36px">
|
||||
<path d="M32 17.25H18.75V4h-1.5v13.25H4v1.5h13.25V32h1.5V18.75H32v-1.5z" />
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { createPortal } from 'react-dom';
|
||||
import FocusTrap from 'focus-trap-react';
|
||||
|
||||
import { Theme, themeClassName } from '../util/theme';
|
||||
import { useEscapeHandling } from '../hooks/useEscapeHandling';
|
||||
|
||||
|
@ -56,6 +58,7 @@ export const ModalHost = React.memo(
|
|||
|
||||
return root
|
||||
? createPortal(
|
||||
<FocusTrap>
|
||||
<div
|
||||
role="presentation"
|
||||
className={classNames(
|
||||
|
@ -66,7 +69,8 @@ export const ModalHost = React.memo(
|
|||
onMouseUp={noMouseClose ? undefined : handleMouseUp}
|
||||
>
|
||||
{children}
|
||||
</div>,
|
||||
</div>
|
||||
</FocusTrap>,
|
||||
root
|
||||
)
|
||||
: null;
|
||||
|
|
|
@ -18,6 +18,8 @@ import {
|
|||
last,
|
||||
zipObject,
|
||||
} from 'lodash';
|
||||
import FocusTrap from 'focus-trap-react';
|
||||
|
||||
import { Emoji } from './Emoji';
|
||||
import { dataByCategory, search } from './lib';
|
||||
import { LocalizerType } from '../../types/Util';
|
||||
|
@ -301,6 +303,7 @@ export const EmojiPicker = React.memo(
|
|||
);
|
||||
|
||||
return (
|
||||
<FocusTrap>
|
||||
<div className="module-emoji-picker" ref={ref} style={style}>
|
||||
<header className="module-emoji-picker__header">
|
||||
<button
|
||||
|
@ -419,6 +422,7 @@ export const EmojiPicker = React.memo(
|
|||
)}
|
||||
</footer>
|
||||
</div>
|
||||
</FocusTrap>
|
||||
);
|
||||
}
|
||||
)
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import FocusTrap from 'focus-trap-react';
|
||||
|
||||
import { useRestoreFocus } from '../../hooks/useRestoreFocus';
|
||||
import { StickerPackType, StickerType } from '../../state/ducks/stickers';
|
||||
import { LocalizerType } from '../../types/Util';
|
||||
|
@ -146,6 +148,7 @@ export const StickerPicker = React.memo(
|
|||
const showLongText = showPickerHint;
|
||||
|
||||
return (
|
||||
<FocusTrap>
|
||||
<div className="module-sticker-picker" ref={ref} style={style}>
|
||||
<div className="module-sticker-picker__header">
|
||||
<div className="module-sticker-picker__header__packs">
|
||||
|
@ -210,7 +213,8 @@ export const StickerPicker = React.memo(
|
|||
aria-label={i18n('stickers--StickerPicker--PrevPage')}
|
||||
/>
|
||||
) : null}
|
||||
{!isUsingKeyboard && !isLastPacksPage(packsPage, packs.length) ? (
|
||||
{!isUsingKeyboard &&
|
||||
!isLastPacksPage(packsPage, packs.length) ? (
|
||||
<button
|
||||
type="button"
|
||||
className={classNames(
|
||||
|
@ -289,10 +293,13 @@ export const StickerPicker = React.memo(
|
|||
) : null}
|
||||
{!isEmpty ? (
|
||||
<div
|
||||
className={classNames('module-sticker-picker__body__content', {
|
||||
className={classNames(
|
||||
'module-sticker-picker__body__content',
|
||||
{
|
||||
'module-sticker-picker__body__content--under-text': showText,
|
||||
'module-sticker-picker__body__content--under-long-text': showLongText,
|
||||
})}
|
||||
}
|
||||
)}
|
||||
>
|
||||
{stickers.map(({ packId, id, url }, index: number) => {
|
||||
const maybeFocusRef = index === 0 ? focusRef : undefined;
|
||||
|
@ -327,6 +334,7 @@ export const StickerPicker = React.memo(
|
|||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</FocusTrap>
|
||||
);
|
||||
}
|
||||
)
|
||||
|
|
|
@ -1688,6 +1688,20 @@
|
|||
"reasonCategory": "falseMatch",
|
||||
"updated": "2018-09-15T00:38:04.183Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-findDOMNode",
|
||||
"path": "node_modules/focus-trap-react/dist/focus-trap-react.js",
|
||||
"line": " var focusTrapElementDOMNodes = this.focusTrapElements.map( // NOTE: `findDOMNode()` does not support CSS selectors; it'll just return",
|
||||
"reasonCategory": "exampleCode",
|
||||
"updated": "2021-10-01T23:53:26.107Z"
|
||||
},
|
||||
{
|
||||
"rule": "React-findDOMNode",
|
||||
"path": "node_modules/focus-trap-react/src/focus-trap-react.js",
|
||||
"line": " // NOTE: `findDOMNode()` does not support CSS selectors; it'll just return",
|
||||
"reasonCategory": "exampleCode",
|
||||
"updated": "2021-10-01T23:53:26.107Z"
|
||||
},
|
||||
{
|
||||
"rule": "jQuery-load(",
|
||||
"path": "node_modules/foreground-child/node_modules/signal-exit/index.js",
|
||||
|
|
19
yarn.lock
19
yarn.lock
|
@ -8677,6 +8677,20 @@ focus-lock@^0.6.3:
|
|||
resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-0.6.5.tgz#f6eb37832a9b1b205406175f5277396a28c0fce1"
|
||||
integrity sha512-i/mVBOoa9o+tl+u9owOJUF8k8L85odZNIsctB+JAK2HFT8jckiBwmk+3uydlm6FN8czgnkIwQtBv6yyAbrzXjw==
|
||||
|
||||
focus-trap-react@8.8.1:
|
||||
version "8.8.1"
|
||||
resolved "https://registry.yarnpkg.com/focus-trap-react/-/focus-trap-react-8.8.1.tgz#2c7043e748460a191a1c7e2552e7c964f3f9fd46"
|
||||
integrity sha512-Uy7U/l3fozlwLYBSQHP91QjuRUUcAQ9FJ3glAGmwF/fXSiPa/4negTy02zWElLZdZDPIfebC8V14aI1Gzc5V3w==
|
||||
dependencies:
|
||||
focus-trap "^6.7.1"
|
||||
|
||||
focus-trap@^6.7.1:
|
||||
version "6.7.1"
|
||||
resolved "https://registry.yarnpkg.com/focus-trap/-/focus-trap-6.7.1.tgz#d474f86dbaf3c7fbf0d53cf0b12295f4f4068d10"
|
||||
integrity sha512-a6czHbT9twVpy2RpkWQA9vIgwQgB9Nx1PIxNNUxQT4nugG/3QibwxO+tWTh9i+zSY2SFiX4pnYhTaFaQF/6ZAg==
|
||||
dependencies:
|
||||
tabbable "^5.2.1"
|
||||
|
||||
follow-redirects@^1.0.0:
|
||||
version "1.13.0"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db"
|
||||
|
@ -17445,6 +17459,11 @@ symbol.prototype.description@^1.0.0:
|
|||
dependencies:
|
||||
has-symbols "^1.0.0"
|
||||
|
||||
tabbable@^5.2.1:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-5.2.1.tgz#e3fda7367ddbb172dcda9f871c0fdb36d1c4cd9c"
|
||||
integrity sha512-40pEZ2mhjaZzK0BnI+QGNjJO8UYx9pP5v7BGe17SORTO0OEuuaAwQTkAp8whcZvqon44wKFOikD+Al11K3JICQ==
|
||||
|
||||
table@^5.2.3:
|
||||
version "5.4.6"
|
||||
resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e"
|
||||
|
|
Loading…
Add table
Reference in a new issue