跳到正文

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

名称类型默认值说明版本
itemsCommandPaletteMixedItem[]必填条目和分组({ type: 'group', key, label, children })。未发布
showbooleanundefined受控的显示状态。未发布
defaultShowbooleanfalse非受控时的初始显示状态。未发布
onUpdateShow(show: boolean) => voidundefined显示状态要改变时调用。未发布
querystringundefined受控的搜索文字。未发布
defaultQuerystring''非受控时的初始搜索文字。未发布
onUpdateQuery(query: string) => voidundefined每次编辑搜索文字时调用。未发布
filterboolean | (item, query) => booleantruetrue 不区分大小写地匹配标签或关键词的子串;函数替换匹配规则;false 原样展示 items。未发布
highlightbooleantrue在标签中标出搜索文字。未发布
onSelect(item, event) => voidundefined点击或 Enter 选中时调用。对链接调用 event.preventDefault() 可自行路由。未发布
closeOnSelectbooleantrue选中后关闭。在新标签页打开链接时保持打开。未发布
loadingbooleanfalse在输入框里显示加载指示;没有结果时显示“搜索中…”。未发布
emptyReactNodeundefined搜索没有结果时显示。默认是显示“没有结果”的 Empty。未发布
renderItem(item, { active, query, label }) => ReactNodeundefined替换每一行的内容。未发布
placeholderstringundefined输入框的占位文字,也是它的无障碍名称。默认取语言包。未发布
labelstringundefined对话框的无障碍名称。默认“命令面板”。未发布
footerReactNodeundefined替换底部的键盘提示。未发布
showFooterbooleantrue是否显示底部。内置提示在触屏设备上隐藏。未发布
maskClosablebooleantrue点击遮罩时关闭。未发布
tostring | HTMLElement | falseundefined挂载位置,见 Modal。未发布
zIndexnumberundefined固定的 z-index,而不是叠在之前打开的浮层之上。未发布
onAfterEnter() => voidundefined进入动画结束时调用。未发布
onAfterLeave() => voidundefined离开动画结束时调用。未发布
classNamestringundefined面板表面的类名。未发布
styleCSSPropertiesundefined面板表面的样式。未发布
inputRefRef<HTMLInputElement>undefined搜索输入框。未发布

CommandPaletteItem

名称类型说明
keystring | number在所有条目中唯一。
labelstring显示的文字,参与匹配和高亮。
descriptionReactNode第二行较弱的说明。
iconReactNode显示在标签前。
suffixReactNode显示在行尾。
keywordsstring[]内置过滤额外匹配的词。
hrefstring让这一行成为链接。
targetstring链接的 target。
disabledboolean显示但不能选中。

useCommandPaletteShortcut

useCommandPaletteShortcut(onTrigger, shortcut = "mod+k", { enabled = true }) 在页面任意位置按下快捷键时调用 onTrigger。快捷键由修饰键(mod、ctrl、meta、alt、shift)和一个键用 + 连接组成;mod 在 Apple 平台是 ⌘,其他平台是 Ctrl,需要 Shift 才能打出的符号直接写符号本身(?)。传数组可以监听多个。不带 Ctrl、⌘ 或 Alt 的快捷键(比如 /)在输入框里打字时会被忽略。commandPaletteShortcutKeys(shortcut) 返回当前平台应显示的键帽,比如 ["⌘", "K"]。