Overview
Dialogs are built on Radix Dialog and Radix Alert Dialog with thin wrappers in components/ui/Dialog.tsx
and components/ui/AlertDialog.tsx
. We expose a small API for sizing/position, a consistent overlay, tokenized colors, and an optional close button. Use Dialog for general content (forms, pickers), and Alert Dialog for confirmations and destructive actions.
Exports
- Primitives:
Dialog
,DialogTrigger
,DialogPortal
,DialogOverlay
,DialogClose
- Content & layout:
DialogContent
(props:size
,position
,showCloseButton
),DialogHeader
,DialogFooter
,DialogTitle
,DialogDescription
- Props:
size
:sm
·default
·lg
position
:centered
·top
showCloseButton
:true | false
(defaulttrue
)
- Behavior & styling:
- Overlay: blurred, semi-transparent, animated; outside click and
Esc
close by default. - Content: rounded, animated in/out, themed with tokens (light/dark).
- Trigger: use
asChild
to style a button/link while keeping behavior.
Controlled vs uncontrolled
- Uncontrolled:
<Dialog>
withoutopen
/onOpenChange
(Radix manages state). - Controlled: pass
open
andonOpenChange
for complex flows (close on success, block open when invalid, etc.).
Patterns
- Form in a dialog:. Wrap the form inside
DialogContent
. For async submit, useReact.useTransition()
withTransitionButton
for pending state. Close on success with your localsetIsOpen(false)
. Keep footers simple: primary action + secondary cancel (DialogFooter
). - Top-positioned sheets: Use
position="top"
for short, frequent interactions (e.g., quick create). - Close affordances: Keep the corner close button (
showCloseButton
) unless the dialog is a single critical choice (then consider Alert Dialog).
Accessibility
DialogTitle
and DialogDescription
wire ARIA automatically; focus is trapped while open, and Esc
/overlay dismiss by default. Icon-only triggers must have an accessible label (aria-label
or visually hidden text).
Alert Dialog
Exports mirror Dialog: AlertDialog
, AlertDialogTrigger
, AlertDialogContent
, AlertDialogHeader/Footer/Title/Description
, AlertDialogOverlay/Portal
, plus AlertDialogAction
and AlertDialogCancel
. Use for irreversible actions (delete, reset, leave flow). Actions reuse buttonVariants
for consistent styling; drive async work with useTransition
+ TransitionButton
, then close on success.
When to choose which
- General UI (forms, pickers, multi-step content) → Dialog
- Confirm dangerous/critical action → Alert Dialog
- Real link or custom element as trigger →
Trigger asChild
- Loading feedback inside actions → TransitionButton with
useTransition()
Customization quick list
- Size & position via
DialogContent size/position
. - Corner close visibility via
showCloseButton
. - Header/footer composition via
DialogHeader
/DialogFooter
. - Keep styling via tokens; use
className
only for small tweaks - avoid one-off colors.