Skip to content
design
Components

Dialog

Composable dialog parts for focused tasks and custom layouts.

On this page
Composable dialog parts for focused tasks and custom layouts.
Code
import { Dialog } from "@bosunkit/components/dialog";
import { Button } from "@bosunkit/components/button";
import { Field } from "@bosunkit/components/field";
import { Stack } from "@bosunkit/components/stack";
import type { ReactElement } from "react";
export const description: string =
  "A composed dialog names its task, moves focus inside, closes with Escape and restores focus to its trigger.";
export default function Showcase(): ReactElement {
  return (
    <Dialog.Root>
      <Dialog.Trigger render={<Button>Name report</Button>} />
      <Dialog.Portal>
        <Dialog.Backdrop />
        <Dialog.Popup>
          <Stack space="lg">
            <Stack space="xs">
              <Dialog.Title>Name report</Dialog.Title>
              <Dialog.Description>This title appears in the report library.</Dialog.Description>
            </Stack>
            <Field.Root>
              <Field.Label>Report title</Field.Label>
              <Field.Control defaultValue="Daily engineering update" />
            </Field.Root>
            <div>
              <Dialog.Close render={<Button>Done</Button>} />
            </div>
          </Stack>
        </Dialog.Popup>
      </Dialog.Portal>
    </Dialog.Root>
  );
}
01Names describe behaviorUse the primitive for custom composition and a named recipe for an assembled control.
02One state contractControlled values, defaults and change callbacks follow Base UI; event details keep their reason and cancellation.
03Composition keeps semanticsA render target forwards its ref and every received DOM prop so keyboard interaction and accessible names survive.

Composition

Import { Dialog } from @bosunkit/components/dialog. Named parts follow Base UI Dialog. Each part retains the upstream render, ref, DOM props, state attributes and event contracts. The kit supplies its typography, surfaces and scoped overlay presentation.

Examples

Custom composition

A composed dialog names its task, moves focus inside, closes with Escape and restores focus to its trigger.
Code
import { Dialog } from "@bosunkit/components/dialog";
import { Button } from "@bosunkit/components/button";
import { Field } from "@bosunkit/components/field";
import { Stack } from "@bosunkit/components/stack";
import type { ReactElement } from "react";
export const description: string =
  "A composed dialog names its task, moves focus inside, closes with Escape and restores focus to its trigger.";
export default function Showcase(): ReactElement {
  return (
    <Dialog.Root>
      <Dialog.Trigger render={<Button>Name report</Button>} />
      <Dialog.Portal>
        <Dialog.Backdrop />
        <Dialog.Popup>
          <Stack space="lg">
            <Stack space="xs">
              <Dialog.Title>Name report</Dialog.Title>
              <Dialog.Description>This title appears in the report library.</Dialog.Description>
            </Stack>
            <Field.Root>
              <Field.Label>Report title</Field.Label>
              <Field.Control defaultValue="Daily engineering update" />
            </Field.Root>
            <div>
              <Dialog.Close render={<Button>Done</Button>} />
            </div>
          </Stack>
        </Dialog.Popup>
      </Dialog.Portal>
    </Dialog.Root>
  );
}

Props

PropTypeDefaultDescription
motionboolean | undefined–Enable token-based transitions; false disables motion.
initialFocusboolean | React.RefObject<HTMLElement | null> | ((openType: InteractionType) => boolean | HTMLElement | null | void) | undefined–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). - RefObject: Move focus to the ref element. - function: Called with the interaction type (mouse, touch, pen, or keyboard). Return an element to focus, true to use the default behavior, null to fall back to the default behavior, or false/undefined to do nothing.
finalFocusboolean | React.RefObject<HTMLElement | null> | ((closeType: InteractionType) => boolean | HTMLElement | null | void) | undefined–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). - RefObject: Move focus to the ref element. - function: Called with the interaction type (mouse, touch, pen, or keyboard). Return an element to focus, true to use the default behavior, null to fall back to the default behavior, or false/undefined to do nothing.
classNamestring | ((state: State) => string | undefined) | undefined–CSS class applied to the element, or a function that returns a class based on the component's state.
renderReact.ReactElement | ComponentRenderFn<RenderFunctionProps, State> | undefined–Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render.
styleReact.CSSProperties | ((state: State) => React.CSSProperties | undefined) | undefined–Style applied to the element, or a function that returns a style object based on the component's state.

Also takes every attribute of Primitive.Popup.Props.

PropTypeDefaultDescription
motionboolean | undefined–Enable token-based transitions; false disables motion.
forceRenderboolean | undefined–Whether the backdrop is forced to render even when nested.
classNamestring | ((state: State) => string | undefined) | undefined–CSS class applied to the element, or a function that returns a class based on the component's state.
renderReact.ReactElement | ComponentRenderFn<RenderFunctionProps, State> | undefined–Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render.
styleReact.CSSProperties | ((state: State) => React.CSSProperties | undefined) | undefined–Style applied to the element, or a function that returns a style object based on the component's state.

Also takes every attribute of Primitive.Backdrop.Props.

PropTypeDefaultDescription
classNamestring | ((state: State) => string | undefined) | undefined–CSS class applied to the element, or a function that returns a class based on the component's state.
renderReact.ReactElement | ComponentRenderFn<RenderFunctionProps, State> | undefined–Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render.
styleReact.CSSProperties | ((state: State) => React.CSSProperties | undefined) | undefined–Style applied to the element, or a function that returns a style object based on the component's state.

Also takes every attribute of Primitive.Title.Props.

PropTypeDefaultDescription
classNamestring | ((state: State) => string | undefined) | undefined–CSS class applied to the element, or a function that returns a class based on the component's state.
renderReact.ReactElement | ComponentRenderFn<RenderFunctionProps, State> | undefined–Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render.
styleReact.CSSProperties | ((state: State) => React.CSSProperties | undefined) | undefined–Style applied to the element, or a function that returns a style object based on the component's state.

Also takes every attribute of Primitive.Description.Props.

Do
Compose labeled parts and preserve their ref and DOM props.
Don't
Use the named parts for keyboard and focus behavior.
Do not replace semantic controls with clickable generic elements or discard event details.