Skip to content

Dialog

In the app

The modal and the right-hand drawer, one component. Built on the native <dialog>, so focus trapping, Escape and the inert background are free.

@varick/ui/components/dialogAdded 2 Sept 2026

Promote v2.3 to production?

The current version keeps running until the new one passes its first scheduled run.

Shown in the audit log.

Run 4f2a · Submission router

Started 2 min ago · 14 steps · 1 retry

TriggerSchedule
Duration41s
OwnerJo Smith
Logs retained for 30 days

Usage

import {
  Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle,
  DialogDescription, DialogBody, DialogFooter, DialogClose,
} from "@varick/ui/components/dialog";

export function Example() {
  return (
    <Dialog>
      <DialogTrigger variant="primary">Promote to production</DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Promote v2.3 to production?</DialogTitle>
          <DialogDescription>The current version keeps running until...</DialogDescription>
        </DialogHeader>
        <DialogBody>...</DialogBody>
        <DialogFooter>
          <DialogClose />
          <Button variant="primary" onClick={promote}>Promote</Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

Variants

Drawer, for detail panes

Run 4f2a

Slides in from the right, 500px wide, full height.

Nothing to show yet

Steps appear here as the run progresses.

<DialogContent variant="drawer">
  <DialogHeader>...</DialogHeader>
  <DialogBody>...</DialogBody>
  <DialogFooter><DialogClose>Close</DialogClose></DialogFooter>
</DialogContent>

API reference

Every component also accepts className and the native props of its root element.

PropTypeDefaultDescription
Dialog.openbooleanuncontrolledControlled open state, with onOpenChange. defaultOpen for uncontrolled.
DialogTriggerButton props + asChildRenders a Button, or decorates the child.
DialogContent.variant'modal' | 'drawer''modal'Centred at 480px, or a 500px right-hand pane.
DialogContent.showClosebooleantrueThe X in the top corner.
DialogClose.childrenReactNode'Cancel'An outline Button that closes.

Accessibility

  • A native <dialog> opened with showModal(): focus is trapped, the page behind is inert, Escape closes.
  • aria-labelledby and aria-describedby point at DialogTitle and DialogDescription. Always include a title.
  • Clicking the backdrop closes; content clicks do not bubble to it.

Styles

The CSS as it appears in the app. The live component above is the same values as Tailwind classes.

.modal-backdrop { position: fixed; inset: 0; background: rgba(17,17,17,0.32); }
.drawer {
  width: 500px;
  max-width: 100%;
  background: #FFFFFF;
  border-radius: 8px;
  box-shadow: 0 24px 64px rgba(0,0,0,0.18);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transform: translateX(16px) scale(0.99);
  opacity: 0;
  transition: transform 260ms var(--ease-out), opacity 220ms var(--ease-out);
}
.drawer-head { padding: 20px 24px; border-bottom: 1px solid var(--hairline-soft); }
.drawer-title { font-size: 16px; font-weight: 500; letter-spacing: -0.01em; }
.drawer-body { flex: 1; overflow-y: auto; padding: 20px 24px 24px; }
.drawer-foot { display: flex; justify-content: space-between; padding: 16px 24px; border-top: 1px solid var(--hairline-soft); }
.modal-head { padding: 16px 20px; border-bottom: 1px solid var(--hairline-soft); }
.modal-title { font-size: 15px; font-weight: 500; }