Overlays

Dialog

Modal dialog. Use for confirmations, forms, and focused tasks.

Preview
01 Installation

Install

Pull Dialog from the barrel for everyday use, or the granular path when you want a tighter bundle.

tsxBarrel1 line
import { Dialog } from "@brika/clay";
tsxGranular1 line
import { Dialog } from "@brika/clay/components/dialog";
02 Usage

A minimal example

Drop this into a page. Native HTML attributes pass through to the underlying primitive.

tsxDialog.tsx36 lines
import { Button } from '@brika/clay/components/button';
import {
  Dialog,
  DialogClose,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from '@brika/clay/components/dialog';
/** Clean modal with a title, description, and two footer actions. */
export default function DialogDefaultDemo() {
  return (
    <Dialog>
      <DialogTrigger asChild>
        <Button>Open dialog</Button>
      </DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Session expiring soon</DialogTitle>
          <DialogDescription>
            Your session will expire in 5 minutes due to inactivity. Save any
            unsaved work before continuing.
          </DialogDescription>
        </DialogHeader>
        <DialogFooter>
          <DialogClose asChild>
            <Button variant="outline">Dismiss</Button>
          </DialogClose>
          <Button>Extend session</Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
03 Examples

Dialog, every way

Form

Dialog wrapping a form, useful for inline editing without leaving the page.

Scrollable

Dialog with long scrollable content, the panel caps at 85vh and scrolls internally.

04 Accessibility

Accessibility

  • Focus is trapped inside the dialog while open, Tab cycles only through its interactive elements.
  • Escape and clicking the backdrop close the dialog and return focus to the trigger.
  • DialogTitle is required and becomes the accessible name, use sr-only to visually hide it if needed.
  • Scrollable content should be the scrollable region, not the entire dialog.
05 Tokens 19 theme-overridable

Theme tokens

Every CSS variable Dialog reads, with its default and the dotted path you'd write in a ThemeConfig JSON to override it. Set any of these in your theme to retune Dialog without touching component code.

Dialog tokens

19 tokens
ColorFill, border, and text colors.8
  • --dialog-containercolorvar(--popover)
    components.dialog.container

    Dialog background.

  • --dialog-labelcolorvar(--popover-foreground)
    components.dialog.label

    Dialog text color.

  • --dialog-overlay-bgcoloroklch(0 0 0 / 0.5)
    components.dialog.overlayBg

    Modal scrim color behind the dialog. Lower alpha + non-zero `overlay-backdrop-blur` produces an iOS-style glass scrim that frosts the page instead of dimming it.

  • --dialog-description-colorcolorvar(--muted-foreground)
    components.dialog.descriptionColor

    Foreground color of `<DialogDescription>` text rendered beneath the dialog title.

  • --dialog-close-active-containercolorvar(--accent)
    components.dialog.closeActiveContainer

    Background of the built-in close-X button when its data-state is open.

  • --dialog-close-active-labelcolorvar(--muted-foreground)
    components.dialog.closeActiveLabel

    Glyph color of the built-in close-X button when its data-state is open.

  • --dialog-close-focus-ring-colorcolorvar(--ring)
    components.dialog.closeFocusRingColor

    Focus ring color of the built-in close-X button when keyboard-focused. Defaults to the theme ring color.

  • --dialog-close-focus-ring-offset-colorcolorvar(--background)
    components.dialog.closeFocusRingOffsetColor

    Color drawn between the close-X button and its focus ring (the ring offset). Should match the page background so the offset reads as a gap.

GeometrySizes, lengths, and corner radii.4
  • --dialog-radiusradiusvar(--radius-surface)
    components.dialog.radius

    Dialog corner radius.

  • --dialog-padding-xsizecalc(var(--spacing) * 6)
    components.dialog.paddingX

    Inline padding inside the dialog.

  • --dialog-padding-ysizecalc(var(--spacing) * 6)
    components.dialog.paddingY

    Block padding inside the dialog.

  • --dialog-gapsizecalc(var(--spacing) * 4)
    components.dialog.gap

    Gap between adjacent children inside the dialog.

BorderBorder width and style.2
  • --dialog-border-widthborder-width1px
    components.dialog.borderWidth

    Border width on the dialog. Set non-zero for outline-style variants.

  • --dialog-border-styleborder-stylesolid
    components.dialog.borderStyle

    Border style on the dialog (`solid`, `dashed`, `double`, `none`).

ElevationDrop shadow and depth.3
  • --dialog-overlay-backdrop-blurblur0px
    components.dialog.overlayBackdropBlur

    Backdrop blur applied to the modal scrim. Set non-zero so the page content behind the dialog is frosted by the overlay itself.

  • --dialog-shadowshadowvar(--shadow-modal)
    components.dialog.shadow

    Dialog elevation.

  • --dialog-backdrop-blurblur0px
    components.dialog.backdropBlur

    Backdrop blur applied behind a translucent dialog.

MotionAnimation duration and easing.2
  • --dialog-durationdurationvar(--motion-standard-duration)
    components.dialog.duration

    Transition duration for dialog state changes.

  • --dialog-easingeasingvar(--motion-standard-easing)
    components.dialog.easing

    Transition easing for dialog state changes.

Override in a theme

Authoring a theme is plain JSON. Drop overrides under components.dialog, the names are camelCase versions of the variable suffix.

jsonmy-theme.json12 lines
{
  "id": "my-theme",
  "name": "My Theme",
  "description": "...",
  "accentSwatches": ["#000"],

  "components": {
    "dialog": {
      "paddingX": "calc(var(--spacing) * 6)"
    }
  }
}

Then apply with applyTheme(myTheme) (see the theming guide), scope it to a subtree with themeToCssVars(myTheme, mode), or consume any token directly in your own JSX with the matching Tailwind utility (e.g. bg-dialog-…) — see the chips on each token row.

06 API reference

API reference

Props specific to Dialog. Native HTML attributes pass through to the underlying primitive, see the component source on GitHub for the full type signature.

<Dialog />

passthrough

No wrapper-specific props, all attributes pass through to the underlying primitive.

<DialogClose />

passthrough

No wrapper-specific props, all attributes pass through to the underlying primitive.

<DialogContent />

1 prop

<DialogDescription />

passthrough

No wrapper-specific props, all attributes pass through to the underlying primitive.

<DialogFooter />

1 prop

<DialogHeader />

passthrough

No wrapper-specific props, all attributes pass through to the underlying primitive.

<DialogOverlay />

passthrough

No wrapper-specific props, all attributes pass through to the underlying primitive.

<DialogPortal />

passthrough

No wrapper-specific props, all attributes pass through to the underlying primitive.

<DialogTitle />

passthrough

No wrapper-specific props, all attributes pass through to the underlying primitive.

<DialogTrigger />

passthrough

No wrapper-specific props, all attributes pass through to the underlying primitive.