Guillermo Peralta Scura e4ff408f23
Accessible modals (#560)
Improve the accessibility of our modals (the color picker and the export dialog)

Implement a focus trap so that tapping through the controls inside them don't escape to outer elements, it also allows to close the modals with the "Escape" key.
2020-01-25 19:37:58 -03:00

52 lines
1.2 KiB
TypeScript

import "./Modal.css";
import React, { useEffect, useState } from "react";
import { createPortal } from "react-dom";
import { KEYS } from "../keys";
export function Modal(props: {
children: React.ReactNode;
maxWidth?: number;
onCloseRequest(): void;
labelledBy: string;
}) {
const modalRoot = useBodyRoot();
const handleKeydown = (e: React.KeyboardEvent) => {
if (e.key === KEYS.ESCAPE) {
e.nativeEvent.stopImmediatePropagation();
props.onCloseRequest();
}
};
return createPortal(
<div
className="Modal"
role="dialog"
aria-modal="true"
onKeyDown={handleKeydown}
aria-labelledby={props.labelledBy}
>
<div className="Modal__background" onClick={props.onCloseRequest}></div>
<div className="Modal__content" style={{ maxWidth: props.maxWidth }}>
{props.children}
</div>
</div>,
modalRoot,
);
}
function useBodyRoot() {
function createDiv() {
const div = document.createElement("div");
document.body.appendChild(div);
return div;
}
const [div] = useState(createDiv);
useEffect(() => {
return () => {
document.body.removeChild(div);
};
}, [div]);
return div;
}