Dialog

Modal dialog on Radix Dialog: a titled panel with body and footer slots, focus trapping, Escape and backdrop dismiss, and entry/exit animation.

// Radix — @radix-ui/react-dialog
import { CloseButton, Dialog, DialogClose } from "@shavin/ui";

Opened from a trigger

The simplest form: Dialog keeps its own open state. DialogClose closes it from a footer button.

The simplest form: Dialog keeps its own open state. DialogClose closes it from a footer button.
import { Dialog, DialogClose, Button } from "@shavin/ui";

<Dialog
  trigger={<Button>Export data</Button>}
  title="Export data"
  description="Download every project as a CSV file."
  footer={
    <DialogClose asChild>
      <Button>Export</Button>
    </DialogClose>
  }
/>

Controlled

Hold the open state yourself when something else opens or closes the dialog. Compose any content in the body: forms, Tabs, Grid.

Hold the open state yourself when something else opens or closes the dialog. Compose any content in the body: forms, Tabs, Grid.
const [open, setOpen] = useState(false);

<Button variant="soft" onClick={() => setOpen(true)}>Rename project</Button>
<Dialog
  open={open}
  onOpenChange={setOpen}
  size="md"
  title="Rename project"
  footer={
    <>
      <Button variant="ghost" onClick={() => setOpen(false)}>Cancel</Button>
      <Button onClick={() => setOpen(false)}>Save</Button>
    </>
  }
>
  <TextField label="Project name" defaultValue="Website redesign" />
</Dialog>

Sizes

Component Source
<Dialog open={open} onOpenChange={setOpen} size="sm" title="Small dialog">…</Dialog>
<Dialog open={open} onOpenChange={setOpen} size="md" title="Medium dialog">…</Dialog>
<Dialog open={open} onOpenChange={setOpen} size="lg" title="Large dialog">…</Dialog>

Non-dismissible

Component Source
<Dialog
  open={open}
  onOpenChange={setOpen}
  dismissible={false}
  title="Try clicking outside"
  footer={<Button onClick={() => setOpen(false)}>Close</Button>}
>
  Clicking the backdrop won't close this one. Escape and the close button still work.
</Dialog>

Props

PropTypeDefaultDescription
title*ReactNode—Heading shown at the top of the dialog (also its accessible name).
descriptionReactNode—Supporting line under the title (also its accessible description).
subtitleReactNode—@deprecated Use `description`.
openboolean—Controlled open state. Pair with `onOpenChange`.
defaultOpenboolean—Initial open state when uncontrolled. Default: closed when `trigger` is set, otherwise open.
onOpenChange(open: boolean) => void—Called whenever the dialog asks to open or close (trigger, Escape, backdrop, close button).
triggerReactNode—Element that opens the dialog, e.g. `<Button>Edit profile</Button>`.
onClose() => void—Called after the close animation finishes. Use it to unmount a dialog you render conditionally.
childrenReactNode—Dialog body.
footerReactNode—Footer actions, right-aligned. Wrap a button in `<DialogClose asChild>` to close from it.
dismissiblebooleantrueWhether clicking the backdrop closes the dialog. Default true.
layout"default" | "centered" | "bare"—Header treatment. `default`: left-aligned title row with a close button. `centered`: centred title and description, no header row (for confirmations, success and invite moments). `bare`: no header row; the title and description sit above the content with no chrome (for forms and pickers that lead with their content).
dividedboolean—Hairlines between header, body and footer. Default: on for `default`, off for `centered` and `bare`.
footerAlign"start" | "center" | "end" | "between" | "stretch"`end`Footer button alignment. `stretch` makes buttons share the row (good on mobile). Default `end`.
size"sm" | "md" | "lg""sm"—

* required

Keyboard

KeyAction
TabMoves focus to the next focusable element (trapped within the dialog).
Shift + TabMoves focus to the previous focusable element.
EscapeCloses the dialog and returns focus to the trigger.

Data attributes

AttributeValues
[data-state]"open" | "closed" — on the overlay and content while mounted.
Configure Theme
Theme
Accent Color
Custom
Gray Family
Appearance
Radius
Scaling
Panel Style
Heading Font
Body Font