Dialog
This is an accessible modal pattern with a trigger part, a portal part, an overlay part, and a content part. A dialog can contain a second dialog. In a stack of dialogs, only the top dialog obeys the global close interactions.
Anatomy
All of the parts are in Dialog.Root. Dialog.Trigger opens the dialog. The modal layers, Dialog.Overlay and Dialog.Content, are in Dialog.Portal. The children snippet of the root receives the state functions: close, open, toggle, and isOpen.
<script>
import { Dialog } from '@human-kit/ui';
</script>
<Dialog.Root>
{#snippet children({ close })}
<Dialog.Trigger>Open</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Overlay />
<Dialog.Content>...</Dialog.Content>
</Dialog.Portal>
{/snippet}
</Dialog.Root>Controlled state
Bind open on Dialog.Root to control the dialog from your own code. Then a trigger is optional. Use defaultOpen when the component controls the state. The onOpenChange prop reports each change.
Nested dialogs
Put a Dialog.Root in the content of a different dialog to make a stack. The component controls the stack. Each overlay and each panel gets a higher z-index. The Escape key and a click outside close only the top dialog.
Usage guidelines
- Put all of the dialog parts in
Dialog.Root. - Use
Dialog.Triggeras the button that opens the dialog. - Put the modal layers in
Dialog.Portal. - Use
Dialog.OverlayandDialog.Contenttogether for the usual modal behavior. - Use nested
Dialog.Rootparts when you need a stack. The component controls which dialog is on top. - Use
shouldCloseOnEscapeandshouldCloseOnInteractOutsideonDialog.Contentto stop the default close interactions.
Accessibility
- While the dialog is open,
Dialog.Contenthasrole="dialog"witharia-modal="true". - The focus stays in the open dialog. Assistive technology does not read the content outside the dialog.
- While a modal dialog is open, the body does not scroll.
- The
Escapekey closes the top dialog. When a dialog closes, the focus goes back to the trigger.
API reference
Root
The container with the state. It holds the open state and the reference to the trigger. It gives the state functions ({ close, open, toggle, isOpen }) to its children snippet.
* required. Native HTML attributes of the underlying element are also accepted.
Trigger
The button that registers itself as the trigger of the dialog. A click opens and closes the dialog.
* required. Native HTML attributes of the underlying element are also accepted.
Portal
The portal that puts the dialog layers in the document body. They are there only while the dialog is open, and they stay until the exit animation is complete.
* required. Native HTML attributes of the underlying element are also accepted.
Overlay
The backdrop behind the dialog content. Its z-index comes from the position of the dialog in the stack.
* required. Native HTML attributes of the underlying element are also accepted.
Content
The modal panel, with role="dialog" and aria-modal. It keeps the focus inside, it obeys an interaction outside it, it stops the page scroll, and it hides the outside content from assistive technology. In a stack, only the top dialog obeys the close interactions.
* required. Native HTML attributes of the underlying element are also accepted.
Title
* required. Native HTML attributes of the underlying element are also accepted.
Description
* required. Native HTML attributes of the underlying element are also accepted.
Close
* required. Native HTML attributes of the underlying element are also accepted.