Skip to content

Commit d71c120

Browse files
committed
fix(a11y): focus the AttachmentSelector button after closing dialog
1 parent 1f3d4e3 commit d71c120

2 files changed

Lines changed: 19 additions & 3 deletions

File tree

src/components/MessageComposer/AttachmentSelector/AttachmentSelector.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ export const AttachmentSelector = ({
326326

327327
const [modalContentAction, setModalContentActionAction] =
328328
useState<AttachmentSelectorAction>();
329+
const shouldRestoreFocusToTriggerRef = useRef(false);
329330
const openModalForAction = useCallback(
330331
(actionType: AttachmentSelectorAction['type']) => {
331332
const action = actions.find((a) => a.type === actionType);
@@ -336,13 +337,24 @@ export const AttachmentSelector = ({
336337
);
337338

338339
const closeModal = useCallback(() => {
340+
shouldRestoreFocusToTriggerRef.current = true;
339341
setModalContentActionAction(undefined);
340-
menuButtonRef.current?.focus();
341342
}, []);
342343

343344
const [fileInput, setFileInput] = useState<HTMLInputElement | null>(null);
344345
const menuButtonRef = useRef<HTMLButtonElement>(null);
345346

347+
useEffect(() => {
348+
if (modalContentAction || !shouldRestoreFocusToTriggerRef.current) return;
349+
350+
const frame = requestAnimationFrame(() => {
351+
menuButtonRef.current?.focus();
352+
shouldRestoreFocusToTriggerRef.current = false;
353+
});
354+
355+
return () => cancelAnimationFrame(frame);
356+
}, [modalContentAction]);
357+
346358
const contextMenuItems = useMemo(
347359
() =>
348360
actions.map((action) => (

src/components/MessageComposer/__tests__/AttachmentSelector.test.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,9 @@ describe('AttachmentSelector', () => {
452452
await waitFor(() => {
453453
expect(screen.queryByTestId(POLL_CREATION_DIALOG_TEST_ID)).not.toBeInTheDocument();
454454
});
455-
expect(invokeButtonFocusSpy).toHaveBeenCalledTimes(1);
455+
await waitFor(() => {
456+
expect(invokeButtonFocusSpy).toHaveBeenCalledTimes(1);
457+
});
456458
});
457459

458460
it('opens share location dialog with description wired to initial close control', async () => {
@@ -493,7 +495,9 @@ describe('AttachmentSelector', () => {
493495
await waitFor(() => {
494496
expect(screen.queryByTestId('share-location-dialog')).not.toBeInTheDocument();
495497
});
496-
expect(invokeButtonFocusSpy).toHaveBeenCalledTimes(1);
498+
await waitFor(() => {
499+
expect(invokeButtonFocusSpy).toHaveBeenCalledTimes(1);
500+
});
497501
});
498502

499503
it('is closed if File menu button is clicked', async () => {

0 commit comments

Comments
 (0)