Design System

Overlay Molecules

ImportCC

Available via @stackmates/ui-interactive/molecules

Drawer

Slide-out panel built on Headless UI Dialog. Supports 4 positions with close button, overlay, and compound sub-components (DrawerHeader, DrawerBody, DrawerFooter).

DrawerProps

PropTypeDefaultDescription
open*booleanWhether the drawer is open
onClose*() => voidCallback when the drawer should close
position'left' | 'right' | 'top' | 'bottom''right'Slide-in position
showCloseButtonbooleantrueShow the X close button
showOverlaybooleantrueShow backdrop overlay

Installation

typescript
import { Drawer, DrawerHeader, DrawerBody, DrawerFooter } from '@stackmates/ui-interactive/molecules';

Accessibility

  • Headless UI Dialog with focus trapping and Escape to close
  • Close button has sr-only "Close panel" label
  • Respects prefers-reduced-motion for transitions

SheetRx

Radix-based side panel with animated slide transitions. Compound component pattern: Sheet, SheetTrigger, SheetContent, SheetHeader, SheetTitle, SheetDescription, SheetFooter.

Sheet / SheetContent

PropTypeDefaultDescription
side'top' | 'right' | 'bottom' | 'left''right'Slide-in side (on SheetContent)
openbooleanControlled open state (on Sheet root)
onOpenChange(open: boolean) => voidOpen state change callback (on Sheet root)

Installation

typescript
import { Sheet, SheetTrigger, SheetContent, SheetHeader, SheetTitle, SheetDescription, SheetFooter, SheetClose } from '@stackmates/ui-interactive/molecules';

Accessibility

  • Radix Dialog with focus trapping, scroll locking, and Escape to dismiss
  • Close button has sr-only "Close" label
  • Animated enter/exit with configurable duration

DropdownMenu

Radix-based dropdown context menu with icon, shortcut, checkbox, radio, sub-menu, and destructive item support.

DropdownMenuItem (enhanced)

PropTypeDefaultDescription
iconLucideIconIcon before item label (on DropdownMenuItem)
shortcutstringKeyboard shortcut hint on the right (on DropdownMenuItem)
variant'default' | 'destructive''default'Visual variant (on DropdownMenuItem)

Installation

typescript
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuCheckboxItem, DropdownMenuRadioItem, DropdownMenuRadioGroup } from '@stackmates/ui-interactive/molecules';

Accessibility

  • Full keyboard navigation (Arrow keys, Enter, Escape) with typeahead
  • Proper role="menu" and role="menuitem" ARIA attributes
  • Disabled items excluded from keyboard navigation

Command

Command palette built on cmdk. Compound component with search input, grouped items, empty state, and keyboard shortcuts. Use CommandDialog for modal overlay variant.

Command

PropTypeDefaultDescription
children*ReactNodeCommandInput, CommandList, CommandGroup, CommandItem composition
classNamestringAdditional CSS classes on the Command root

Installation

typescript
import { Command, CommandDialog, CommandInput, CommandList, CommandGroup, CommandItem, CommandEmpty, CommandSeparator, CommandShortcut } from '@stackmates/ui-interactive/molecules';

Accessibility

  • Built on cmdk with full keyboard navigation and auto-filtering
  • Search input auto-focused inside CommandDialog
  • Items support aria-selected state

Combobox

Searchable dropdown built on Headless UI Combobox. Supports custom filtering, virtual scrolling, and render-prop children for option rendering.

ComboboxProps<T>

PropTypeDefaultDescription
options*T[]Array of options to display
displayValue*(value: T | null) => string | undefinedExtract display string from an option
filter(value: T, query: string) => booleanCustom filter. Falls back to displayValue includes check.
placeholderstringPlaceholder text for the input
children*(value: T) => ReactElementRender function for each option row

Installation

typescript
import { Combobox, ComboboxOption, ComboboxLabel, ComboboxDescription } from '@stackmates/ui-interactive/molecules';

Accessibility

  • Headless UI ARIA combobox pattern with aria-label support
  • Arrow keys + Enter for keyboard navigation and selection
  • Selected option shows check icon indicator

ContextMenuRx

Right-click context menu built on Radix ContextMenu. Supports items, checkbox items, radio items, sub-menus, labels, separators, and keyboard shortcuts.

Right-click here

ContextMenuItem / ContextMenuCheckboxItem

PropTypeDefaultDescription
variant'default' | 'destructive''default'Visual variant (on ContextMenuItem)
insetbooleanIndent to align with icon items (on ContextMenuItem)
checkedbooleanChecked state (on ContextMenuCheckboxItem)

Installation

typescript
import { ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem, ContextMenuCheckboxItem, ContextMenuRadioItem, ContextMenuRadioGroup, ContextMenuLabel, ContextMenuSeparator, ContextMenuSub, ContextMenuSubTrigger, ContextMenuSubContent } from '@stackmates/ui-interactive/molecules';

Accessibility

  • Activated via right-click or long-press on touch devices
  • Full keyboard navigation with role="menu" ARIA attributes
  • CheckboxItem and RadioItem announce their state
Related:

HoverCardRx

Hover-triggered popover card built on Radix HoverCard. Displays rich content on pointer hover with animated enter/exit transitions.

HoverCardContent

PropTypeDefaultDescription
align'start' | 'center' | 'end''center'Alignment relative to trigger (on HoverCardContent)
sideOffsetnumber4Distance in px from trigger (on HoverCardContent)

Installation

typescript
import { HoverCard, HoverCardTrigger, HoverCardContent } from '@stackmates/ui-interactive/molecules';

Accessibility

  • Content accessible via pointer hover and focus (Radix Portal)
  • Not suitable for essential info (hover unavailable on touch)
  • Use Tooltip for brief labels; HoverCard for rich previews

TooltipRx

Radix-based tooltip with arrow indicator and animated enter/exit transitions. Rx suffix avoids conflict with atoms/Tooltip. Wraps its own TooltipProvider with zero delay by default.

TooltipRx / TooltipContentRx

PropTypeDefaultDescription
sideOffsetnumber0Distance in px from the trigger (on TooltipContentRx)
side'top' | 'right' | 'bottom' | 'left''top'Preferred side of the trigger (on TooltipContentRx)
align'start' | 'center' | 'end''center'Alignment along the side edge (on TooltipContentRx)
delayDurationnumber0Delay in ms before tooltip shows (on TooltipProviderRx)

Installation

typescript
import { TooltipRx, TooltipTriggerRx, TooltipContentRx, TooltipProviderRx } from '@stackmates/ui-interactive/molecules';

Usage

Icon button with tooltip

tsx
<TooltipRx>
  <TooltipTriggerRx asChild>
    <Button variant="ghost" size="icon">
      <Settings className="h-4 w-4" />
    </Button>
  </TooltipTriggerRx>
  <TooltipContentRx side="bottom">
    Settings
  </TooltipContentRx>
</TooltipRx>

Accessibility

  • Radix Tooltip provides aria-describedby linking trigger to content
  • Content portaled to document body to avoid clipping
  • Arrow element rendered with matching background color for visual continuity

Popover

Click-triggered floating content panel built on Radix Popover. Supports configurable alignment, side, offset, arrow, and collision avoidance. Dismisses on click outside or Escape.

PopoverContent

PropTypeDefaultDescription
align'start' | 'center' | 'end''center'Alignment relative to trigger (on PopoverContent)
side'top' | 'right' | 'bottom' | 'left''bottom'Preferred side of the trigger (on PopoverContent)
sideOffsetnumber4Distance in px from trigger (on PopoverContent)
showArrowbooleanfalseShow arrow pointing to trigger (on PopoverContent)

Installation

typescript
import { Popover, PopoverTrigger, PopoverContent, PopoverAnchor } from '@stackmates/ui-interactive/molecules';

Usage

Settings popover

tsx
<Popover>
  <PopoverTrigger asChild>
    <Button variant="outline">Settings</Button>
  </PopoverTrigger>
  <PopoverContent className="w-80">
    <div className="space-y-2">
      <h4 className="font-medium">Preferences</h4>
      <p className="text-sm text-muted-foreground">Configure options.</p>
    </div>
  </PopoverContent>
</Popover>

Accessibility

  • Built on Radix Popover with focus management
  • Escape closes the popover and returns focus to trigger
  • Click outside dismisses by default (configurable)
  • Content portaled to avoid clipping

DialogRx

Modal dialog built on Radix Dialog. Compound component with overlay, content, header, title, description, footer, and close button. Supports both controlled and uncontrolled modes.

DialogRx (root)

PropTypeDefaultDescription
openbooleanControlled open state
onOpenChange(open: boolean) => voidCallback when open state changes
defaultOpenbooleanfalseInitial open state (uncontrolled)

Installation

typescript
import {
  Dialog, DialogTrigger, DialogContent,
  DialogHeader, DialogTitle, DialogDescription,
  DialogFooter, DialogClose,
} from '@stackmates/ui-interactive/molecules';

Usage

Edit form dialog

tsx
<Dialog>
  <DialogTrigger asChild>
    <Button>Edit</Button>
  </DialogTrigger>
  <DialogContent>
    <DialogHeader>
      <DialogTitle>Edit Item</DialogTitle>
      <DialogDescription>Make changes here.</DialogDescription>
    </DialogHeader>
    <form>...</form>
    <DialogFooter>
      <Button type="submit">Save</Button>
    </DialogFooter>
  </DialogContent>
</Dialog>

Accessibility

  • Built on Radix Dialog with role="dialog" and aria-modal
  • Focus trapped inside the dialog while open
  • Escape key and close button dismiss the dialog
  • Overlay click dismisses (unlike AlertDialog)