Components
Command
A dialog-based command palette — a trigger (or application hotkey) opens a dialog with a search input on top and a filtered, keyboard-navigable list below.
Installation
- $npx litefy@latest add command
- $pnpm dlx litefy@latest add command
- $yarn dlx litefy@latest add command
- $bun --bun litefy@latest add command
Usage
"use client";import * as React from "react";import { Command, Kbd } from "@/ui";import { FilePlus, FolderPlus, House, Keyboard, LogOut, Moon, Search, Settings, UserRound,} from "lucide-react";const items = [ { group: "Actions", items: [ { label: "Create file", value: "new-file", icon: <FilePlus />, shortcut: "⌘N" }, { label: "Create folder", value: "new-folder", icon: <FolderPlus />, shortcut: "⇧⌘N" }, ], }, { group: "Navigation", items: [ { label: "Go home", value: "home", icon: <House /> }, { label: "Open settings", value: "settings", icon: <Settings />, shortcut: "⌘,", keywords: ["preferences"] }, { label: "View profile", value: "profile", icon: <UserRound /> }, ], }, { group: "Preferences", items: [ { label: "Toggle theme", value: "theme", icon: <Moon />, keywords: ["dark", "light"] }, { label: "Keyboard shortcuts", value: "shortcuts", icon: <Keyboard />, shortcut: "⌘/" }, { label: "Sign out", value: "sign-out", icon: <LogOut />, disabled: true }, ], },];export default function Demo() { const [open, setOpen] = React.useState(false); const [lastRun, setLastRun] = React.useState<string | null>(null); React.useEffect(() => { const onKeyDown = (e: KeyboardEvent) => { if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") { e.preventDefault(); setOpen(true); } }; window.addEventListener("keydown", onKeyDown); return () => window.removeEventListener("keydown", onKeyDown); }, []); return ( <div className="flex flex-col items-center gap-4"> <Command trigger={ <> <Search /> Search commands… <Kbd className="h-6 min-w-6 px-1.5 text-[10px]">⌘K</Kbd> </> } items={items} open={open} onOpenChange={setOpen} placeholder="Type a command or search…" onSelect={(item) => setLastRun(typeof item.label === "string" ? item.label : (item.value ?? "Command")) } /> {lastRun && ( <p className="text-sm text-muted-foreground"> Last command: <span className="font-medium text-foreground">{lastRun}</span> </p> )} </div> );}Parts
"use client";import * as React from "react";import { CommandInput, CommandList, CommandRoot, type CommandConfig } from "@/ui";import { Calendar, FileText, Folder, Settings, Users } from "lucide-react";const items: CommandConfig[] = [ { group: "Workspace", items: [ { label: "New document", value: "new-doc", icon: <FileText /> }, { label: "New event", value: "new-event", icon: <Calendar /> }, ], }, { group: "General", items: [ { label: "Team members", value: "team", icon: <Users /> }, { label: "New folder", value: "new-folder", icon: <Folder /> }, { label: "Settings", value: "settings", icon: <Settings /> }, ], },];export default function Demo() { const [lastRun, setLastRun] = React.useState<string | null>(null); return ( <div className="flex flex-col items-center gap-4"> <CommandRoot items={items} className="w-80 rounded-xl border shadow-elevated" onSelect={(item) => setLastRun(item.value ?? null)} > <CommandInput placeholder="Search…" /> <CommandList className="max-h-64" /> </CommandRoot> {lastRun && ( <p className="text-sm text-muted-foreground"> Last command: <span className="font-medium text-foreground">{lastRun}</span> </p> )} </div> );}API Reference
Command
| Prop | Type | Default | Description |
|---|---|---|---|
items | (CommandItemConfig | CommandGroupConfig)[] | - | Commands or grouped commands. Required |
trigger | React.ReactNode | - | Trigger content, rendered as a primary button that opens the dialog. Omit to control open yourself |
open | boolean | - | Controlled dialog state |
defaultOpen | boolean | false | Initial state (uncontrolled) |
onOpenChange | (open: boolean) => void | - | Dialog state callback |
onSelect | (item: CommandItemConfig) => void | - | Fired when a command is chosen; the dialog closes afterwards |
filter | (item, keyword) => boolean | substring match | Custom filter; default matches value, string label and keywords |
renderItem | (item, { highlighted, disabled }) => React.ReactNode | icon + label + shortcut | Custom row rendering |
placeholder | string | - | Search input placeholder |
empty | React.ReactNode | "No results" | Empty state node |
className | ClassNameValue | - | Custom classes, applied to the <dialog> element |
classNames | trigger / content / input / list / item / label | - | Custom classes per part |
styles | content / list / item / label | - | Inline styles per part |
CommandItemConfig
| Prop | Type | Default | Description |
|---|---|---|---|
label | React.ReactNode | - | Row label. Required |
value | string | - | Stable key and default filter text |
icon | React.ReactNode | - | Leading icon |
shortcut | React.ReactNode | - | Keyboard hint, rendered as a Kbd on the right |
keywords | string[] | - | Extra filter-only terms |
disabled | boolean | false | Not selectable; skipped by filtering and keyboard navigation |
CommandGroupConfig
| Prop | Type | Description |
|---|---|---|
group | string | Group title, rendered as a section header. Required |
items | CommandItemConfig[] | Commands in the group. Required |
CommandRoot / CommandInput / CommandList
| Part | Props | Description |
|---|---|---|
CommandRoot | items, open?, filter?, onSelect?, className | Context provider and panel container |
CommandInput | placeholder?, autoFocus?, className | Search input |
CommandList | empty?, renderItem?, className, classNames (item / label), styles | Filtered list |
Combobox
An input with a filterable dropdown list — local options with client-side filtering, or async remote search with debounced fetching and scroll-to-load-more
Date Picker
A date picker built on the native Temporal API — an editable input, a month panel and pointer-anchored popover in one shipped component