@cassa/ui-overlay
Layered UI — Dialog, Drawer, Popover, Dropdown Menu, Tooltip, and Tabs. Built on the native <dialog> element and the Popover API, with collision-aware positioning from @floating-ui/dom. Same tokens, CVA variants, and cn() merging as the rest of the system — dark mode is automatic.
Import
import {
Dialog, DialogHeader, DialogTitle, DialogBody, DialogFooter,
Drawer, DrawerHeader, DrawerTitle, DrawerBody,
Popover, PopoverTrigger, PopoverContent,
DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem,
Tooltip,
Tabs, TabList, Tab, TabPanel,
} from '@cassa/ui-overlay'Dialog
A modal built on native <dialog> — focus trap, top-layer stacking, and ::backdrop come from the platform. Controlled through open / onClose.
| Prop | Type | Default | Description |
|---|---|---|---|
| open* | boolean | — | Controlled visibility. |
| onClose* | () => void | — | Called on every dismissal — Escape, backdrop click, or a close button. |
| size | "sm" | "md" | "lg" | "xl" | "md" | Max-width of the panel. |
| closeOnBackdrop | boolean | true | Dismiss when the backdrop is clicked. |
| className | string | — | Merged onto the native <dialog>. |
Drawer
The same native-dialog foundation, sliding in from an edge. Composes with DrawerHeader / DrawerBody / DrawerFooter.
| Prop | Type | Default | Description |
|---|---|---|---|
| open* | boolean | — | Controlled visibility. |
| onClose* | () => void | — | Called on every dismissal. |
| side | "right" | "left" | "right" | Edge the panel slides in from. |
| closeOnBackdrop | boolean | true | Dismiss when the backdrop is clicked. |
Popover
Native Popover API for top-layer rendering and light dismiss, positioned against its trigger with automatic flip and shift. Controlled or uncontrolled.
PopoverTrigger renders the <button> itself — pass text and a className (e.g. buttonVariants(…) from @cassa/ui), not a nested <Button>. Same for DropdownMenuTrigger.
Deployment
Shipped 4 minutes ago from main. All checks passed.
| Prop | Type | Default | Description |
|---|---|---|---|
| open | boolean | — | Controlled open state. Omit for uncontrolled. |
| defaultOpen | boolean | false | Initial state when uncontrolled. |
| onOpenChange | (open: boolean) => void | — | Fires whenever the open state changes. |
| placement | Placement | "bottom-start" | Preferred side. Flips automatically on collision. |
| offset | number | 6 | Gap in px between trigger and content. |
Dropdown Menu
A Popover with menu semantics — role="menu", roving focus, arrow-key navigation, and close-on-select. Pair with DropdownMenuLabel and DropdownMenuSeparator.
| Prop | Type | Default | Description |
|---|---|---|---|
| open | boolean | — | Controlled open state. |
| defaultOpen | boolean | false | Initial state when uncontrolled. |
| onOpenChange | (open: boolean) => void | — | Fires whenever the open state changes. |
| placement | Placement | "bottom-start" | Preferred side. Flips on collision. |
DropdownMenuItem
| Prop | Type | Default | Description |
|---|---|---|---|
| onSelect | () => void | — | Fires on click or Enter/Space, then the menu closes. |
| tone | "default" | "destructive" | "default" | Visual emphasis. |
| disabled | boolean | false | Skips selection and keyboard focus. |
Tooltip
Hover- and focus-triggered, with a configurable delay. Wraps its child in an inline span that carries aria-describedby.
| Prop | Type | Default | Description |
|---|---|---|---|
| content* | React.ReactNode | — | Tooltip contents. |
| placement | Placement | "top" | Preferred side. Flips on collision. |
| delay | number | 200 | Delay in ms before it opens on hover/focus. |
Tabs
Pure WAI-ARIA tabs — roving tabIndex, arrow / Home / End keys, and aria-controls wiring. Only the active panel is mounted.
| Prop | Type | Default | Description |
|---|---|---|---|
| defaultValue* | string | — | Active tab on first render. |
| value | string | — | Controlled active tab. |
| onValueChange | (value: string) => void | — | Fires when the active tab changes. |
Positioning hook
useAnchoredPosition is exported for building your own anchored surfaces — it wraps computePosition and autoUpdate with offset, flip, and shift middleware.
const { setAnchor, setFloating, floatingStyles, placement } = useAnchoredPosition({
placement: 'bottom-start',
offset: 6,
enabled: open,
});