fix: focus on last active element when dialog closes (#3447)
* fix: focus on last active element when dialog closes * useState instead of ref
This commit is contained in:
parent
793b69e592
commit
c0047269c1
@ -1,5 +1,5 @@
|
|||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import React, { useEffect } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { useCallbackRefState } from "../hooks/useCallbackRefState";
|
import { useCallbackRefState } from "../hooks/useCallbackRefState";
|
||||||
import { t } from "../i18n";
|
import { t } from "../i18n";
|
||||||
import { useIsMobile } from "../components/App";
|
import { useIsMobile } from "../components/App";
|
||||||
@ -20,6 +20,8 @@ export const Dialog = (props: {
|
|||||||
theme?: AppState["theme"];
|
theme?: AppState["theme"];
|
||||||
}) => {
|
}) => {
|
||||||
const [islandNode, setIslandNode] = useCallbackRefState<HTMLDivElement>();
|
const [islandNode, setIslandNode] = useCallbackRefState<HTMLDivElement>();
|
||||||
|
const [lastActiveElement] = useState(document.activeElement);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!islandNode) {
|
if (!islandNode) {
|
||||||
return;
|
return;
|
||||||
@ -66,12 +68,17 @@ export const Dialog = (props: {
|
|||||||
return focusableElements ? Array.from(focusableElements) : [];
|
return focusableElements ? Array.from(focusableElements) : [];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onClose = () => {
|
||||||
|
(lastActiveElement as HTMLElement).focus();
|
||||||
|
props.onCloseRequest();
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
className={clsx("Dialog", props.className)}
|
className={clsx("Dialog", props.className)}
|
||||||
labelledBy="dialog-title"
|
labelledBy="dialog-title"
|
||||||
maxWidth={props.small ? 550 : 800}
|
maxWidth={props.small ? 550 : 800}
|
||||||
onCloseRequest={props.onCloseRequest}
|
onCloseRequest={onClose}
|
||||||
theme={props.theme}
|
theme={props.theme}
|
||||||
>
|
>
|
||||||
<Island ref={setIslandNode}>
|
<Island ref={setIslandNode}>
|
||||||
@ -79,7 +86,7 @@ export const Dialog = (props: {
|
|||||||
<span className="Dialog__titleContent">{props.title}</span>
|
<span className="Dialog__titleContent">{props.title}</span>
|
||||||
<button
|
<button
|
||||||
className="Modal__close"
|
className="Modal__close"
|
||||||
onClick={props.onCloseRequest}
|
onClick={onClose}
|
||||||
aria-label={t("buttons.close")}
|
aria-label={t("buttons.close")}
|
||||||
>
|
>
|
||||||
{useIsMobile() ? back : close}
|
{useIsMobile() ? back : close}
|
||||||
|
@ -2,6 +2,7 @@ import React, { useState } from "react";
|
|||||||
import { t } from "../i18n";
|
import { t } from "../i18n";
|
||||||
|
|
||||||
import { Dialog } from "./Dialog";
|
import { Dialog } from "./Dialog";
|
||||||
|
import { useExcalidrawContainer } from "./App";
|
||||||
|
|
||||||
export const ErrorDialog = ({
|
export const ErrorDialog = ({
|
||||||
message,
|
message,
|
||||||
@ -11,6 +12,7 @@ export const ErrorDialog = ({
|
|||||||
onClose?: () => void;
|
onClose?: () => void;
|
||||||
}) => {
|
}) => {
|
||||||
const [modalIsShown, setModalIsShown] = useState(!!message);
|
const [modalIsShown, setModalIsShown] = useState(!!message);
|
||||||
|
const excalidrawContainer = useExcalidrawContainer();
|
||||||
|
|
||||||
const handleClose = React.useCallback(() => {
|
const handleClose = React.useCallback(() => {
|
||||||
setModalIsShown(false);
|
setModalIsShown(false);
|
||||||
@ -18,8 +20,9 @@ export const ErrorDialog = ({
|
|||||||
if (onClose) {
|
if (onClose) {
|
||||||
onClose();
|
onClose();
|
||||||
}
|
}
|
||||||
document.querySelector<HTMLElement>(".excalidraw-container")?.focus();
|
// TODO: Fix the A11y issues so this is never needed since we should always focus on last active element
|
||||||
}, [onClose]);
|
excalidrawContainer?.focus();
|
||||||
|
}, [onClose, excalidrawContainer]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -244,11 +244,9 @@ export const ExportDialog = ({
|
|||||||
onExportToBackend?: ExportCB;
|
onExportToBackend?: ExportCB;
|
||||||
}) => {
|
}) => {
|
||||||
const [modalIsShown, setModalIsShown] = useState(false);
|
const [modalIsShown, setModalIsShown] = useState(false);
|
||||||
const triggerButton = useRef<HTMLButtonElement>(null);
|
|
||||||
|
|
||||||
const handleClose = React.useCallback(() => {
|
const handleClose = React.useCallback(() => {
|
||||||
setModalIsShown(false);
|
setModalIsShown(false);
|
||||||
triggerButton.current?.focus();
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -263,7 +261,6 @@ export const ExportDialog = ({
|
|||||||
aria-label={t("buttons.export")}
|
aria-label={t("buttons.export")}
|
||||||
showAriaLabel={useIsMobile()}
|
showAriaLabel={useIsMobile()}
|
||||||
title={t("buttons.export")}
|
title={t("buttons.export")}
|
||||||
ref={triggerButton}
|
|
||||||
/>
|
/>
|
||||||
{modalIsShown && (
|
{modalIsShown && (
|
||||||
<Dialog onCloseRequest={handleClose} title={t("buttons.export")}>
|
<Dialog onCloseRequest={handleClose} title={t("buttons.export")}>
|
||||||
|
@ -671,10 +671,6 @@ const LayerUI = ({
|
|||||||
{appState.showHelpDialog && (
|
{appState.showHelpDialog && (
|
||||||
<HelpDialog
|
<HelpDialog
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
const helpIcon = document.querySelector(
|
|
||||||
".help-icon",
|
|
||||||
)! as HTMLElement;
|
|
||||||
helpIcon.focus();
|
|
||||||
setAppState({ showHelpDialog: false });
|
setAppState({ showHelpDialog: false });
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -591,8 +591,6 @@ class CollabWrapper extends PureComponent<Props, CollabState> {
|
|||||||
|
|
||||||
handleClose = () => {
|
handleClose = () => {
|
||||||
this.setState({ modalIsShown: false });
|
this.setState({ modalIsShown: false });
|
||||||
const collabIcon = document.querySelector(".CollabButton") as HTMLElement;
|
|
||||||
collabIcon.focus();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onUsernameChange = (username: string) => {
|
onUsernameChange = (username: string) => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user