Command Menu
componentry/command-menuFreeComponent
A macOS Spotlight-style command menu with animated search, keyboard navigation, and customizable groups. Features backdrop blur, smooth animations, and full keyboard support.
Live preview
live · rendered by the registry
Rendered by componentry on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://componentry.dev/r/command-menu.jsonSource
1"use client"23import * as React from "react"4import * as ReactDOM from "react-dom"5import { Command } from "cmdk"6import { Search, ArrowRight, X } from "lucide-react"7import { motion, AnimatePresence } from "framer-motion"89import { cn } from "@/lib/utils"1011export interface CommandMenuItem {12 id: string13 title: string14 group?: string15 icon?: React.ReactNode16 onSelect?: () => void17}1819export interface CommandMenuGroup {20 title: string21 items: CommandMenuItem[]22}2324export interface CommandMenuProps {25 groups: CommandMenuGroup[]26 placeholder?: string27 emptyMessage?: string28 brandName?: string29 triggerClassName?: string30 triggerLabel?: string31 shortcutKey?: string32 open?: boolean33 onOpenChange?: (open: boolean) => void34}3536function CommandMenu({37 groups,38 placeholder = "Search...",39 emptyMessage = "No results found",40 brandName = "Command Menu",41 triggerClassName,42 triggerLabel = "Search...",43 shortcutKey = "K",44 open: controlledOpen,45 onOpenChange,46}: CommandMenuProps) {47 const [internalOpen, setInternalOpen] = React.useState(false)48 const [query, setQuery] = React.useState("")49 const inputRef = React.useRef<HTMLInputElement>(null)5051 const isControlled = controlledOpen !== undefined52 const open = isControlled ? controlledOpen : internalOpen53 const setOpen = isControlled ? (onOpenChange ?? (() => {})) : setInternalOpen5455 React.useEffect(() => {56 const down = (e: KeyboardEvent) => {57 if (e.key.toLowerCase() === shortcutKey.toLowerCase() && (e.metaKey || e.ctrlKey)) {58 e.preventDefault()59 setOpen(!open)60 }61 if (e.key === "Escape") {62 setOpen(false)63 }64 }6566 document.addEventListener("keydown", down)67 return () => document.removeEventListener("keydown", down)68 }, [open, setOpen, shortcutKey])6970 React.useEffect(() => {71 if (open) {72 setTimeout(() => {73 inputRef.current?.focus()74 }, 0)75 } else {76 setQuery("")77 }78 }, [open])7980 const handleSelect = React.useCallback((item: CommandMenuItem) => {81 setOpen(false)82 item.onSelect?.()83 }, [setOpen])8485 return (86 <>87 <button88 onClick={() => setOpen(true)}89 className={cn(90 "group inline-flex items-center gap-2 whitespace-nowrap transition-all duration-200",91 "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50",92 "disabled:pointer-events-none disabled:opacity-50",93// … truncated
More from componentry
All 59 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Animated Gradientanimated-gradient | componentry | Components | Free | no deps | |
| ASCII Effectascii-effect | componentry | Components | Free | no deps | |
| Aurora Flowaurora-flow | componentry | Components | Free | no deps | |
| auth-modalauth-modal | componentry | Components | Free | no deps | |
| border-beamborder-beam | componentry | Components | Free | no deps | |
| circuit-boardcircuit-board | componentry | Components | Free | no deps | |
| closing-plasmaclosing-plasma | componentry | Components | Free | no deps | |
| collection-surfercollection-surfer | componentry | Components | Free | no deps |
