diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e075b1af..f51159b9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,7 @@ and this project adheres to ### Changed - ♻️(backend) reset collaboration connection in cascade for all children #2507 +- ♿️(frontend) limit share modal opening announcement for screen readers #2452 ### Fixed diff --git a/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareModal.tsx b/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareModal.tsx index 01f1c729a..7288872d4 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareModal.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-share/components/DocShareModal.tsx @@ -40,6 +40,8 @@ import { import { QuickSearchGroupMember } from './DocShareMember'; import { DocShareModalFooter } from './DocShareModalFooter'; +const DEBOUNCE_MS = 300; + const ShareModalStyle = createGlobalStyle` .--docs--doc-share-modal [cmdk-item] { cursor: auto; @@ -84,6 +86,7 @@ export const DocShareModal = ({ doc, onClose, isRootDoc = true }: Props) => { const [listHeight, setListHeight] = useState('400px'); const canShare = doc.abilities.accesses_manage && isRootDoc; + const [isContentAccessible, setIsContentAccessible] = useState(canShare); const canViewAccesses = doc.abilities.accesses_view; const showMemberSection = inputValue === '' && selectedUsers.length === 0; const showFooter = selectedUsers.length === 0 && !inputValue; @@ -119,7 +122,7 @@ export const DocShareModal = ({ doc, onClose, isRootDoc = true }: Props) => { const onFilter = useDebouncedCallback((str: string) => { setUserQuery(str); - }, 300); + }, DEBOUNCE_MS); const onRemoveUser = (row: User) => { setSelectedUsers((prevState) => { @@ -161,6 +164,20 @@ export const DocShareModal = ({ doc, onClose, isRootDoc = true }: Props) => { const showInheritedShareContent = inheritedAccesses.length > 0 && showMemberSection && !isRootDoc; + // When the search input is hidden, keep the modal content out of the + // accessibility tree during the opening announcement, then restore it. + useEffect(() => { + if (canShare) { + return; + } + + const id = window.setTimeout(() => { + setIsContentAccessible(true); + }, DEBOUNCE_MS); + + return () => window.clearTimeout(id); + }, [canShare]); + // Invalidate relevant queries to ensure fresh data on modal open useEffect(() => { [ @@ -197,6 +214,7 @@ export const DocShareModal = ({ doc, onClose, isRootDoc = true }: Props) => { {t('Share the document')} @@ -206,6 +224,7 @@ export const DocShareModal = ({ doc, onClose, isRootDoc = true }: Props) => { >