From 61779a6ca7ec101195cb12fb246e454f72d53d1d Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Fri, 28 Feb 2025 18:47:42 +0530 Subject: [PATCH] More aria taken from the basic example in https://mui.com/material-ui/react-menu/ --- .../gallery/components/viewer/FileViewer.tsx | 18 ++++++---- .../gallery/components/viewer/photoswipe.ts | 35 +++++++++++++++++-- 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/web/packages/gallery/components/viewer/FileViewer.tsx b/web/packages/gallery/components/viewer/FileViewer.tsx index d5952add20..ab1b385905 100644 --- a/web/packages/gallery/components/viewer/FileViewer.tsx +++ b/web/packages/gallery/components/viewer/FileViewer.tsx @@ -37,6 +37,9 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { fileInfoExifForFile } from "./data-source"; import { FileViewerPhotoSwipe, + moreButtonID, + moreMenuID, + resetMoreMenuButtonOnMenuClose, type FileViewerAnnotatedFile, type FileViewerFileAnnotation, type FileViewerPhotoSwipeDelegate, @@ -279,10 +282,12 @@ const FileViewer: React.FC = ({ [], ); - const handleMoreMenuClose = useCallback( - () => setMoreMenuAnchorEl(null), - [], - ); + const handleMoreMenuClose = useCallback(() => { + setMoreMenuAnchorEl((el) => { + resetMoreMenuButtonOnMenuClose(el); + return null; + }); + }, []); const handleEditImage = useMemo(() => { return onSaveEditedImageCopy @@ -407,10 +412,9 @@ const FileViewer: React.FC = ({ open={!!moreMenuAnchorEl} onClose={handleMoreMenuClose} anchorEl={moreMenuAnchorEl} + id={moreMenuID} slotProps={{ - list: { - "aria-labelledby": moreMenuAnchorEl?.id, - }, + list: { "aria-labelledby": moreButtonID }, }} > Test diff --git a/web/packages/gallery/components/viewer/photoswipe.ts b/web/packages/gallery/components/viewer/photoswipe.ts index 75a1b15c7f..4fe76277d8 100644 --- a/web/packages/gallery/components/viewer/photoswipe.ts +++ b/web/packages/gallery/components/viewer/photoswipe.ts @@ -165,6 +165,21 @@ export interface FileViewerAnnotatedFile { annotation: FileViewerFileAnnotation; } +/** + * The ID that is used by the "more" action button (if one is being displayed). + * + * @see also {@link moreMenuID}. + */ +export const moreButtonID = "ente-pswp-more-button"; + +/** + * The ID this is expected to be used by the more menu that is shown in response + * to the more action button being activated. + * + * @see also {@link moreButtonID}. + */ +export const moreMenuID = "ente-pswp-more-menu"; + /** * A wrapper over {@link PhotoSwipe} to tailor its interface for use by our file * viewer. @@ -616,9 +631,16 @@ export class FileViewerPhotoSwipe { order: 17, isButton: true, html: createPSRegisterElementIconHTML("more"), - onClick: (e) => onMore(currentAnnotatedFile(), e.target), onInit: (buttonElement) => { - buttonElement.id = "ente-pswp-show-more"; + buttonElement.setAttribute("id", moreButtonID); + buttonElement.setAttribute("aria-haspopup", "true"); + }, + onClick: (e) => { + const buttonElement = e.target; + // See also: `resetMoreMenuButtonOnMenuClose`. + buttonElement.setAttribute("aria-controls", moreMenuID); + buttonElement.setAttribute("aria-expanded", true); + onMore(currentAnnotatedFile(), buttonElement); }, }); }); @@ -740,3 +762,12 @@ const createElementFromHTMLString = (htmlString: string) => { template.innerHTML = htmlString.trim(); return template.content.firstChild; }; + +/** + * Update the ARIA attributes for the button that controls the more menu when + * the menu is closed. + */ +export const resetMoreMenuButtonOnMenuClose = (buttonElement: HTMLElement) => { + buttonElement.removeAttribute("aria-controls"); + buttonElement.removeAttribute("aria-expanded"); +};