Dialog
Accessible modal dialog built on Radix Dialog primitive with focus trapping, ESC key dismiss, and entry/exit transitions.
// Radix — @radix-ui/react-dialog
import { CloseButton, Dialog } from "@shavin/ui";Sizes
import { Dialog, Button } from "@shavin/ui";
{open && (
<Dialog
title="Small dialog"
subtitle="Radix-backed, cva-styled"
size="sm"
onClose={() => setOpen(false)}
footer={
<>
<Button variant="outline" onClick={() => setOpen(false)}>Cancel</Button>
<Button variant="solid" onClick={() => setOpen(false)}>Confirm</Button>
</>
}
>
Dialog body content goes here.
</Dialog>
)}Non-Dismissible (dismissible=false)
{open && (
<Dialog
title="Try clicking outside"
subtitle="dismissible={false}"
dismissible={false}
onClose={() => setOpen(false)}
footer={
<Button variant="solid" onClick={() => setOpen(false)}>Close</Button>
}
>
Clicking the backdrop won't close this one. Escape and the ✕ button still work.
</Dialog>
)}Props
| Prop | Type | Default |
|---|---|---|
| title* | string | — |
| subtitle | string | — |
| onClose* | () => void | — |
| children | ReactNode | — |
| footer | ReactNode | — |
| dismissible | boolean | — |
| size | "sm" | "md" | "lg" | "sm" |
* required
Keyboard
| Key | Action |
|---|---|
| Tab | Moves focus to the next focusable element (trapped within the dialog). |
| Shift + Tab | Moves focus to the previous focusable element. |
| Escape | Closes the dialog and returns focus to the trigger. |
Data attributes
| Attribute | Values |
|---|---|
| [data-state] | "open" | "closed" — on the overlay and content while mounted. |