| Need | Use | Why |
|---|---|---|
| Modal blocking dialog, general content | Dialog | Focus-trapped, Esc closes, Title/Description announced |
| Modal requiring explicit confirm/cancel response | AlertDialog | Same as Dialog but semantically an interrupt; Cancel/Action must be visually distinct |
| Non-modal rich content near a trigger | Popover | Defaults non-modal (modal={false}); set modal={true} for Dialog-like trapping if needed |
| Click-triggered action list | DropdownMenu | Positions against Trigger |
| Right-click/long-press action list | ContextMenu | Positions at pointer |
| Persistent File/Edit-style command bar | Menubar | Adjacent-menu ArrowLeft/Right switching that plain DropdownMenus lack |
| Hierarchical site navigation with animated panel switching | NavigationMenu | Shared Viewport for cross-panel transitions |
| Short hint text, keyboard-accessible | Tooltip | Opens on focus AND hover |
| Rich preview, sighted-mouse-only | HoverCard | Explicitly excluded from a11y tree — never put essential-only content here |
| Need | Use | Why |
|---|---|---|
| Single choice, form-native, radio look | RadioGroup | Mutually exclusive, roving tabindex |
| Single choice, segmented-button look | ToggleGroup type="single" | Same exclusivity, button styling instead of dots |
| Independent multi-select toggles | ToggleGroup type="multiple" or several Toggle | Grouped vs. fully independent |
| Boolean, form-checkbox semantics, optional indeterminate | Checkbox | Tri-state (boolean | "indeterminate") |
| Boolean, immediate on/off setting feel | Switch | Two-state only, no indeterminate |
| Single value from a long/native-feeling list | Select | Item-aligned positioning mimics native <select> |
AlertDialog, not Dialog, when the interaction must interrupt and demand a response (destructive confirm) — Dialog doesn't guarantee the same focus/announcement contract for that use case.forceMount only when a JS animation library needs to control unmount timing — CSS keyframes alone don't need it (Radix already suspends unmount for you).Select/Popover/etc. to "popper" positioning when the default item-aligned or trigger-adjacent placement collides with the viewport edge, or you need the same side/align API as the rest of your overlay UI.Label (or Form.Label) with custom controls — none of the interactive primitives render their own visible label text.HiddenInput/rely on the default hidden input for Checkbox/RadioGroup/Switch/Slider used inside a real <form> — don't reach for the unstable_* decoupled parts unless you specifically need to relocate the input.AccessibleIcon — a bare icon has no inherent accessible name.Separator's decorative prop whenever the divider is purely visual, to avoid ARIA separator noise.ContextMenu, not a manually-positioned Popover.Tooltip, never HoverCard.open/checked/value state purely to add a CSS class → stop, use data-state instead.setTimeout an auto-dismiss notification → use Toast, it already handles duration, pause-on-hover/focus/blur, and swipe-dismiss.asChild "loses" Radix's click/keyboard behavior → check it spreads props and forwards its ref.delayDuration: 700ms open delay (Tooltip), 200ms (NavigationMenu) — Tooltip's skipDelayDuration default 300ms.openDelay/closeDelay: 700/300ms.duration: 5000ms; default swipeThreshold: 50.loop defaults to true.