diff --git a/__tests__/src/components/CanvasInfo.test.js b/__tests__/src/components/CanvasInfo.test.js index 751ac2b60..94ac9082d 100644 --- a/__tests__/src/components/CanvasInfo.test.js +++ b/__tests__/src/components/CanvasInfo.test.js @@ -14,7 +14,6 @@ describe('CanvasInfo', () => { canvasLabel="The Canvas Label" canvasDescription="The Canvas Description" canvasMetadata={metadata} - id="xyz" />, ); }); @@ -45,7 +44,7 @@ describe('CanvasInfo', () => { describe('when metadata is not present', () => { beforeEach(() => { render( - , + , ); }); diff --git a/__tests__/src/components/CollectionInfo.test.js b/__tests__/src/components/CollectionInfo.test.js index b6080a91d..b147614bb 100644 --- a/__tests__/src/components/CollectionInfo.test.js +++ b/__tests__/src/components/CollectionInfo.test.js @@ -6,7 +6,6 @@ import { CollectionInfo } from '../../../src/components/CollectionInfo'; function createWrapper(props) { return render( {}} {...props} diff --git a/__tests__/src/components/ManifestInfo.test.js b/__tests__/src/components/ManifestInfo.test.js index 292e59370..3479e3a49 100644 --- a/__tests__/src/components/ManifestInfo.test.js +++ b/__tests__/src/components/ManifestInfo.test.js @@ -8,7 +8,6 @@ describe('ManifestInfo', () => { beforeEach(() => { render( { describe('when metadata is not present', () => { beforeEach(() => { render( - , + , ); }); diff --git a/__tests__/src/components/WindowTopMenuButton.test.js b/__tests__/src/components/WindowTopMenuButton.test.js index baf91aef5..f49934dbe 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/__tests__/src/components/WorkspaceOptionsMenu.test.js b/__tests__/src/components/WorkspaceOptionsMenu.test.js index 3d71aab0d..64da09529 100644 --- a/__tests__/src/components/WorkspaceOptionsMenu.test.js +++ b/__tests__/src/components/WorkspaceOptionsMenu.test.js @@ -48,18 +48,18 @@ describe('WorkspaceOptionsMenu', () => { it('renders the export dialog when export option is clicked', async () => { render(); - expect(document.querySelector('#workspace-export')).not.toBeInTheDocument(); // eslint-disable-line testing-library/no-node-access + expect(screen.queryByRole('heading', { name: 'Export workspace' })).not.toBeInTheDocument(); - await user.click(screen.getAllByRole('menuitem')[0]); - expect(document.querySelector('#workspace-export')).toBeInTheDocument(); // eslint-disable-line testing-library/no-node-access + await user.click(screen.getByRole('menuitem', { name: 'Export workspace' })); + expect(screen.getByRole('heading', { name: 'Export workspace' })).toBeInTheDocument(); }); - it('renders the import dialog when imporrt option is clicked', async () => { + it('renders the import dialog when import option is clicked', async () => { render(); - expect(document.querySelector('#workspace-import')).not.toBeInTheDocument(); // eslint-disable-line testing-library/no-node-access + expect(screen.queryByRole('heading', { name: 'Import workspace' })).not.toBeInTheDocument(); - await user.click(screen.getAllByRole('menuitem')[1]); - expect(document.querySelector('#workspace-import')).toBeInTheDocument(); // eslint-disable-line testing-library/no-node-access + await user.click(screen.getByRole('menuitem', { name: 'Import workspace' })); + expect(screen.getByRole('heading', { name: 'Import workspace' })).toBeInTheDocument(); }); it('fires the correct callbacks on menu close', async () => { diff --git a/src/components/CanvasInfo.js b/src/components/CanvasInfo.js index 2cd699c9c..6f3fa9e98 100644 --- a/src/components/CanvasInfo.js +++ b/src/components/CanvasInfo.js @@ -1,3 +1,4 @@ +import { useId } from 'react'; import PropTypes from 'prop-types'; import Typography from '@mui/material/Typography'; import { useTranslation } from 'react-i18next'; @@ -13,24 +14,25 @@ export function CanvasInfo({ canvasDescription = null, canvasLabel = null, canvasMetadata = [], - id, index = 1, totalSize = 1, }) { const { t } = useTranslation(); + const id = useId(); + const titleId = useId(); const pluginProps = arguments[0]; // eslint-disable-line prefer-rest-params return ( {canvasLabel && ( @@ -56,7 +58,6 @@ CanvasInfo.propTypes = { canvasDescription: PropTypes.string, canvasLabel: PropTypes.string, canvasMetadata: PropTypes.array, // eslint-disable-line react/forbid-prop-types - id: PropTypes.string.isRequired, index: PropTypes.number, totalSize: PropTypes.number, }; diff --git a/src/components/CollectionInfo.js b/src/components/CollectionInfo.js index c4aa043e2..1e4c6550d 100644 --- a/src/components/CollectionInfo.js +++ b/src/components/CollectionInfo.js @@ -1,3 +1,4 @@ +import { useId } from 'react'; import PropTypes from 'prop-types'; import Button from '@mui/material/Button'; import Typography from '@mui/material/Typography'; @@ -9,9 +10,11 @@ import CollapsibleSection from '../containers/CollapsibleSection'; * CollectionInfo */ export function CollectionInfo({ - collectionLabel = null, collectionPath = [], id, showCollectionDialog, windowId = null, + collectionLabel = null, collectionPath = [], showCollectionDialog, windowId = null, }) { const { t } = useTranslation(); + const id = useId(); + const titleId = useId(); /** * Show the containing collection. @@ -26,13 +29,13 @@ export function CollectionInfo({ return ( {collectionLabel && ( {collectionLabel} @@ -53,7 +56,6 @@ export function CollectionInfo({ CollectionInfo.propTypes = { collectionLabel: PropTypes.string, collectionPath: PropTypes.arrayOf(PropTypes.string), - id: PropTypes.string.isRequired, showCollectionDialog: PropTypes.func.isRequired, windowId: PropTypes.string, }; diff --git a/src/components/ManifestInfo.js b/src/components/ManifestInfo.js index 2b45e58e4..acdcf1dbe 100644 --- a/src/components/ManifestInfo.js +++ b/src/components/ManifestInfo.js @@ -1,3 +1,4 @@ +import { useId } from 'react'; import PropTypes from 'prop-types'; import Typography from '@mui/material/Typography'; import { useTranslation } from 'react-i18next'; @@ -10,12 +11,13 @@ import { PluginHook } from './PluginHook'; * ManifestInfo */ export function ManifestInfo({ - manifestDescription = null, manifestLabel = null, manifestMetadata = [], manifestSummary = null, id, + manifestDescription = null, manifestLabel = null, manifestMetadata = [], manifestSummary = null, ...rest }) { const { t } = useTranslation(); + const id = useId(); const pluginProps = { - id, manifestDescription, manifestLabel, manifestMetadata, manifestSummary, ...rest, + manifestDescription, manifestLabel, manifestMetadata, manifestSummary, ...rest, }; return ( @@ -56,7 +58,6 @@ export function ManifestInfo({ } ManifestInfo.propTypes = { - id: PropTypes.string.isRequired, manifestDescription: PropTypes.string, manifestLabel: PropTypes.string, manifestMetadata: PropTypes.array, // eslint-disable-line react/forbid-prop-types diff --git a/src/components/ManifestRelatedLinks.js b/src/components/ManifestRelatedLinks.js index 2169b68c1..80d4a09a1 100644 --- a/src/components/ManifestRelatedLinks.js +++ b/src/components/ManifestRelatedLinks.js @@ -1,3 +1,4 @@ +import { useId } from 'react'; import PropTypes from 'prop-types'; import { styled } from '@mui/material/styles'; import Typography from '@mui/material/Typography'; @@ -20,7 +21,6 @@ const StyledDl = styled('dl')(({ theme }) => ({ */ export function ManifestRelatedLinks({ homepage = null, - id, manifestUrl = null, related = null, renderings = null, @@ -28,18 +28,22 @@ export function ManifestRelatedLinks({ ...rest }) { const { t } = useTranslation(); + const id = useId(); + const titleId = useId(); + const pluginProps = { - homepage, id, manifestUrl, related, renderings, seeAlso, t, ...rest, + homepage, manifestUrl, related, renderings, seeAlso, t, ...rest, }; return ( @@ -129,7 +133,6 @@ ManifestRelatedLinks.propTypes = { label: PropTypes.string, value: PropTypes.string, })), - id: PropTypes.string.isRequired, manifestUrl: PropTypes.string, related: PropTypes.arrayOf(PropTypes.shape({ format: PropTypes.string, diff --git a/src/components/SearchHit.js b/src/components/SearchHit.js index c656f4d14..de79d2126 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 3134fa745..451cf2bba 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 59953f227..2b30297c4 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 && (