Dialog
A modal window for focused tasks, with focus trapping and Esc to close.
A modal window for focused tasks, with focus trapping and Esc to close.
<Dialog>
<DialogTrigger asChild>
<Button variant="outline">Open dialog</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Delete project?</DialogTitle>
<DialogDescription>This removes the project and its history. It can't be undone.</DialogDescription>
</DialogHeader>
<DialogFooter>
<DialogClose asChild><Button variant="outline">Cancel</Button></DialogClose>
<DialogClose asChild><Button variant="danger">Delete</Button></DialogClose>
</DialogFooter>
</DialogContent>
</Dialog>The same component at all four levels. Pick the one that fits your project; they share tokens, so they mix.
npm i junco @junco/tailwindimport { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, DialogClose } from "junco";
<Dialog>
<DialogTrigger asChild>
<Button>Edit profile</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Edit profile</DialogTitle>
<DialogDescription>Changes show up for your whole team.</DialogDescription>
</DialogHeader>
{/* form fields */}
<DialogFooter>
<DialogClose asChild><Button variant="outline">Cancel</Button></DialogClose>
<Button>Save</Button>
</DialogFooter>
</DialogContent>
</Dialog>Control open state to close the dialog after a successful submit.
Every dialog needs a title for screen readers. When the design has no heading, hide it visually.
Dialog#The root. Uncontrolled by default.
opendefaultOpenonOpenChangemodal| Prop | Type | Default |
|---|---|---|
openControlled open state. | boolean | – |
defaultOpenInitial open state when uncontrolled. | boolean | false |
onOpenChangeCalled when the dialog opens or closes. | (open: boolean) => void | – |
modalBlocks the rest of the page while open. | boolean | true |
DialogContent#The window, rendered in a portal with the scrim behind it.
sizeshowClosecloseLabelclassNamesonEscapeKeyDown| Prop | Type | Default |
|---|---|---|
sizeMax width. full fills the viewport with a small margin. | "sm" | "md" | "lg" | "xl" | "full" | "md" |
showCloseShow the × button in the corner. | boolean | true |
closeLabelAccessible name for the × button. | string | "Close" |
classNamesClass overrides for each part. | { overlay?, content?, close? } | – |
onEscapeKeyDownCall event.preventDefault() to keep it open on Esc. | (event) => void | – |
DialogTitle#isHidden| Prop | Type | Default |
|---|---|---|
isHiddenVisually hidden, still read by screen readers. | boolean | false |
DialogTrigger / DialogClose#asChild| Prop | Type | Default |
|---|---|---|
asChildUse your own button (usually a Junco Button) as the trigger or close control. | boolean | false |
| Key | Action |
|---|---|
| Esc | Closes the dialog and returns focus to the trigger. |
| Tab | Moves focus to the next control inside the dialog; focus can't leave it. |
| ShiftTab | Moves focus back, wrapping inside the dialog. |