diff --git a/__tests__/src/components/WindowTopMenuButton.test.js b/__tests__/src/components/WindowTopMenuButton.test.js index baf91aef59..f49934dbe3 100644 --- a/__tests__/src/components/WindowTopMenuButton.test.js +++ b/__tests__/src/components/WindowTopMenuButton.test.js @@ -47,6 +47,6 @@ describe('WindowTopMenuButton', () => { render(); await user.click(screen.getByLabelText('Window views & thumbnail display')); // when 'open' is true, aria-owns is set to the id of the window - expect(screen.getByLabelText('Window views & thumbnail display')).toHaveAttribute('aria-owns', 'window-menu_xyz'); // eslint-disable-line testing-library/no-node-access + expect(screen.getByLabelText('Window views & thumbnail display')).toHaveAttribute('aria-owns'); // eslint-disable-line testing-library/no-node-access }); }); diff --git a/src/components/ManifestRelatedLinks.js b/src/components/ManifestRelatedLinks.js index 2169b68c1d..b6609ed3d0 100644 --- a/src/components/ManifestRelatedLinks.js +++ b/src/components/ManifestRelatedLinks.js @@ -7,6 +7,7 @@ import { useTranslation } from 'react-i18next'; import CollapsibleSection from '../containers/CollapsibleSection'; import ns from '../config/css-ns'; import { PluginHook } from './PluginHook'; +import { useId } from 'react'; const StyledDl = styled('dl')(({ theme }) => ({ '& dd': { @@ -28,18 +29,19 @@ export function ManifestRelatedLinks({ ...rest }) { const { t } = useTranslation(); + const titleId = useId(); + const pluginProps = { homepage, id, manifestUrl, related, renderings, seeAlso, t, ...rest, }; return ( diff --git a/src/components/SearchHit.js b/src/components/SearchHit.js index c656f4d147..de79d2126f 100644 --- a/src/components/SearchHit.js +++ b/src/components/SearchHit.js @@ -1,4 +1,4 @@ -import { useEffect, useMemo } from 'react'; +import { useEffect, useId, useMemo } from 'react'; import { useEffectEvent } from 'use-effect-event'; import PropTypes from 'prop-types'; import Button from '@mui/material/Button'; @@ -86,11 +86,12 @@ export function SearchHit({ ); }); + const canvasLabelHtmlId = useId(); + if (focused && !selected) return null; const renderedHit = focused ? hit : hit && truncatedHit; const truncated = hit && (renderedHit.before !== hit.before || renderedHit.after !== hit.after); - const canvasLabelHtmlId = `${companionWindowId}-${index}`; const ownerState = { adjacent, focused, selected, windowSelected, }; diff --git a/src/components/WindowListButton.js b/src/components/WindowListButton.js index 3134fa745e..451cf2bba7 100644 --- a/src/components/WindowListButton.js +++ b/src/components/WindowListButton.js @@ -1,4 +1,4 @@ -import { useState } from 'react'; +import { useId, useState } from 'react'; import PropTypes from 'prop-types'; import BookmarksIcon from '@mui/icons-material/BookmarksSharp'; import { useTranslation } from 'react-i18next'; @@ -11,6 +11,7 @@ import MiradorMenuButton from '../containers/MiradorMenuButton'; export function WindowListButton({ disabled = false, windowCount }) { const { t } = useTranslation(); const [windowListAnchor, setWindowListAnchor] = useState(null); + const id = useId(); /** */ const handleClose = () => { setWindowListAnchor(null); }; @@ -22,7 +23,7 @@ export function WindowListButton({ disabled = false, windowCount }) { diff --git a/src/components/WindowSideBarCanvasPanel.js b/src/components/WindowSideBarCanvasPanel.js index 59953f2275..2b30297c4b 100644 --- a/src/components/WindowSideBarCanvasPanel.js +++ b/src/components/WindowSideBarCanvasPanel.js @@ -1,4 +1,4 @@ -import { useRef } from 'react'; +import { useId, useRef } from 'react'; import PropTypes from 'prop-types'; import { styled } from '@mui/material/styles'; import Tabs from '@mui/material/Tabs'; @@ -49,6 +49,7 @@ export function WindowSideBarCanvasPanel({ }) { const { t } = useTranslation(); const containerRef = useRef(); + const tabPanelId = useId(); /** */ const handleSequenceChange = (event) => { @@ -126,15 +127,15 @@ export function WindowSideBarCanvasPanel({ textColor="primary" > {showToc && ( - } /> + } /> )} - } /> - } /> + } /> + } /> > )} > - + { collection && ( { @@ -31,7 +32,6 @@ export function WindowTopBarPluginMenu({ setOpen(false); }; - const windowPluginMenuId = `window-plugin-menu_${windowId}`; if (!PluginComponents || PluginComponents.length === 0) return null; return ( diff --git a/src/components/WindowTopMenuButton.js b/src/components/WindowTopMenuButton.js index 75a70a5f39..dc0375d619 100644 --- a/src/components/WindowTopMenuButton.js +++ b/src/components/WindowTopMenuButton.js @@ -1,4 +1,4 @@ -import { useState } from 'react'; +import { useId, useState } from 'react'; import PropTypes from 'prop-types'; import { useTranslation } from 'react-i18next'; import WindowTopMenu from '../containers/WindowTopMenu'; @@ -11,6 +11,7 @@ export function WindowTopMenuButton({ classes = {}, windowId }) { const { t } = useTranslation(); const [anchorEl, setAnchorEl] = useState(null); const [open, setOpen] = useState(false); + const menuId = useId(); /** */ const handleMenuClick = (event) => { @@ -24,7 +25,6 @@ export function WindowTopMenuButton({ classes = {}, windowId }) { setOpen(false); }; - const menuId = `window-menu_${windowId}`; return ( <> - + {t('downloadExport')} diff --git a/src/components/WorkspaceImport.js b/src/components/WorkspaceImport.js index a553445e9e..430ab35685 100644 --- a/src/components/WorkspaceImport.js +++ b/src/components/WorkspaceImport.js @@ -1,4 +1,4 @@ -import { useState } from 'react'; +import { useId, useState } from 'react'; import DialogTitle from '@mui/material/DialogTitle'; import PropTypes from 'prop-types'; import { @@ -13,10 +13,11 @@ import ScrollIndicatedDialogContent from '../containers/ScrollIndicatedDialogCon /** */ export function WorkspaceImport({ - addError, importConfig, classes = {}, handleClose, open = false, + addError, id, importConfig, classes = {}, handleClose, open = false, }) { const { t } = useTranslation(); const [configImportValue, setConfigImportValue] = useState(''); + const titleId = useId(); /** */ const handleChange = (event) => { @@ -37,14 +38,14 @@ export function WorkspaceImport({ return ( - + {t('importWorkspace')} diff --git a/src/components/WorkspaceMenuButton.js b/src/components/WorkspaceMenuButton.js index c26309999e..b4cd1798cf 100644 --- a/src/components/WorkspaceMenuButton.js +++ b/src/components/WorkspaceMenuButton.js @@ -1,4 +1,4 @@ -import { useState } from 'react'; +import { useId, useState } from 'react'; import SettingsIcon from '@mui/icons-material/SettingsSharp'; import { useTranslation } from 'react-i18next'; import WorkspaceMenu from '../containers/WorkspaceMenu'; @@ -10,6 +10,7 @@ export function WorkspaceMenuButton() { const { t } = useTranslation(); const [anchorEl, setAnchorEl] = useState(null); const [open, setOpen] = useState(false); + const id = useId(); /** */ const handleMenuClick = (event) => { @@ -28,7 +29,7 @@ export function WorkspaceMenuButton() { diff --git a/src/components/WorkspaceOptionsMenu.js b/src/components/WorkspaceOptionsMenu.js index 470902554d..061b09f6dd 100644 --- a/src/components/WorkspaceOptionsMenu.js +++ b/src/components/WorkspaceOptionsMenu.js @@ -1,4 +1,4 @@ -import { useContext, useState } from 'react'; +import { useContext, useId, useState } from 'react'; import PropTypes from 'prop-types'; import ImportIcon from '@mui/icons-material/Input'; import SaveAltIcon from '@mui/icons-material/SaveAltSharp'; @@ -21,6 +21,8 @@ export function WorkspaceOptionsMenu({ const { t } = useTranslation(); const container = useContext(WorkspaceContext); const [selectedOption, setSelectedOption] = useState(null); + const exportId = useId(); + const importId = useId(); const pluginProps = { anchorEl, container, handleClose, open, t, ...rest, @@ -57,7 +59,7 @@ export function WorkspaceOptionsMenu({ { handleClick('exportWorkspace'); }} - aria-owns={selectedOption === 'exportWorkspace' ? 'workspace-export' : undefined} + aria-owns={selectedOption === 'exportWorkspace' ? exportId : undefined} > @@ -66,9 +68,8 @@ export function WorkspaceOptionsMenu({ { handleClick('importWorkspace'); }} - aria-owns={selectedOption === 'importWorkspace' ? 'workspace-import' : undefined} + aria-owns={selectedOption === 'importWorkspace' ? importId : undefined} > @@ -79,6 +80,7 @@ export function WorkspaceOptionsMenu({ {selectedOption === 'exportWorkspace' && ( ({ display: 'flex', @@ -25,6 +26,8 @@ export function WorkspaceSelectionDialog({ container = null, handleClose, open = false, children = null, updateWorkspace, workspaceType, }) { const { t } = useTranslation(); + const dialogTitleId = useId(); + /** */ const handleWorkspaceTypeChange = (newWorkspaceType) => { updateWorkspace({ @@ -35,13 +38,12 @@ export function WorkspaceSelectionDialog({ return ( - + {t('workspaceSelectionTitle')}