Dialog
import { Dialog } from '@yarcl/react';<Dialog trigger={<Button>Invite teammate</Button>} title="Invite a teammate" description="They'll get an email with a link to join." footer={<Button>Send invite</Button>}> <Field label="Email"><Input type="email" /></Field></Dialog>Controlled
Section titled “Controlled”const [open, setOpen] = useState(false);
<Dialog open={open} onOpenChange={setOpen} title="Delete project?" size="sm" footer={…} />size sets the width and accepts the keys of your config’s modalSizes. The default is defaults.modalSize. The height always follows the content, up to the height of the screen, and the body scrolls when it doesn’t fit.
<Dialog size="lg" title="Edit invoice">…</Dialog>There’s no free-form width: every dialog width in your app comes from the config.
Behavior
Section titled “Behavior”Built on <dialog> with showModal(), so the browser handles the hard parts:
- focus moves into the dialog and is trapped there
- the rest of the page is inert and doesn’t scroll
- Esc, the close button and a backdrop click close it (
closeOnBackdrop={false}to disable the last one) - focus returns to the element that opened it
title is the dialog’s accessible name; description its accessible description.
Select, Combobox, Menu, Popover, Tooltip and HoverCard work inside the dialog. Their panels stay in the modal and can extend beyond its scrolling body. When a popup is open, Esc dismisses it first; another press closes the dialog.
Nested dialogs
Section titled “Nested dialogs”A dialog can open another dialog. Only the topmost one shows a backdrop, so the page and the dialogs below are dimmed once, not once per dialog. Esc closes only the top dialog, and the one below gets its backdrop back.
Dialogs center themselves with margin: auto rather than relying on the browser’s default, so CSS resets like * { margin: 0 } don’t push them into the corner.
Part styles
Section titled “Part styles”Style the native root and its header, body and footer through component parts. They expose data-part="root", "header", "body" and "footer". Configuring a slot does not add missing content sections.
| Prop | Type | Default | Description |
|---|---|---|---|
title required | ReactNode | Heading of the dialog. Also its accessible name. | |
children | ReactNode | Body content. Scrolls when it doesn't fit. | |
closeLabel | string | config.labels.close | Accessible name of the close button. |
closeOnBackdrop | boolean | true | Closes when the backdrop is clicked. |
defaultOpen | boolean | false | Initial open state when uncontrolled. |
description | ReactNode | Supporting text below the title. Also its accessible description. | |
footer | ReactNode | Actions shown at the bottom, e.g. Cancel and Confirm buttons. | |
onOpenChange | (open: boolean) => void | Called when the dialog opens or closes, including by Esc, the close button or a backdrop click. | |
open | boolean | Controlled open state. | |
radius | Radiusconfig | config.defaults.radius | Corner radius, from the radii config. |
size | ModalSizeconfig | config.defaults.modalSize (Drawer: its component default, `sm` in the library defaults) | Width, from the modalSizes config. Height follows the content, up to the viewport. |
trigger | ReactElement<{ onClick?: (event: MouseEvent) => void }, string | JSXElementConstructor<any>> | An element that opens the dialog when clicked, e.g. a Button. Optional when controlled. |