DesignDialog
Modal dialog component with consistent styling and animations. Composition-based API with Header, Body, Footer sections. Based on Radix UI Dialog.
Component
Import
tsx
import {
  DesignDialog,
  DesignDialogContent,
  DesignDialogHeader,
  DesignDialogTitle,
  DesignDialogDescription,
  DesignDialogBody,
  DesignDialogFooter,
  DesignDialogTrigger,
  DesignDialogClose,
} from "@/components/ui/design-dialog";
import { DesignButton } from "@/components/ui/design-button";
Sizes
sm (512px), default (640px), lg (768px)
Max Height
90vh with scrollable body
Sections
Header, Body, Footer
Features
preventOutsideClose, controlled mode

DesignDialogContent Props

Main container for dialog content

Props
PropTypeDefaultDescription
size"sm" | "default" | "lg""default"Dialog width: sm=512px, default=640px, lg=768px
preventOutsideClosebooleanfalsePrevent closing when clicking outside the dialog
classNamestring-Additional CSS classes

Composition Components

Use these components to build dialog content

Props
PropTypeDefaultDescription
DesignDialogContainer-Root component, wraps everything. Accepts open/onOpenChange for controlled mode
DesignDialogTriggerTrigger-Button/element that opens the dialog. Use asChild with DesignButton
DesignDialogContentContent-The modal content container with size and preventOutsideClose props
DesignDialogHeaderSection-Contains Title and Description, with bottom padding
DesignDialogTitleText-Dialog title (required for accessibility)
DesignDialogDescriptionText-Optional description below title
DesignDialogBodySection-Scrollable content area with max-height
DesignDialogFooterSection-Action buttons area, right-aligned on desktop
DesignDialogCloseAction-Closes the dialog when clicked. Use asChild with DesignButton
Common Patterns

Basic Confirmation Dialog

Simple yes/no confirmation
<DesignDialog>
  <DesignDialogTrigger asChild>
    <DesignButton variant="primary">Delete</DesignButton>
  </DesignDialogTrigger>
  <DesignDialogContent size="sm">
    <DesignDialogHeader>
      <DesignDialogTitle>Are you sure?</DesignDialogTitle>
      <DesignDialogDescription>
        This action cannot be undone.
      </DesignDialogDescription>
    </DesignDialogHeader>
    <DesignDialogFooter>
      <DesignDialogClose asChild>
        <DesignButton variant="tertiary" size="large">Cancel</DesignButton>
      </DesignDialogClose>
      <DesignDialogClose asChild>
        <DesignButton variant="primary" size="large">Delete</DesignButton>
      </DesignDialogClose>
    </DesignDialogFooter>
  </DesignDialogContent>
</DesignDialog>

Form Dialog

Dialog with form inputs
<DesignDialog>
  <DesignDialogTrigger asChild>
    <DesignButton variant="secondary">Create</DesignButton>
  </DesignDialogTrigger>
  <DesignDialogContent>
    <DesignDialogHeader>
      <DesignDialogTitle>Create New Item</DesignDialogTitle>
      <DesignDialogDescription>
        Fill in the details below
      </DesignDialogDescription>
    </DesignDialogHeader>
    <DesignDialogBody>
      <div className="flex flex-col gap-4">
        <DesignInput label="Name" placeholder="Enter name..." />
        <DesignInput label="Description" placeholder="Enter description..." />
      </div>
    </DesignDialogBody>
    <DesignDialogFooter>
      <DesignDialogClose asChild>
        <DesignButton variant="tertiary" size="large">Cancel</DesignButton>
      </DesignDialogClose>
      <DesignButton variant="primary" size="large">Create</DesignButton>
    </DesignDialogFooter>
  </DesignDialogContent>
</DesignDialog>

Controlled Dialog

Programmatic open/close control
const [open, setOpen] = useState(false);

<DesignDialog open={open} onOpenChange={setOpen}>
  <DesignDialogContent>
    <DesignDialogHeader>
      <DesignDialogTitle>Controlled Dialog</DesignDialogTitle>
    </DesignDialogHeader>
    <DesignDialogBody>
      <p>State controlled externally</p>
    </DesignDialogBody>
    <DesignDialogFooter>
      <DesignButton variant="tertiary" size="large" onClick={() => setOpen(false)}>
        Close
      </DesignButton>
    </DesignDialogFooter>
  </DesignDialogContent>
</DesignDialog>

<DesignButton onClick={() => setOpen(true)}>Open</DesignButton>

Prevent Outside Close

Force explicit action
<DesignDialogContent preventOutsideClose>
  <DesignDialogHeader>
    <DesignDialogTitle>Important Action</DesignDialogTitle>
    <DesignDialogDescription>
      Click outside won't close. Must use buttons.
    </DesignDialogDescription>
  </DesignDialogHeader>
  <DesignDialogFooter>
    <DesignDialogClose asChild>
      <DesignButton variant="tertiary" size="large">Cancel</DesignButton>
    </DesignDialogClose>
    <DesignDialogClose asChild>
      <DesignButton variant="primary" size="large">Confirm</DesignButton>
    </DesignDialogClose>
  </DesignDialogFooter>
</DesignDialogContent>
When to Use
1

Delete confirmation

Use size="sm", no Body needed, just Header + Footer

<DesignDialogContent size="sm">
  <DesignDialogHeader>
    <DesignDialogTitle>Delete this item?</DesignDialogTitle>
    <DesignDialogDescription>This cannot be undone.</DesignDialogDescription>
  </DesignDialogHeader>
  <DesignDialogFooter>
    <DesignDialogClose asChild>
      <DesignButton variant="tertiary" size="large">Cancel</DesignButton>
    </DesignDialogClose>
    <DesignDialogClose asChild>
      <DesignButton variant="primary" size="large">Delete</DesignButton>
    </DesignDialogClose>
  </DesignDialogFooter>
</DesignDialogContent>
2

Settings or form with multiple fields

Use default size, Body for form content

<DesignDialogContent>
  <DesignDialogHeader>
    <DesignDialogTitle>Settings</DesignDialogTitle>
  </DesignDialogHeader>
  <DesignDialogBody>
    <div className="flex flex-col gap-4">
      <DesignInput label="Username" />
      <DesignInput label="Email" />
    </div>
  </DesignDialogBody>
  <DesignDialogFooter>...</DesignDialogFooter>
</DesignDialogContent>
3

Long content like terms or documentation

Use size="lg", Body will scroll automatically

<DesignDialogContent size="lg">
  <DesignDialogHeader>
    <DesignDialogTitle>Terms of Service</DesignDialogTitle>
  </DesignDialogHeader>
  <DesignDialogBody>
    {/* Long content here - will scroll */}
  </DesignDialogBody>
  <DesignDialogFooter>
    <DesignDialogClose asChild>
      <DesignButton variant="tertiary" size="large">Decline</DesignButton>
    </DesignDialogClose>
    <DesignDialogClose asChild>
      <DesignButton variant="primary" size="large">Accept</DesignButton>
    </DesignDialogClose>
  </DesignDialogFooter>
</DesignDialogContent>
Do

Always use size="large" for footer buttons

<DesignDialogFooter>
  <DesignButton variant="tertiary" size="large">Cancel</DesignButton>
  <DesignButton variant="primary" size="large">Confirm</DesignButton>
</DesignDialogFooter>

Use asChild with DesignDialogTrigger and DesignDialogClose

<DesignDialogTrigger asChild>
  <DesignButton>Open</DesignButton>
</DesignDialogTrigger>

<DesignDialogClose asChild>
  <DesignButton variant="tertiary" size="large">Cancel</DesignButton>
</DesignDialogClose>

Place Cancel button first, primary action last

<DesignDialogFooter>
  <DesignDialogClose asChild>
    <DesignButton variant="tertiary" size="large">Cancel</DesignButton>
  </DesignDialogClose>
  <DesignDialogClose asChild>
    <DesignButton variant="primary" size="large">Save</DesignButton>
  </DesignDialogClose>
</DesignDialogFooter>
Don't

Don't use default/small size buttons in footer

// ❌ Bad - wrong button size
<DesignDialogFooter>
  <DesignButton variant="tertiary">Cancel</DesignButton>
</DesignDialogFooter>

// βœ… Good - use size="large"
<DesignDialogFooter>
  <DesignButton variant="tertiary" size="large">Cancel</DesignButton>
</DesignDialogFooter>

Don't forget asChild on Trigger and Close

// ❌ Bad - missing asChild, creates nested buttons
<DesignDialogTrigger>
  <DesignButton>Open</DesignButton>
</DesignDialogTrigger>

// βœ… Good - asChild merges props
<DesignDialogTrigger asChild>
  <DesignButton>Open</DesignButton>
</DesignDialogTrigger>

Don't omit DesignDialogTitle (required for accessibility)

// ❌ Bad - no title
<DesignDialogContent>
  <DesignDialogBody>Content</DesignDialogBody>
</DesignDialogContent>

// βœ… Good - always include title
<DesignDialogContent>
  <DesignDialogHeader>
    <DesignDialogTitle>Dialog Title</DesignDialogTitle>
  </DesignDialogHeader>
  <DesignDialogBody>Content</DesignDialogBody>
</DesignDialogContent>

Visual Examples

Interactive examples showing all variants

Size: Small (512px)

For simple confirmations

<DesignDialogContent size="sm">...</DesignDialogContent>

Size: Default (640px)

For forms and general use

<DesignDialogContent>...</DesignDialogContent>

Size: Large (768px)

For complex content

<DesignDialogContent size="lg">...</DesignDialogContent>

Prevent Outside Close

Must use buttons to close

<DesignDialogContent preventOutsideClose>...</DesignDialogContent>

With Form

Dialog containing form inputs

<DesignDialogBody>
  <DesignInput label="Name" />
</DesignDialogBody>

Controlled Mode

Programmatic control

Closed
const [open, setOpen] = useState(false);
<DesignDialog open={open} onOpenChange={setOpen}>...