Skip to content

Now in the official shadcn registry directory.

Start free

Dialog

A modal dialog with portal, overlay, focus trap and fade/zoom animations, composed from Trigger, Content, Header, Footer, Title, Description and Close parts.

overlay
A free styled version is available

Installation

Run the following command

npx shadcn@latest add @ai2/dialog

Dependencies, the @ai2/tokens theme and the component file are installed together.

Usage

TS
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog"

<Dialog>
  <DialogTrigger asChild>
    <Button variant="outline">Open dialog</Button>
  </DialogTrigger>
  <DialogContent>
    <DialogHeader>
      <DialogTitle>Create API key</DialogTitle>
      <DialogDescription>You can revoke it at any time.</DialogDescription>
    </DialogHeader>
  </DialogContent>
</Dialog>

Wrap the trigger with DialogTrigger asChild to attach the dialog to any element. Always include a DialogTitle (visually hidden with sr-only if needed) for accessibility.

Examples

Wrap a button with DialogClose asChild to make it dismiss the dialog without extra state.

Without close button

Custom width

Sizes

The size prop caps the panel max width from the sm breakpoint up: sm, md (the default, max-w-lg), lg, xl and full. On mobile every size stays full width minus a 1rem margin on each side. For a one-off width, keep the className override shown above.

Props

DialogContent adds two props on top of the radix Content props. Every part also forwards its underlying radix props, e.g. open / onOpenChange on Dialog.

PropTypeDefaultDescription
size"sm" | "md" | "lg" | "xl" | "full""md"Caps the panel max width from the sm breakpoint up: sm (sm), md (max-w-lg), lg (2xl), xl (4xl), full (100% minus a 2rem margin each side). On mobile every size stays full width minus a 1rem margin.
showClosebooleantrueRenders the X close button in the top-right corner of DialogContent.

ai2 Dialog: an accessible modal dialog for React

The ai2 Dialog is a shadcn-compatible modal dialog component for React, built on the radix-ui Dialog primitive and styled with Tailwind CSS v4. It handles everything a modal is supposed to handle: rendering in a portal above the page, dimming the background with an overlay, trapping focus inside the content, closing on Escape or an outside click, and returning focus to the trigger when it closes.

Because it ships through the shadcn registry format, you install it with one CLI command, an MCP agent, or a copy-paste, and the source lands in your own project. You own the file; there is no runtime dependency on ai2 itself. The live example above is the exact component you get.

What is the ai2 Dialog?

It is an eight-part composition: Dialog, DialogTrigger, DialogContent, DialogHeader, DialogFooter, DialogTitle, DialogDescription and DialogClose, with DialogOverlay also exported. The anatomy matches shadcn/ui exactly, so existing snippets and AI agents keep working without changes.

DialogContent bundles the portal, the overlay and the panel in one component, adds a built-in X close button you can hide with showClose={false}, caps the panel width through a five-step size prop (sm, md, lg, xl, full), and animates open and close with fade and zoom on the shared ai2 motion tokens.

Why use it

  • Focus trap done right: The radix-ui Dialog primitive moves focus into the dialog on open, keeps Tab cycling inside it, and returns focus to the trigger on close. This is the part of modals most hand-rolled versions get wrong.
  • Correct ARIA wiring: The content gets role dialog and aria-modal, and DialogTitle and DialogDescription are announced through aria-labelledby and aria-describedby automatically.
  • Escape and outside click: Both dismiss the dialog by default, and both are configurable through the radix onEscapeKeyDown and onPointerDownOutside callbacks when a flow must not be abandoned.
  • Portal and overlay included: DialogContent renders in a portal above everything with a black/50 overlay, so z-index fights and clipped parents are not your problem.
  • Agent-readable metadata: The registry item describes its parts and intended use in plain words, so an MCP agent can find, inspect and install it without guessing.

Features

  • shadcn registry install: One command adds the component, its dependencies and the @ai2/tokens theme to your project.
  • Fade and zoom animation: The overlay fades and the panel zooms from 95 percent on open and close, timed by --motion-base from the shared token file.
  • Optional close button: The X button in the corner renders by default and disappears with showClose={false}, for flows that must end through an explicit action.
  • Responsive footer: DialogFooter stacks actions in reverse column order on small screens and right-aligns them in a row from the sm breakpoint up.
  • Controlled and uncontrolled state: Let DialogTrigger manage the open state, or pass open and onOpenChange to drive the dialog from React state, for example after a form submit.
  • Data attributes for styling: Every part exposes data-slot, and radix adds data-state on the overlay and content, so open and closed styles are targetable from CSS.

Production tips

  • Always render a DialogTitle: Screen readers announce the dialog by its title. If the design has no visible heading, keep a DialogTitle with the sr-only class instead of omitting it.
  • Use asChild for triggers: DialogTrigger asChild attaches the dialog to your own Button or any element without nesting two buttons in the DOM.
  • Pick a size, or override with className: The size prop caps the panel width from the sm breakpoint up: sm, md (the default), lg, xl and full. On mobile every size spans the viewport minus a 1rem margin on each side. For a one-off width outside the scale, pass className="sm:max-w-2xl" on DialogContent instead.
  • Close through DialogClose: Wrap Cancel buttons with DialogClose asChild so dismissal needs no state wiring; reserve controlled mode for closes that follow async work.
  • Do not stack modals: A dialog opening another dialog disorients keyboard and screen reader users. Prefer a single dialog with steps, or an inline expansion.

Works with the rest of ai2

Dialogs are usually forms: ai2 Field rows with ai2 Input inside DialogContent and ai2 Button actions in the footer is the standard recipe. The ai2 Command palette builds its CommandDialog on this exact component.

For destructive confirmations that need an explicit choice, use the ai2 Alert Dialog instead; for side-anchored panels like filters or carts, reach for the ai2 Sheet. All three share the same overlay language and token source.

FAQs

Get new components in your inbox

Component drops, new themes and release notes. No spam, and you can unsubscribe from any email.

© 2026 ai2 design system · MIT licensed · Built with its own components