useModalLayer

useModalLayer(ref, open) puts a modal <dialog> of your own in Todae's modal stack, the list of modals Todae knows are open. Dialog and BottomSheet join it by themselves.

function YourDialog({ open, onClose, children }) {
	const ref = useRef<HTMLDialogElement>(null);
	useModalLayer(ref, open);
	useEffect(() => {
		if (open) ref.current?.showModal();
		else ref.current?.close();
	}, [open]);
	return (
		<dialog ref={ref} onClose={onClose}>
			{children}
		</dialog>
	);
}

The dialog joins once open is true and it is shown with showModal(), in either order, and stays until close(), also after open turns false. The hook reads ref each time the component that calls it renders, so render the <dialog> in that component. A modal <dialog> makes everything outside it inert, so Toast.Region moves its toasts into the modal in front, where they stay usable. Without this hook, toasts stay inert under your dialog.

Accessible composition

Todae handles: Membership in the modal stack, and nothing else. While your dialog is in the stack, Toast.Region moves its toasts inside it and useAnnouncer writes its messages to a live region inside it, so both stay reachable while the page behind is inert. The hook adds no attributes to the <dialog>.

You supply: The rest of an accessible modal, which Dialog would handle for you: showModal(), a name through aria-labelledby or aria-label, a first focus that makes sense, and a button that closes it. Escape closes a modal <dialog> by itself, so keep your open state in step with its close event, as the example does.

Watch for: A dialog opened with show() or the open attribute joins only when it carries aria-modal="true". Pass the same open your dialog uses: while it is false, the dialog does not join, even after showModal().

When to use

When: A modal <dialog> you open with showModal() yourself, on a page that shows toasts.

When not: Dialog or BottomSheet → they join by themselves. A dialog opened with show() → it is not modal, and toasts already sit above it.

Props

useModalLayer props
NameTypeDescription
ref RequiredRefObject<HTMLDialogElement | null>

The <dialog>. Render it in the component that calls the hook, which reads the ref each time that component renders.

open Requiredboolean

Whether the dialog may be shown. It joins once this is true and it is shown with showModal(), and stays until close().