Skip to content
uiify

Dialog

Modal dialog built on the native dialog element.

Browsers
Chrome 123+, Firefox 121+, Safari 17.5+
Tier
0
Bundle compressed
940 B
Forced layout budget
0 ms
Axe budget
0
SSR compatible
Yes
Published contract
Test harness

Playground

Settings

Update your profile preferences.

Changes apply to your whole workspace.

Settings

Update your profile preferences.

Changes apply to your whole workspace.

import { Dialog } from "@gunkin/uiify";

export default function Example() {
  return (
    <Dialog
      id="settings-dialog"
      trigger="Open settings"
      title="Settings"
      description="Update your profile preferences."
    />
  );
}

API

Dialog

PropTypeDefaultDescription
idstring——
triggerReactNode——
titleReactNode——
descriptionReactNode——
childrenReactNode——
closeLabelstring—Accessible name of the header close icon.
labelsPartial<DialogLabels>——
slotPropsDialogSlotProps—Native props for the elements created by this convenience component.
sizeDialogSize—Width step; `full` fills the viewport. Default `md`.
alignDialogAlign—Vertical position on tablet and desktop; phones get a bottom sheet unless `size` is `full`. Default `center`.
dismissDialogDismiss—Native `closedby`: `any` also closes on a backdrop tap, `closerequest` on Escape only, `none` only through your own controls. Default `any`. Engines without `closedby` (Safari) ignore it: Escape still closes the dialog there, and `UIEnhance` honours it only for its own backdrop tap (`any` only) and sheet swipe (off for `none`).
backdropDialogBackdrop—Backdrop treatment. Default `opaque`.

DialogBody

PropTypeDefaultDescription

DialogClose

PropTypeDefaultDescription
childrenReactNode——
targetstring—`id` of the `DialogContent` this button closes.
commandstring——
commandforstring——
asElementType & ("button" | ComponentType<any>)—`"button"` (default) or a component that forwards props and ref to a native <button>.
rendernever——

DialogContent

PropTypeDefaultDescription
childrenReactNode——
idstring—Unique id supplied by the consumer; referenced by trigger and close `target`.
sizeDialogSize—Width step; `full` fills the viewport. Default `md`.
alignDialogAlign—Vertical position on tablet and desktop; phones get a bottom sheet unless `size` is `full`. Default `center`.
dismissDialogDismiss—Native `closedby`: `any` also closes on a backdrop tap, `closerequest` on Escape only, `none` only through your own controls. Default `any`. Engines without `closedby` (Safari) ignore it: Escape still closes the dialog there, and `UIEnhance` honours it only for its own backdrop tap (`any` only) and sheet swipe (off for `none`).
backdropDialogBackdrop—Backdrop treatment. Default `opaque`.

DialogDescription

PropTypeDefaultDescription

DialogFooter

PropTypeDefaultDescription

DialogGrabber

PropTypeDefaultDescription

DialogHeader

PropTypeDefaultDescription

DialogTitle

PropTypeDefaultDescription

DialogTrigger

PropTypeDefaultDescription
childrenReactNode——
targetstring—`id` of the `DialogContent` this button opens; the browser resolves it at click time.
commandstring——
commandforstring——
asElementType & ("button" | ComponentType<any>)—`"button"` (default) or a component that forwards props and ref to a native <button>.
rendernever——

Keyboard

KeyAction
EscapeClose (only the topmost modal when nested)
TabCycle focus inside modal
Shift+TabReverse tab order

Accessibility

Native <dialog> opened by a command="show-modal" invoker before any JavaScript runs. The browser owns modality, focus containment, Escape and focus return; closing uses request-close so onCancel can veto. The header close icon is always present. On phones the modal is a bottom sheet; swiping it down and tapping the backdrop are shortcuts, never the only way out.

Styling hooks

  • data-size="sm|lg|full"
  • data-align="start"
  • data-backdrop="blur|none"
  • --uiify-trigger-openinside .uiify-dialog-root
  • --uiify-dialog-inline-sizedialog width