Dialog
The Mosaic Dialog — an opinionated wrapper around the headless @clerk/headless dialog
primitives, composed with Mosaic slot recipes. It flattens the required nesting (Root, Portal,
Backdrop, Viewport, Popup) into a single component and exposes a close callback through a
render-prop children pattern.
Playground
Props
| Prop | Type | Default | Value |
|---|---|---|---|
| size | 'md' | 'lg' | 'md' | |
| trigger | (props: HTMLAttributes<HTMLElement>) => ReactElement | — | — |
| children | ReactNode | ((ctx: { close: () => void }) => ReactNode) | — | — |
| open | boolean | — | — |
| defaultOpen | boolean | false | — |
| onOpenChange | (open: boolean) => void | — | — |
| modal | boolean | true | — |
| sx | StyleRule | (theme) => StyleRule | — | — |
Usage
import { Button } from '@clerk/ui/mosaic/components/button';
import { Dialog } from '@clerk/ui/mosaic/components/dialog';
<Dialog trigger={props => <Button {...props}>Open dialog</Button>}>
{({ close }) => (
<>
<Dialog.Title>Confirm action</Dialog.Title>
<Dialog.Description>Are you sure you want to proceed?</Dialog.Description>
<Button onClick={close}>Cancel</Button>
</>
)}
</Dialog>The trigger render prop receives the interaction props (ARIA attributes, click handler) from
Floating UI and should spread them onto whatever element opens the dialog.
children can also be a plain ReactNode when no programmatic close is needed — the dialog
can always be dismissed via Escape or clicking the backdrop:
<Dialog trigger={props => <Button {...props}>Open</Button>}>
<Dialog.Title>Info</Dialog.Title>
<Dialog.Description>Nothing to confirm here.</Dialog.Description>
</Dialog>Controlled
const [open, setOpen] = useState(false);
<Dialog
open={open}
onOpenChange={setOpen}
trigger={props => <Button {...props}>Open</Button>}
>
{({ close }) => (
<>
<Dialog.Title>Confirm</Dialog.Title>
<Button onClick={close}>Cancel</Button>
</>
)}
</Dialog>Sub-parts
| Part | Slot | Description |
|---|---|---|
Dialog.Title | dialog-title | Heading; wired to the popup's aria-labelledby |
Dialog.Description | dialog-description | Description; wired to the popup's aria-describedby |
Styled slots
The Mosaic dialog exposes the following slots that can be styled via appearance.elements:
| Slot | Component | Description |
|---|---|---|
dialog-backdrop | Backdrop | Themed overlay behind the dialog |
dialog-viewport | Viewport | Fixed centering container; owns scroll lock |
dialog-popup | Popup | The dialog surface (role="dialog", focus-trapped) |
Styling
Override per slot through appearance.elements — e.g. { 'dialog-popup': { borderRadius: 24 } }.
State attributes from the headless layer are also available for CSS targeting:
| Attribute | Applies To | Description |
|---|---|---|
data-open | Trigger, Backdrop, Viewport, Popup | Present when the dialog is open |
data-closed | Trigger, Backdrop, Viewport, Popup | Present when closed (during exit) |
data-starting-style | Backdrop, Viewport, Popup | Present on the entering frame |
data-ending-style | Backdrop, Viewport, Popup | Present during the exit animation |