Dialog
Modal with focus trap and overlay.
Usage
Use the child snippet on Dialog.Trigger and Dialog.Close to render real, accessible elements. The trigger spreads all
required ARIA and event props onto whatever element you pass.
Anatomy
Dialog.Content already portals to <body> and renders the overlay behind the panel — you do not need to add Dialog.Overlay separately. Focus is trapped inside the content while
open; pressing Esc closes.
See the Usage example above for a runnable demo.
Props
Dialog.Root
| Prop | Type | Default |
|---|---|---|
children bits-ui | Snippet<[]> | undefined | — |
onOpenChange bits-ui A callback that is called when the popover's open state changes. | OnChangeFn<boolean> | undefined | — |
onOpenChangeComplete bits-ui A callback called when the dialog finishes opening/closing animations. | OnChangeFn<boolean> | undefined | — |
open bits-ui The open state of the dialog. | boolean | undefined | — |
Dialog.Trigger
| Prop | Type | Default |
|---|---|---|
child bits-ui | Snippet<[{ props: Record<string, unknown>; }]> | undefined | — |
children bits-ui | Snippet<[]> | undefined | — |
id bits-ui | string | undefined | — |
ref bits-ui | HTMLElement | null | undefined | — |
Dialog.Content
| Prop | Type | Default |
|---|---|---|
class | string | — |
child bits-ui | Snippet<[DialogContentSnippetProps & { props: Record<string, unknown>; }]> | undefined | — |
children bits-ui | Snippet<[]> | undefined | — |
escapeKeydownBehavior bits-ui Escape behavior type. `close`: Closes the element immediately. `defer-otherwise-close`: Delegates the action to its parent component that has an escape keydown handler. If no parent is found, it closes the element. `defer-otherwise-ignore`: Delegates the action to the parent element. If no parent is found, nothing is done. `ignore`: Prevents the element from closing and also blocks the parent element from closing in response to an escape key press. | EscapeBehaviorType | undefined | `close` |
forceMount bits-ui Whether to force mount the component. | boolean | undefined | — |
id bits-ui | string | undefined | — |
interactOutsideBehavior bits-ui Interact outside behavior type. `close`: Closes the element immediately. `defer-otherwise-close`: Delegates the action to the parent element. If no parent is found, it closes the element. `defer-otherwise-ignore`: Delegates the action to the parent element. If no parent is found, nothing is done. `ignore`: Prevents the element from closing and also blocks the parent element from closing in response to an outside interaction. | InteractOutsideBehaviorType | undefined | `close` |
onCloseAutoFocus bits-ui Event handler called when auto-focusing on close. Can be prevented. | EventCallback | undefined | — |
onEscapeKeydown bits-ui Callback fired when escape is pressed. | ((e: KeyboardEvent) => void) | undefined | — |
onFocusOutside bits-ui Callback fired when focus leaves the dismissible layer. | ((event: FocusEvent) => void) | undefined | — |
onInteractOutside bits-ui Callback fired when an outside interaction event completes, which is either a `pointerup`, `mouseup`, or `touchend` event, depending on the user's input device. | InteractOutsideEventHandler | undefined | — |
onOpenAutoFocus bits-ui Event handler called when auto-focusing on open. Can be prevented. | EventCallback | undefined | — |
preventOverflowTextSelection bits-ui Passing `true` will prevent the overflow of text selection outside the element, provided the element is the top layer. | boolean | undefined | `true` |
preventScroll bits-ui Whether to prevent body scrolling when the content is open. | boolean | undefined | true |
ref bits-ui | HTMLElement | null | undefined | — |
restoreScrollDelay bits-ui The delay in milliseconds before the scrollbar is restored after closing the dialog. This is only applicable when using the `child` snippet for custom transitions and `preventScroll` is `true`. You should set this to a value greater than the transition duration to prevent content from shifting during the transition. | number | null | undefined | null |
trapFocus bits-ui Whether focus is trapped within the focus scope. | boolean | undefined | false |
Dialog.Title
| Prop | Type | Default |
|---|---|---|
class | string | — |
child bits-ui | Snippet<[{ props: Record<string, unknown>; }]> | undefined | — |
children bits-ui | Snippet<[]> | undefined | — |
id bits-ui | string | undefined | — |
level bits-ui The heading level of the dialog title. | 1 | 2 | 3 | 4 | 5 | 6 | undefined | — |
ref bits-ui | HTMLElement | null | undefined | — |
Dialog.Description
| Prop | Type | Default |
|---|---|---|
class | string | — |
child bits-ui | Snippet<[{ props: Record<string, unknown>; }]> | undefined | — |
children bits-ui | Snippet<[]> | undefined | — |
id bits-ui | string | undefined | — |
ref bits-ui | HTMLElement | null | undefined | — |
Dialog.Close
| Prop | Type | Default |
|---|---|---|
child bits-ui | Snippet<[{ props: Record<string, unknown>; }]> | undefined | — |
children bits-ui | Snippet<[]> | undefined | — |
id bits-ui | string | undefined | — |
ref bits-ui | HTMLElement | null | undefined | — |
Built on bits-ui — all underlying Bits UI Dialog props are forwarded transparently.