Command Palette with Argument Chips
moumenlab/command-paletteFreeComponent
Commands that take inline argument chips, fuzzy ranking, and a measured height morph.
Live preview
live · rendered by the registry
Rendered by moumenlab on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://lab.moumen.dev/r/command-palette.jsonSource
1"use client";23import { Fragment, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, type ReactNode } from "react";4import { MotionConfig, motion, useReducedMotion } from "motion/react";56// Command palette with argument chips - Linear-style multi-step commands inside7// a single input.8//9// The hard problem is focus choreography. A command like "Assign to [person]10// with priority [level]" is really a tiny form; the obvious build gives each11// picked value its own focusable element - then Tab order, Backspace and12// screen-reader context all fracture mid-command. Here the palette has exactly13// ONE focusable control, the text input, for its whole life:14//15// · Picking a command collapses it into a CHIP painted before the input (the16// chip is render output, not a field). The list slides to that command's17// first argument slot and the same input now filters the options.18// · Filling a command's last slot STAGES it as a clause instead of running19// it - the list slides back to the remaining commands joined by an "and",20// so one session builds a compound. Nothing runs until ✓ Apply (⌘⏎);21// ✕ discards the whole stack.22// · Backspace on an empty query POPS the last chip - across the "and" too.23// Chips never join the tab order but ARE clickable: clicking one rewinds24// to that slot; the tail dims to preview the rewind scope.25//26// Matching is a fuzzy subsequence ("mvp" finds "Move to project") scored with27// word-start + adjacency bonuses minus a gap penalty, matched letters28// underlined in place. The list body's height is a measured px that motion29// eases between filter states and view swaps; pushes slide in from the right,30// pops from the left; chips grow in and pop instantly (Backspace must feel31// immediate). Pass your own `commands` and handle `onApply`.32//33// Animation via motion/react; honours prefers-reduced-motion. Requires the34// lab-theme tokens. Fully Tailwind, no CSS files.3536const EASE = [0.22, 1, 0.36, 1] as const;37const EASE_ICON = [0.2, 0, 0, 1] as const;38const SLIDE = 28; // 1.75rem directional slide3940export interface CommandOption {41 value: string;42 hint?: string;43 dot?: string;44}45export interface CommandSlot {46 name: string;47 prompt: string;48 kind: "person" | "dot" | "plain";49 options: CommandOption[];50}51export interface Command {52 id: string;53 label: string;54 icon?: ReactNode;55 shortcut?: string;56 danger?: boolean;57 slots: CommandSlot[];58// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from moumenlab
All 14 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Caret-Anchored Mention Popovercaret-mention-popover | moumenlab | Components | Free | 1 dep | |
| Drag-to-Reorder Listdrag-to-reorder-list | moumenlab | Components | Free | 1 dep | |
| File Upload Staging Areafile-upload-staging | moumenlab | Components | Free | 1 dep | |
| Hover-Expand Icon Striphover-expand-icon-strip | moumenlab | Components | Free | 1 dep | |
| Inertial Wheel Listinertial-wheel-list | moumenlab | Components | Free | 1 dep | |
| Morphing Checkout Flowmorphing-checkout | moumenlab | Components | Free | 1 dep | |
| OTP Segmented Inputotp-segmented-input | moumenlab | Components | Free | 1 dep | |
| Schedule Builderschedule-builder | moumenlab | Components | Free | 1 dep |
