CommandPalette 命令面板
CommandPalette 是放在 Modal 里的一个搜索框加一列命令或页面:⌘K 菜单、快速切换器、站内搜索都可以用它。它参考的是 cmdk、Raycast、Linear 和 Algolia DocSearch。
它不关心数据本身。你传入 items(或分组),它要么用内置的简单匹配过滤,要么原样展示——由你自己在服务端或用全文索引搜索时就是这样。宽屏上它是固定在视口上方的对话框,结果增减时不会上下跳动;640px 以下是全高的底部面板,输入框在顶部,不会被软键盘挡住。
演示
基础用法
用 show 和 onUpdateShow 控制显示,onSelect 收到选中的条目。内置过滤不区分大小写,匹配标签或 keywords 中任意位置的文字,过滤后为空的分组会隐藏,匹配到的文字在标签里高亮。
图标、描述与快捷键
条目可以有 icon、一行 description,以及行尾的 suffix(比如这条命令自己的快捷键)。disabled 的条目会显示,但方向键会跳过它。
用快捷键打开
useCommandPaletteShortcut(onTrigger, "mod+k") 在整个页面上监听快捷键:Apple 平台是 ⌘K,其他平台是 Ctrl+K,并阻止浏览器自己对它的处理。commandPaletteShortcutKeys 返回给 Kbd 用的键帽。在本页获得焦点时按下快捷键试试。
链接
有 href 的条目是真正的链接:点击会跳转,中键或 ⌘ / Ctrl 点击在新标签页打开。用键盘时,Enter 跳转,⌘ / Ctrl / Shift + Enter 在新标签页打开并保持面板打开。target 和普通链接一样生效。
异步搜索
远程或全文搜索时,设置 filter={false},在 onUpdateQuery 里搜索,再把结果作为 items 传入;loading 会显示加载指示,并保留上一次的结果直到新结果到达。这里 onSelect 调用了 event.preventDefault(),自己处理链接的跳转,就像客户端路由那样。
自定义行
renderItem 绘制每一行的内容。它会收到该行是否处于激活状态,以及已经高亮好匹配文字的标签。
无障碍
遵循 WAI-ARIA 的 combobox + listbox 模式。输入框是 combobox,焦点始终留在它上面;↑ / ↓ 移动激活的 option(循环,跳过禁用项),Home / End 跳到首项和末项,Enter 选中,Escape 关闭面板。激活项通过 aria-activedescendant 播报,结果数量由一个 polite 的 live region 播报。确认输入法候选词的按键不会选中条目。分组是以其标签命名的 group。
Props
| 名称 | 类型 | 默认值 | 说明 | 版本 |
|---|---|---|---|---|
items | CommandPaletteMixedItem[] | 必填 | 条目和分组({ type: 'group', key, label, children })。 | 未发布 |
show | boolean | undefined | 受控的显示状态。 | 未发布 |
defaultShow | boolean | false | 非受控时的初始显示状态。 | 未发布 |
onUpdateShow | (show: boolean) => void | undefined | 显示状态要改变时调用。 | 未发布 |
query | string | undefined | 受控的搜索文字。 | 未发布 |
defaultQuery | string | '' | 非受控时的初始搜索文字。 | 未发布 |
onUpdateQuery | (query: string) => void | undefined | 每次编辑搜索文字时调用。 | 未发布 |
filter | boolean | (item, query) => boolean | true | true 不区分大小写地匹配标签或关键词的子串;函数替换匹配规则;false 原样展示 items。 | 未发布 |
highlight | boolean | true | 在标签中标出搜索文字。 | 未发布 |
onSelect | (item, event) => void | undefined | 点击或 Enter 选中时调用。对链接调用 event.preventDefault() 可自行路由。 | 未发布 |
closeOnSelect | boolean | true | 选中后关闭。在新标签页打开链接时保持打开。 | 未发布 |
loading | boolean | false | 在输入框里显示加载指示;没有结果时显示“搜索中…”。 | 未发布 |
empty | ReactNode | undefined | 搜索没有结果时显示。默认是显示“没有结果”的 Empty。 | 未发布 |
renderItem | (item, { active, query, label }) => ReactNode | undefined | 替换每一行的内容。 | 未发布 |
placeholder | string | undefined | 输入框的占位文字,也是它的无障碍名称。默认取语言包。 | 未发布 |
label | string | undefined | 对话框的无障碍名称。默认“命令面板”。 | 未发布 |
footer | ReactNode | undefined | 替换底部的键盘提示。 | 未发布 |
showFooter | boolean | true | 是否显示底部。内置提示在触屏设备上隐藏。 | 未发布 |
maskClosable | boolean | true | 点击遮罩时关闭。 | 未发布 |
to | string | HTMLElement | false | undefined | 挂载位置,见 Modal。 | 未发布 |
zIndex | number | undefined | 固定的 z-index,而不是叠在之前打开的浮层之上。 | 未发布 |
onAfterEnter | () => void | undefined | 进入动画结束时调用。 | 未发布 |
onAfterLeave | () => void | undefined | 离开动画结束时调用。 | 未发布 |
className | string | undefined | 面板表面的类名。 | 未发布 |
style | CSSProperties | undefined | 面板表面的样式。 | 未发布 |
inputRef | Ref<HTMLInputElement> | undefined | 搜索输入框。 | 未发布 |
CommandPaletteItem
| 名称 | 类型 | 说明 |
|---|---|---|
key | string | number | 在所有条目中唯一。 |
label | string | 显示的文字,参与匹配和高亮。 |
description | ReactNode | 第二行较弱的说明。 |
icon | ReactNode | 显示在标签前。 |
suffix | ReactNode | 显示在行尾。 |
keywords | string[] | 内置过滤额外匹配的词。 |
href | string | 让这一行成为链接。 |
target | string | 链接的 target。 |
disabled | boolean | 显示但不能选中。 |
useCommandPaletteShortcut
useCommandPaletteShortcut(onTrigger, shortcut = "mod+k", { enabled = true }) 在页面任意位置按下快捷键时调用 onTrigger。快捷键由修饰键(mod、ctrl、meta、alt、shift)和一个键用 + 连接组成;mod 在 Apple 平台是 ⌘,其他平台是 Ctrl,需要 Shift 才能打出的符号直接写符号本身(?)。传数组可以监听多个。不带 Ctrl、⌘ 或 Alt 的快捷键(比如 /)在输入框里打字时会被忽略。commandPaletteShortcutKeys(shortcut) 返回当前平台应显示的键帽,比如 ["⌘", "K"]。