Command
A searchable command palette with keyboard navigation and real action callbacks.
Give your AI assistant this page as context.
Connect your library with MCPui/commandUsage
Get this component from a saved library export or the connected CLI. The imports below refer to local files installed in your app.
Import styles/components.css, then styles/theme.css once. Wrap your app in ThemeScope from components/ui/utils so typography, focus and overlays share the theme. The installation guide covers runtime dependencies and React/Next.js setup.
import { Command } from './components/ui/command';
<Command items={[{value:"settings",label:"Open settings",onSelect:()=>console.info("Settings")},{value:"export",label:"Export library",onSelect:()=>console.info("Export")}]} />Design system
This component consumes your semantic colors, spacing, typography and shape tokens. Import the compiled styles and your theme once as described in Export.
Dependencies: Dialog.
Behavior and accessibility
- Provide meaningful labels for interactive controls.
- Connect action callbacks to your application logic.
- Verify keyboard navigation and contrast in your application.
Status: experimental during early access. Sample previews do not send emails, process payments or upload files to a service.
Source and props
This is the exported source, using the same implementation as the editor.
"use client";
import { Combobox as Base } from "@base-ui/react/combobox";
import { Dialog } from "./dialog";
import { useRef, useState, type ReactNode } from "react";
export interface CommandItem {
value: string;
label: string;
description?: string;
onSelect: () => void;
disabled?: boolean;
}
export function Command({
trigger = "Open commands",
title = "Command menu",
items,
open,
onOpenChange,
defaultOpen = false,
searchLabel = "Search commands",
searchPlaceholder = "Search commands…",
emptyMessage = "No matching commands.",
}: {
trigger?: ReactNode;
title?: string;
items: CommandItem[];
open?: boolean;
onOpenChange?: (open: boolean) => void;
defaultOpen?: boolean;
searchLabel?: string;
searchPlaceholder?: string;
emptyMessage?: ReactNode;
}) {
const [internal, setInternal] = useState(defaultOpen);
const input = useRef<HTMLInputElement>(null);
const setOpen = (value: boolean) => {
if (open === undefined) setInternal(value);
onOpenChange?.(value);
};
return (
<Dialog
trigger={trigger}
title={title}
open={open ?? internal}
onOpenChange={setOpen}
initialFocus={input}
>
<Base.Root
items={items}
inline
open={open ?? internal}
autoHighlight
value={null}
itemToStringLabel={(item: CommandItem) => item.label}
onValueChange={(item: CommandItem | null) => {
if (item && !item.disabled) {
item.onSelect();
setOpen(false);
}
}}
>
<Base.Input
ref={input}
className="cr-input"
aria-label={searchLabel}
placeholder={searchPlaceholder}
/>
<Base.Empty className="cr-description">{emptyMessage}</Base.Empty>
<Base.List className="cr-command-list">
{(item: CommandItem) => (
<Base.Item
className="cr-menu-item"
key={item.value}
value={item}
disabled={item.disabled}
>
<span className="cr-command-item-text">
<span>{item.label}</span>
{item.description && (
<small className="cr-description">{item.description}</small>
)}
</span>
</Base.Item>
)}
</Base.List>
</Base.Root>
</Dialog>
);
}