zzzUI

Command

始终展开的操作列表,上方是搜索框:输入文字缩小范围,方向键切换选项,Enter 执行。CommandDialog 让它浮在变暗的页面之上。

安装

terminal
# once per project: where @zzzui items come frompnpm dlx shadcn@latest registry add @zzzui=https://zzzui.catforest.dev/r/{name}.jsonpnpm dlx shadcn@latest add @zzzui/command

示例

内嵌,以及 ⌘K 命令面板

Take the job⌘T
Hand in
Abandon
Job board
District map
Drivers
command-palette.tsx
import { useEffect, useState } from "react";import { Button } from "@/components/zero/button";import {  Command,  CommandCollection,  CommandDialog,  CommandEmpty,  CommandGroup,  CommandGroupLabel,  CommandInput,  CommandItem,  CommandList,  CommandShortcut,} from "@/components/zero/command";type Action = { value: string; label: string; keys?: string };const groups: { value: string; items: Action[] }[] = [  {    value: "Jobs",    items: [      { value: "take", label: "Take the job", keys: "⌘T" },      { value: "hand-in", label: "Hand in" },      { value: "abandon", label: "Abandon" },    ],  },  {    value: "Go to",    items: [      { value: "board", label: "Job board" },      { value: "map", label: "District map" },      { value: "drivers", label: "Drivers" },    ],  },];function Palette({ onRun }: { onRun?: () => void }) {  return (    <Command items={groups}>      <CommandInput placeholder="Type a command" aria-label="Command" />      <CommandList>        {(group: (typeof groups)[number]) => (          <CommandGroup key={group.value} items={group.items}>            <CommandGroupLabel>{group.value}</CommandGroupLabel>            <CommandCollection>              {(item: Action) => (                <CommandItem key={item.value} value={item} onClick={onRun}>                  {item.label}                  {item.keys ? (                    <CommandShortcut>{item.keys}</CommandShortcut>                  ) : null}                </CommandItem>              )}            </CommandCollection>          </CommandGroup>        )}      </CommandList>      <CommandEmpty>Nothing matches.</CommandEmpty>    </Command>  );}export default function CommandPalette() {  const [open, setOpen] = useState(false);  useEffect(() => {    const onKeyDown = (event: KeyboardEvent) => {      if (event.key === "k" && (event.metaKey || event.ctrlKey)) {        event.preventDefault();        setOpen((current) => !current);      }    };    window.addEventListener("keydown", onKeyDown);    return () => window.removeEventListener("keydown", onKeyDown);  }, []);  return (    <div className="grid w-full max-w-md justify-items-start gap-4">      <Palette />      <Button variant="secondary" onClick={() => setOpen(true)}>        Open the palette (⌘K)      </Button>      <CommandDialog open={open} onOpenChange={setOpen}>        <Palette onRun={() => setOpen(false)} />      </CommandDialog>    </div>  );}

行为

第一个匹配项始终处于高亮状态,按 Enter 即可执行。搜索框位于黑色横条上;列表行沿用 Dropdown menu 的样式,高亮时填充强调色。将条目或条目分组传给 Command,并在 CommandList 的函数子元素中渲染;输入的文字与条目的 label 匹配。

组件基于 Base UI 的 Autocomplete 构建,无需其他依赖库。⌘K 快捷键需自行绑定,做法见示例。

属性

Command

属性类型默认值说明
itemsItem[] | Group[]—列出的条目,每项都需要 label。
filter(item, query) => boolean—替换内置的匹配逻辑。

另可传入 Base UI Autocomplete.Root 的全部属性。

CommandDialog

属性类型默认值说明
open / onOpenChangeboolean / (open) => void—是否打开,受控。
titlestring"Command palette"对话框的可访问名称。

CommandInput, CommandList, CommandEmpty, CommandGroup, CommandGroupLabel, CommandCollection, CommandItem, CommandSeparator, CommandShortcut

另可传入 Base UI Autocomplete.Input 的全部属性。