Components

Dialog

A modal dialog for confirmations, forms, and focused tasks. Includes backdrop, keyboard dismissal, and focus trapping.

Basic usage

Compose with DialogTrigger, DialogContent, DialogHeader, and DialogFooter. Pass asChild to the trigger so it renders a real Button.

Controlled

Pass open and onOpenChange for full control.

Sizes

size is a Comitor addition to the shadcn dialog. It maps to a static sm:max-w-* class so Tailwind can see it at build time; on narrow viewports every size falls back to max-w-[calc(100%-2rem)].

With form

DialogBody is the second Comitor addition: the region between header and footer that owns the scroll, so a long form never pushes the title or the actions out of view. Give it max-h-* only when you want a cap tighter than the dialog's own — the scrolling itself is already built in.

Close button

The corner ✕ is on by default. Turn it off with showCloseButton={false} when the footer should be the only exit, and keep at least one DialogClose in reach. When you keep it, set closeLabel — its default screen-reader text is the Vietnamese "Đóng".

Dialog Props

PropTypeDefaultDescription
openbooleanControlled open state. Pair with onOpenChange.
defaultOpenbooleanfalseOpen state on first render, for uncontrolled usage.
onOpenChange(open: boolean) => voidCalled whenever the dialog opens or closes.
modalbooleantrueWhen true, content outside the dialog is inert and hidden from assistive technology.
childrenrequiredReact.ReactNodeDialog trigger and content.

DialogContent Props

PropTypeDefaultDescription
size'sm' | 'md' | 'lg' | 'xl''md'Max width from the sm breakpoint up (sm:max-w-sm … sm:max-w-xl). Below sm the panel is always max-w-[calc(100%-2rem)]. Package addition — not in the shadcn baseline.
showCloseButtonbooleantrueRender the ✕ button in the top-right corner of the panel.
closeLabelstring'Đóng'Visually hidden label on that close button. The package default is Vietnamese — pass an English string in an English UI.
classNamestringMerged onto the panel with cn(); use it for one-off width or padding overrides.
…Radix ContentDialogPrimitive.ContentPropsEverything else is forwarded to Radix Dialog.Content — onEscapeKeyDown, onInteractOutside, onOpenAutoFocus, forceMount.

Parts

Every part accepts className, which is merged onto the defaults with cn().

PropTypeDefaultDescription
DialogDialogPrimitive.RootStateful container. Holds the open state and the trigger/content pair.
DialogTriggerDialogPrimitive.TriggerControl that opens the dialog. Use asChild to render your own Button.
DialogPortalDialogPrimitive.PortalPortal target. DialogContent already renders one — reach for it only when building a custom content shell.
DialogOverlayDialogPrimitive.OverlayDimmed backdrop (bg-ink/60, dark:bg-ink/80, backdrop-blur). Also rendered for you by DialogContent.
DialogContentDialogPrimitive.ContentThe centred panel: portal + overlay + card surface + optional close button.
DialogHeaderdivflex flex-col gap-2, centred on mobile and left-aligned from sm up.
DialogBodydivScrolling content region between header and footer — the package applies -m-1 min-h-0 flex-auto overflow-y-auto p-1, so the header and footer stay pinned and the focus ring on a w-full child is not clipped. Package addition.
DialogFooterdivActions row: stacked and reversed on mobile, right-aligned from sm up.
DialogTitleDialogPrimitive.TitleAccessible name for the panel. Always include one.
DialogDescriptionDialogPrimitive.DescriptionSupporting text wired to aria-describedby.
DialogCloseDialogPrimitive.CloseDismisses the dialog. Use asChild to wrap your own Button.

Accessibility

  • Built on Radix Dialog: the panel carries role="dialog" and aria-modal="true", focus is trapped while open and returns to the trigger on close.
  • Always include a DialogTitle — it supplies aria-labelledby; DialogDescription supplies aria-describedby.
  • Escape and a click on the backdrop both close the dialog. Intercept them with onEscapeKeyDown / onInteractOutside when there is unsaved work — or reach for AlertDialog, which refuses outside clicks by design.
  • Body scroll is locked and the rest of the page is inert while modal is true.
  • The corner close button has no visible text — its accessible name comes from the visually hidden closeLabel, which defaults to "Đóng". Pass closeLabel="Close" in English interfaces.