Westy Design Systemv0.2.7
OverviewComponentsExamplesStorybook

Foundations

  • Typography
  • Colors
  • Spacing
  • Radius
  • Shadows
  • Icons

Components

  • Accordion
  • Alert
  • Alert Dialog
  • Aspect Ratio
  • Avatar
  • Badge
  • Breadcrumb
  • Button
  • Button Group
  • Calendar
  • Card
  • Carousel
  • Chart
  • Checkbox
  • Collapsible
  • Combobox
  • Command
  • Context Menu
  • Data Table
  • Date Picker
  • Dialog
  • Direction
  • Drawer
  • Dropdown Menu
  • Empty
  • Field
  • Hover Card
  • Input
  • Input Group
  • Input OTP
  • Item
  • Kbd
  • Label
  • Menubar
  • Native Select
  • Navigation Menu
  • Pagination
  • Popover
  • Progress
  • Questionnaire
  • Radio Group
  • Resizable
  • Scroll Area
  • Select
  • Separator
  • Sheet
  • Sidebar
  • Skeleton
  • Slider
  • Sonner
  • Spinner
  • Switch
  • Table
  • Tabs
  • Textarea
  • Toggle
  • Toggle Group
  • Tooltip

Chat

  • Attachment
  • Bubble
  • Marker
  • Message
  • Message Scroller

Components

Command

Command menu for search and quick actions, built on cmdk.

Playground

No results found.
Suggestions
Calendar
Search Emoji
Calculator
Settings
Profile⌘P
Billing⌘B
Settings⌘S
—CommandItem children
—CommandShortcut
—CommandItem disabled
—loop
Usage
Command wraps a CommandInput and a CommandList. Inside the list, CommandEmpty renders when nothing matches, CommandGroup labels a set of CommandItems via heading, and CommandSeparator divides groups. Typing filters items automatically — matching happens against each item's text content.
No results found.
Suggestions
Calendar
Search Emoji
Calculator
Settings
Profile
Billing
Settings
import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
  CommandSeparator,
} from "@workspace/ui/components/command"

<Command className="max-w-sm rounded-lg border">
  <CommandInput placeholder="Type a command or search..." />
  <CommandList>
    <CommandEmpty>No results found.</CommandEmpty>
    <CommandGroup heading="Suggestions">
      <CommandItem>Calendar</CommandItem>
      <CommandItem>Search Emoji</CommandItem>
      <CommandItem>Calculator</CommandItem>
    </CommandGroup>
    <CommandSeparator />
    <CommandGroup heading="Settings">
      <CommandItem>Profile</CommandItem>
      <CommandItem>Billing</CommandItem>
      <CommandItem>Settings</CommandItem>
    </CommandGroup>
  </CommandList>
</Command>
Dialog
CommandDialog presents the menu as a modal palette — it renders a Dialog positioned at the top third of the screen with an sr-only title and description. Control it with open / onOpenChange and toggle it from a global ⌘K listener. Run an action from onSelect on each item.

or press ⌘K

Command Palette

Search for a command to run...

const [open, setOpen] = React.useState(false)

React.useEffect(() => {
  function down(event: KeyboardEvent) {
    if (event.key === "k" && (event.metaKey || event.ctrlKey)) {
      event.preventDefault()
      setOpen((current) => !current)
    }
  }

  document.addEventListener("keydown", down)
  return () => document.removeEventListener("keydown", down)
}, [])

<CommandDialog open={open} onOpenChange={setOpen}>
  <Command>
    <CommandInput placeholder="Type a command or search..." />
    <CommandList>
      <CommandEmpty>No results found.</CommandEmpty>
      <CommandGroup heading="Suggestions">
        <CommandItem onSelect={() => setOpen(false)}>
          <CalendarBlankIcon />
          <span>Calendar</span>
        </CommandItem>
        {/* ... */}
      </CommandGroup>
    </CommandList>
  </Command>
</CommandDialog>
Icons and shortcuts
Items lay out with gap-2 and size any svg to size-4, so an icon followed by a span just works. CommandShortcut pushes itself to the end with ms-auto to display the keyboard shortcut — it is presentational only, the key handling is up to you. Disabled items skip filtering, pointer and keyboard selection.
No results found.
Suggestions
Calendar
Search Emoji
Calculator
Settings
Profile⌘P
Billing⌘B
Settings⌘S
<Command className="max-w-sm rounded-lg border">
  <CommandInput placeholder="Type a command or search..." />
  <CommandList>
    <CommandEmpty>No results found.</CommandEmpty>
    <CommandGroup heading="Suggestions">
      <CommandItem>
        <CalendarBlankIcon />
        <span>Calendar</span>
      </CommandItem>
      <CommandItem>
        <SmileyIcon />
        <span>Search Emoji</span>
      </CommandItem>
      <CommandItem disabled>
        <CalculatorIcon />
        <span>Calculator</span>
      </CommandItem>
    </CommandGroup>
    <CommandSeparator />
    <CommandGroup heading="Settings">
      <CommandItem>
        <UserIcon />
        <span>Profile</span>
        <CommandShortcut>⌘P</CommandShortcut>
      </CommandItem>
      <CommandItem>
        <CreditCardIcon />
        <span>Billing</span>
        <CommandShortcut>⌘B</CommandShortcut>
      </CommandItem>
      <CommandItem>
        <GearIcon />
        <span>Settings</span>
        <CommandShortcut>⌘S</CommandShortcut>
      </CommandItem>
    </CommandGroup>
  </CommandList>
</Command>
Scrollable
CommandList caps its height at max-h-72 and scrolls beyond it, with scroll-py-1 keeping the selected item clear of the edges as you arrow through. Override the cap with a max-h-* class on CommandList.
No results found.
Navigation
Home⌘H
Inbox⌘I
Documents⌘D
Folders⌘F
Actions
New File⌘N
New Folder⇧⌘N
Copy⌘C
Cut⌘X
Paste⌘V
Delete⌫
Account
Profile
Billing
Settings
Notifications
Help & Support
<Command className="max-w-sm rounded-lg border">
  <CommandInput placeholder="Type a command or search..." />
  <CommandList>
    <CommandEmpty>No results found.</CommandEmpty>
    <CommandGroup heading="Navigation">
      <CommandItem>
        <HouseIcon />
        <span>Home</span>
        <CommandShortcut>⌘H</CommandShortcut>
      </CommandItem>
      {/* ... */}
    </CommandGroup>
    <CommandSeparator />
    <CommandGroup heading="Actions">{/* ... */}</CommandGroup>
    <CommandSeparator />
    <CommandGroup heading="Account">{/* ... */}</CommandGroup>
  </CommandList>
</Command>
RTL
The layout uses logical properties throughout — the search icon, shortcuts, and item padding all mirror when you set dir="rtl" on the Command root.
لم يتم العثور على نتائج.
اقتراحات
التقويم
البحث عن الرموز التعبيرية
الآلة الحاسبة
الإعدادات
الملف الشخصي⌘P
الفوترة⌘B
<Command dir="rtl" className="max-w-sm rounded-lg border">
  <CommandInput placeholder="اكتب أمرًا أو ابحث..." />
  <CommandList>
    <CommandEmpty>لم يتم العثور على نتائج.</CommandEmpty>
    <CommandGroup heading="اقتراحات">
      <CommandItem>التقويم</CommandItem>
      <CommandItem>البحث عن الرموز التعبيرية</CommandItem>
      <CommandItem disabled>الآلة الحاسبة</CommandItem>
    </CommandGroup>
    <CommandSeparator />
    <CommandGroup heading="الإعدادات">
      <CommandItem>
        الملف الشخصي
        <CommandShortcut>⌘P</CommandShortcut>
      </CommandItem>
      <CommandItem>
        الفوترة
        <CommandShortcut>⌘B</CommandShortcut>
      </CommandItem>
    </CommandGroup>
  </CommandList>
</Command>
Accessibility
cmdk implements the combobox pattern: the input renders as role="combobox" pointing at a role="listbox" list whose items are role="option", with selection tracked through aria-activedescendant. Arrow keys (plus Home / End) move the selection, Enter runs the item's onSelect, and Escape closes CommandDialog. Name the menu with the label prop — CommandDialog already provides an sr-only title and description you can override.
<Command label="Command palette">{/* inline usage */}</Command>

<CommandDialog
  title="Command Palette"
  description="Search for a command to run..."
>
  {/* rendered as sr-only DialogTitle / DialogDescription */}
</CommandDialog>
API Reference
Nine parts wrap cmdk: Command as the stateful root, CommandInput (an InputGroup with a built-in search icon), CommandList, CommandEmpty, CommandGroup, CommandItem, CommandSeparator, CommandShortcut, and CommandDialog composing the whole menu into a Dialog. Filtering, sorting, and selection state all live in the root — items register themselves automatically. All parts accept their underlying element props.
ComponentPropDefault
Commandvalue?: string, onValueChange?: (value: string) => void, defaultValue?: string—
Commandloop?: boolean, shouldFilter?: boolean, filter?: (value, search, keywords) => numberfalse / true
CommandDialogtitle?: string, description?: string, showCloseButton?: boolean, ...Dialog propsshowCloseButton: false
CommandGroupheading?: ReactNode, value?: string—
CommandItemvalue?: string, keywords?: string[], disabled?: boolean, onSelect?: (value: string) => void—
<Command data-slot="command" />
<CommandInput data-slot="command-input" />
<CommandList data-slot="command-list" />
<CommandEmpty data-slot="command-empty" />
<CommandGroup data-slot="command-group" />
<CommandItem data-slot="command-item" />
<CommandShortcut data-slot="command-shortcut" />
<CommandSeparator data-slot="command-separator" />

Tokens used

13 design tokens consumed by the Command component.

  • --popover

    Popover

    bg-popover
  • --popover-foreground

    Popover Foreground

    text-popover-foreground
  • --foreground

    Foreground

    text-foregrounddata-selected:text-foreground
  • --muted

    Muted

    data-selected:bg-muted
  • --muted-foreground

    Muted Foreground

    text-muted-foreground**:[[cmdk-group-heading]]:text-muted-foreground
  • --input

    Input

    border-input/30bg-input/30
  • --border

    Border

    bg-border
  • --text-sm

    Text Small (14px)

    text-sm
  • --text-xs

    Text Extra Small (12px)

    text-xs**:[[cmdk-group-heading]]:text-xs
  • --radius-sm

    Radius 0.6× (6px)

    rounded-sm
  • --radius-lg

    Radius 1× (10px)

    rounded-lg!
  • --radius-xl

    Radius 1.4× (14px)

    rounded-xl!
  • --spacing

    Spacing unit (4px)

    p-1px-2py-1.5gap-2size-4h-8!max-h-72