Menus and pickers
Command Palette
Search for an app, a document or a command and run it from the keyboard.
"use client"
import {
Command,
CommandInput,
CommandPalette,
CommandPaletteContent,
CommandPaletteTrigger,
} from "macbetter/command-palette"
import { useState } from "react"
import { Results } from "./results"
export default function Example() {
const [open, setOpen] = useState(false)
return (
<CommandPalette open={open} onOpenChange={setOpen}>
<CommandPaletteTrigger>Search</CommandPaletteTrigger>
<CommandPaletteContent title="Search apps and actions">
<Command
onAction={(value) => {
console.log(value)
setOpen(false)
}}
>
<CommandInput aria-label="Search apps and actions" placeholder="Spotlight Search" />
<Results />
</Command>
</CommandPaletteContent>
</CommandPalette>
)
}When to use it
A command palette is Spotlight for your app: one field that finds any command, page or document, and runs it without a mouse. It's for people who know what they want and would rather type than browse.
- Make it an addition, never the only way to a command.
- Group results by kind, put the best match first, and show each command's shortcut so people learn it.
- Open it with ⌘K, and close it as soon as a command runs.
Usage
import {
Command,
CommandInput,
CommandItem,
CommandList,
CommandPalette,
CommandPaletteContent,
CommandPaletteTrigger,
} from "macbetter/command-palette"CommandPalette is a dialog. CommandPaletteTrigger is a search-field-shaped button that also listens for ⌘K, and CommandPaletteContent is the floating panel. Inside it, Command holds a CommandInput, which draws its own magnifier, and a CommandList of groups and items. Close the palette from onAction.
On its own
Command also works inline, as a panel of its own, for a search page or a sidebar.
"use client"
import { Command, CommandInput } from "macbetter/command-palette"
import { Results } from "./results"
export default function Example() {
return (
<div style={{ width: "min(560px, 100%)" }}>
<Command onAction={(value) => console.log(value)}>
<CommandInput aria-label="Search apps and actions" placeholder="Search apps and actions" />
<Results />
</Command>
</div>
)
}Platform behavior
- macOS: a large translucent panel near the top of the screen, like Spotlight, with a 22-point search field, a hairline under it, and results whose highlighted row fills with the accent. Shortcuts sit at the trailing edge.
- iOS and iPadOS: a rounded card with a capsule search field and 48-point rows. The highlight is gray, as touch highlights are. iOS hides shortcuts; iPadOS shows them.
Accessibility
The palette is a modal dialog named by title, and focus starts in the search field. Arrow keys move the highlight while focus stays in the field, Enter runs the highlighted command, Escape clears the search and then closes the palette, and focus returns to the trigger. Result counts are announced after typing pauses.
API
| Prop | Type | Default | Description |
|---|---|---|---|
CommandPalette | open, onOpenChange | — | The dialog root. |
CommandPaletteTrigger | shortcut | "mod+k" | Opens the palette. Shows the shortcut on the Mac and iPad. |
CommandPaletteContent | title | "Search" | The panel. `title` names it for screen readers. |
Command | onAction, filter, autoHighlight | — | The search and its results. |
CommandInput | input props | — | The search field, with its magnifier. |
CommandItem | value, label, keywords, shortcut, disabled | — | A result. Put a CommandShortcut inside to show its keys. |
CommandItemIcon | — | — | A 22-point icon (28 on touch) before the label. |
CommandGroup, CommandGroupLabel, CommandSeparator | — | — | Organize results. Empty groups disappear. |
CommandEmpty, CommandStatus | — | — | What shows when nothing matches, and loading or error messages. |
--mb-command-width | length | 680px | The panel's width on the Mac. |
--mb-command-highlight | color | accent · gray | The highlighted row's fill. |