Dialog
A window over the page that holds the reader's attention until it closes, with focus kept inside.
A dialog interrupts: it asks for a decision or a short task, such as renaming an item, before the reader returns to the page. The page behind it cannot be used while it is open. For a choice that cannot be undone, use ConfirmActionDialog; for content the reader consults beside the page, use a sheet or a popover.
// apps/docs/examples/ui/dialog-basic.tsx'use client';
import {Button} from '@workspace/active-ui/components/primitives/button';import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger,} from '@workspace/active-ui/components/primitives/dialog';import { Field, FieldLabel,} from '@workspace/active-ui/components/primitives/field';import {Input} from '@workspace/active-ui/components/primitives/input';
/** * A trigger, a title and description, content, and a footer. The close * button at the top right has no visible text, so `closeLabel` gives it its * accessible name; the package does not supply one. */export default function DialogBasic() { return ( <Dialog> <DialogTrigger render={<Button variant="outline" />}> Rename scheme </DialogTrigger> <DialogContent closeLabel="Close"> <DialogHeader> <DialogTitle>Rename scheme</DialogTitle> <DialogDescription> The new name appears everywhere the scheme is listed. </DialogDescription> </DialogHeader> <Field> <FieldLabel htmlFor="dialog-scheme-name">Name</FieldLabel> <Input id="dialog-scheme-name" defaultValue="Basic scheme 2026" /> </Field> <DialogFooter> <DialogClose render={<Button variant="outline" />}> Cancel </DialogClose> <DialogClose render={<Button />}>Save</DialogClose> </DialogFooter> </DialogContent> </Dialog> );}Usage#
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger,} from '@workspace/active-ui/components/primitives/dialog';
<Dialog> <DialogTrigger render={<Button variant="outline" />}>Open</DialogTrigger> <DialogContent closeLabel="Close"> <DialogHeader> <DialogTitle>Title</DialogTitle> <DialogDescription>What this dialog is for.</DialogDescription> </DialogHeader> </DialogContent></Dialog>;Anatomy#
Dialog: the state. Uncontrolled by default; controlled withopenandon.Open Change Dialog: the element that opens it.Trigger rendermakes your own button the trigger.Dialog: the window, with the overlay behind it and a close button in the corner.Content DialogwithHeader DialogandTitle Dialog: the title names the dialog for assistive technology; the description is read with it.Description Dialog: the actions.Footer Dialogcloses the dialog from any element.Close
Controlled, without the corner button#
// apps/docs/examples/ui/dialog-controlled.tsx'use client';
import {useState} from 'react';
import {Button} from '@workspace/active-ui/components/primitives/button';import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle,} from '@workspace/active-ui/components/primitives/dialog';
/** * Open state owned by the application: `open` and `onOpenChange`. Without * the corner button (`showCloseButton={false}`), the dialog still closes * with Escape, a click outside it, or the buttons in the footer. */export default function DialogControlled() { const [open, setOpen] = useState(false); const [last, setLast] = useState('none yet'); const close = (reason: string) => { setLast(reason); setOpen(false); }; return ( <div className="flex flex-wrap items-center gap-3"> <Button variant="outline" onClick={() => setOpen(true)}> Show the terms </Button> <span className="text-muted-foreground text-sm" role="status"> Last choice: {last} </span> <Dialog open={open} onOpenChange={(next) => { if (!next) close('dismissed'); }} > <DialogContent showCloseButton={false}> <DialogHeader> <DialogTitle>Terms of use</DialogTitle> <DialogDescription> Read the terms before you continue. </DialogDescription> </DialogHeader> <p> The service is provided as is. You keep the rights to the data you enter, and you can export it at any time. </p> <DialogFooter> <Button variant="outline" onClick={() => close('declined')}> Decline </Button> <Button onClick={() => close('accepted')}>Accept</Button> </DialogFooter> </DialogContent> </Dialog> </div> );}Pass open and on when your application decides when the dialog opens or must know
how it closed. show removes the corner button; Escape and a click outside
still close the dialog, and on reports it.
What your application provides#
close: the accessible name of the corner button. It is required while the button is shown, and not allowed withLabel show; the types enforce both.Close Button={false} The title and description, and the labels of the actions.
Any work the dialog's actions start, and the open state when the dialog is controlled.
Accessibility and keyboard#
Opening moves the focus into the dialog;
TabandShift+Tabstay inside it.Escapecloses it, and the focus returns to the element that opened it.The dialog is named by its title (
aria-) and described by its description.labelledby The page behind it is inert while it is open.
API#
Dialog#
Import from @workspace/
All props come from the Base UI part this component is built on.
Props
- Type
boolean
Whether the dialog is currently open.
- Type
boolean- Default
false
Whether the dialog is initially open.
To render a controlled dialog, use the open prop instead.
- Type
PayloadChild Render Function<โฆ> ReactNode
The content of the dialog. This can be a regular React node or a render function that receives the payload of the active trigger.
- Type
string | null
ID of the trigger that the dialog is associated with. This is useful in conjunction with the default prop to create an initially open dialog.
- Type
boolean- Default
false
Whether to prevent the dialog from closing on outside presses. For non-modal dialogs, this also prevents the dialog from closing when focus moves outside of it.
- Type
DialogHandle<unknown>
A handle to associate the dialog with a trigger. If specified, allows external triggers to control the dialog's open state. Can be created with the Dialog.createHandle() method.
- Type
"trap-focus" | boolean - Default
true
Determines if the dialog enters a modal state when open.
true: user interaction is limited to just the dialog: focus is trapped, document page scroll is locked, and pointer interactions on outside elements are disabled.false: user interaction with the rest of the document is allowed.'trap-: focus is trapped inside the dialog, but document page scroll is not locked and pointer interactions outside of it remain enabled.focus'
When modal is true or 'trap-, render <Dialog. inside <Dialog. so touch screen readers can escape the popup.
- Type
string | null
ID of the trigger that the dialog is associated with. This is useful in conjunction with the open prop to create a controlled dialog. There's no need to specify this prop when the dialog is uncontrolled (that is, when the open prop is not set).
- Type
RefObject<โฆ>
A ref to imperative actions.
unmount: Ends the closing phase of the dialog after an externally controlled closing animation finishes. CallpreventinUnmount On Close() onfirst, otherwise the dialog completes closing on its own. Whether it leaves the DOM is decided byOpen Change keepon the portal.Mounted close: Closes the dialog imperatively when called.
Events
Called by the component when something happens.
- Type
(open, eventDetails) => void
Event handler called when the dialog is opened or closed.
- Type
(open: boolean) => void
Event handler called after any animations complete when the dialog is opened or closed.
Takes only the props listed.
DialogContent#
Import from @workspace/
Props marked Base UI are behaviour of the Base UI part this component is built on.
Props
- Type
string
The accessible name of the close button in the corner, in the reader's language. Required while the button is shown; not allowed with show.
- Type
booleanRefObject<HTMLElement | null> (closeType) => โฆ
Determines the element to focus when the dialog is closed.
false: Do not move focus.true: Move focus based on the default behavior (trigger or previously focused element).Ref: Move focus to the ref element.Object function: Called with the interaction type (mouse,touch,pen, orkeyboard). Return an element to focus,trueto use the default behavior,nullto fall back to the default behavior, orfalse/undefinedto do nothing.
- Type
booleanRefObject<HTMLElement | null> (openType) => โฆ
Determines the element to focus when the dialog is opened. By default, focus moves to the first tabbable element inside the popup, except when the dialog is opened by touch โ then the popup itself is focused to avoid opening the virtual keyboard.
false: Do not move focus.true: Move focus based on the default behavior (first tabbable element or popup).Ref: Move focus to the ref element.Object function: Called with the interaction type (mouse,touch,pen, orkeyboard). Return an element to focus,trueto use the default behavior,nullto fall back to the default behavior, orfalse/undefinedto do nothing.
- Type
ComponentRender Fn<โฆ> ReactElement<โฆ>
Allows you to replace the component's HTML element with a different tag, or compose it with another component.
Accepts a React or a function that returns the element to render.
Other props, such as the standard attributes of the underlying element, className and ref, are passed through.
Other parts#
Dialog and Dialog take Base UI's render prop to use your own element.
Dialog can render its own close button with show and a visible
close.
DialogClose
All props come from the Base UI part this component is built on.
Props
- Type
ComponentRender Fn<โฆ> ReactElement<โฆ>
Allows you to replace the component's HTML element with a different tag, or compose it with another component.
Accepts a React or a function that returns the element to render.
Other props, such as the standard attributes of the underlying element, className and ref, are passed through.
DialogFooter
Props
Other props, such as the standard attributes of the underlying element, className and ref, are passed through.
DialogOverlay
All props come from the Base UI part this component is built on.
Props
- Type
boolean- Default
false
Whether the backdrop is forced to render even when nested.
- Type
ComponentRender Fn<โฆ> ReactElement<โฆ>
Allows you to replace the component's HTML element with a different tag, or compose it with another component.
Accepts a React or a function that returns the element to render.
Other props, such as the standard attributes of the underlying element, className and ref, are passed through.
DialogPortal
All props come from the Base UI part this component is built on.
Props
- Type
HTMLElementRefObject<โฆ> ShadowRoot null
A parent element to render the portal element into.
- Type
boolean- Default
false
Whether to keep the portal mounted in the DOM while the popup is hidden.
- Type
ComponentRender Fn<โฆ> ReactElement<โฆ>
Allows you to replace the component's HTML element with a different tag, or compose it with another component.
Accepts a React or a function that returns the element to render.
Other props, such as the standard attributes of the underlying element, className and ref, are passed through.
DialogTrigger
All props come from the Base UI part this component is built on.
Props
- Type
DialogHandle<unknown>
A handle to associate the trigger with a dialog. Can be created with the Dialog.createHandle() method.
- Type
string
ID of the trigger. In addition to being forwarded to the rendered element, it is also used to specify the active trigger for the dialog in controlled mode (with the DialogRoot trigger prop).
- Type
unknown
A payload to pass to the dialog when it is opened.
- Type
ComponentRender Fn<โฆ> ReactElement<โฆ>
Allows you to replace the component's HTML element with a different tag, or compose it with another component.
Accepts a React or a function that returns the element to render.
Other props, such as the standard attributes of the underlying element, className and ref, are passed through.
Parts that take only their elementโs attributes
Dialog: the attributes of its element, with className and ref, and Base UI'sDescription renderto use your own element.Dialog: the attributes of aHeader <div>, with className and ref.Dialog: the attributes of its element, with className and ref, and Base UI'sTitle renderto use your own element.
This page adapts the Dialog documentation of shadcn/ui (MIT licence) to this package; see Third-party notices.