Skip to content
GetUrUI

Dialog

New
.md

Accessible base modal with a featured icon, four widths and stacked phone actions; it springs in over a blurred scrim and turns into a drag-to-dismiss bottom sheet below 640px.

dialogmodalalert dialogconfirmsheetoverlayfocus trap

Installation

$npx shadcn@latest add @geturui/dialog
Download source (.zip)

Usage

usage.tsx
1import { Rocket } from "lucide-react";
2import { Button } from "@/components/ui/button";
3import { Dialog } from "@/components/ui/dialog";
4
5export function PublishDialog() {
6  return (
7    <Dialog
8      trigger={<Button>Publish</Button>}
9      icon={<Rocket />}
10      tone="volt"
11      title="Publish to production?"
12      description="Your site updates in about 40 seconds."
13      footer={({ close }) => (
14        <>
15          <Button variant="secondary" onClick={close}>Cancel</Button>
16          <Button onClick={close}>Publish</Button>
17        </>
18      )}
19    />
20  );
21}

Props

PropTypeDefaultDescription
title*ReactNode—Heading; labels the dialog.
descriptionReactNode—Supporting copy; describes the dialog.
childrenReactNode | ({ close }) => ReactNode—Body. Scrolls when tall.
footerReactNode | ({ close }) => ReactNode—Actions, primary last. Full-width and stacked with the primary on top on phones.
footerAsideReactNode | ({ close }) => ReactNode—Left side of the footer, e.g. a “Don’t ask again” checkbox.
icon / toneReactNode / "neutral" | "volt" | "success" | "warning" | "danger" | "ember"— / "neutral"Featured icon in a tinted tile. It pops in; the warning tone wobbles once.
layout"stacked" | "inline" | "centered""stacked"Icon above the text, beside it (from 640px) or centred.
size"sm" | "md" | "lg" | "xl""md"Max width 400 / 480 / 640 / 800 px.
role"dialog" | "alertdialog""dialog"Use alertdialog for interrupting confirmations.
closeOnEscape / closeOnScrim / showClosebooleantrueDismissal controls. With closeOnScrim off, a scrim click nudges the panel and the sheet can’t be dragged away.
initialFocusRefObject<HTMLElement>—Element focused on open. Otherwise [data-autofocus], then the first body control, then the footer.
sheetOnMobilebooleantrueBelow 640px present as a bottom sheet with a drag handle.
triggerReactElement—Element that opens the modal; it receives onClick, aria-haspopup and aria-expanded.
open / defaultOpen / onOpenChangeboolean / boolean / (open: boolean) => void—Controlled or uncontrolled open state.
useDialog()() => { close }—Close the dialog from any descendant.

Accessibility

  • role="dialog" or "alertdialog" with aria-modal, aria-labelledby (title) and aria-describedby (description).
  • Focus moves inside on open (initialFocus, [data-autofocus], first control), Tab cycles within the panel, focus that escapes is pulled back, and focus returns to the trigger on close.
  • Escape and scrim click close unless disabled; the page behind is scroll-locked without a layout shift.
  • Reduced motion swaps the spring, blur and sheet slide for a fade.

Related