Dialog
Modal dialog for important actions or information
Basic Usage
Semantic Size Variants
Choose the dialog size based on its purpose, not arbitrary pixel values. Semantic names make it clear which size to use.
| Size | Width | Use Case |
|---|---|---|
alert | 384px | Confirmations, alerts, simple prompts |
form(default) | 448px | Standard entity forms, create/edit dialogs |
panel | 672px | Multi-section forms, wizards, settings |
picker | 896px | Selection interfaces, template pickers |
editor | 1024px | Large editing tools, icon/image pickers |
workspace | 1152px | Full-featured design tools |
Scrollable Content
Use the scrollable prop for dialogs with potentially long content that may exceed the viewport.
| Prop | Type | Default | Description |
|---|---|---|---|
size | "alert" | "form" | "panel" | "picker" | "editor" | "workspace" | "form" | Semantic size variant based on dialog purpose |
scrollable | boolean | false | Enable scrollable content with max-h-[80vh] |
open | boolean | - | Controlled open state |
onOpenChange | (open: boolean) => void | - | Open state change handler |
modal | boolean | true | Render as modal overlay |
Sheet
Slide-in panel from screen edges
| Prop | Type | Default | Description |
|---|---|---|---|
side | "top" | "right" | "bottom" | "left" | "right" | Side to slide in from |
open | boolean | - | Controlled open state |
onOpenChange | (open: boolean) => void | - | Open state change handler |
DropdownMenu
Contextual dropdown menu for actions
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | - | Controlled open state |
onOpenChange | (open: boolean) => void | - | Open state change handler |
align | "start" | "center" | "end" | "center" | Alignment relative to trigger |
ContextMenu
Right-click contextual menu
Right click here
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | - | Trigger element to right-click |
onOpenChange | (open: boolean) => void | - | Open state change handler |
Popover
Floating content panel attached to trigger
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | - | Controlled open state |
onOpenChange | (open: boolean) => void | - | Open state change handler |
align | "start" | "center" | "end" | "center" | Alignment relative to trigger |
side | "top" | "right" | "bottom" | "left" | "bottom" | Preferred side |
Tooltip
Brief hover hints and help text
| Prop | Type | Default | Description |
|---|---|---|---|
delayDuration | number | 700 | Delay before showing (ms) |
side | "top" | "right" | "bottom" | "left" | "top" | Preferred side |
sideOffset | number | 4 | Offset from trigger |
Command
Command palette for keyboard-driven navigation
| Prop | Type | Default | Description |
|---|---|---|---|
filter | (value: string, search: string) => number | - | Custom filter function |
shouldFilter | boolean | true | Enable/disable filtering |
loop | boolean | false | Loop keyboard navigation |
import { useState } from 'react';
import {
CommandDialog,
CommandInput,
CommandList,
CommandEmpty,
CommandGroup,
CommandItem,
} from '@/ui/primitives';
const [open, setOpen] = useState(false);
<Button onClick={() => setOpen(true)}>Open Command Palette</Button>
<CommandDialog open={open} onOpenChange={setOpen} title="Command palette">
<CommandInput placeholder="Search..." />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup heading="Suggestions">
<CommandItem onSelect={() => setOpen(false)}>
<Icon icon={faCalendar} />
Calendar
</CommandItem>
</CommandGroup>
</CommandList>
</CommandDialog>