Command 命令面板
用于快速搜索和操作的命令面板(⌘K)。支持键盘导航、分组项、嵌套页面,以及数据驱动和复合组件模式。
import { Command } from 'asterui'基本用法
带分组项的数据驱动命令面板。
import { Command, Button } from 'asterui'
import { useState } from 'react'
function App() {
const [open, setOpen] = useState(false);
const items = [
{ key: 'new-file', label: 'Create New File', group: 'Actions' },
{ key: 'new-folder', label: 'Create New Folder', group: 'Actions' },
{ key: 'search', label: 'Search Files', group: 'Actions' },
{ key: 'home', label: 'Go to Home', group: 'Navigation' },
{ key: 'settings', label: 'Open Settings', group: 'Navigation' },
{ key: 'profile', label: 'View Profile', group: 'Navigation' },
];
return (
<>
<Button color="primary" onClick={() => setOpen(true)}>
Open Command Palette
</Button>
<Command
open={open}
onOpenChange={setOpen}
items={items}
placeholder="Type a command or search..."
/>
</>
)
}
export default App 复合组件
使用复合组件构建命令面板以获得更多控制。
import { Command, Button } from 'asterui'
import { useState } from 'react'
function App() {
const [open, setOpen] = useState(false);
return (
<>
<Button color="primary" onClick={() => setOpen(true)}>
Open Command Palette
</Button>
<Command open={open} onOpenChange={setOpen}>
<Command.List>
<Command.Empty>No results found</Command.Empty>
<Command.Group heading="Actions">
<Command.Item onSelect={() => alert('Creating file...')}>
Create New File
</Command.Item>
<Command.Item onSelect={() => alert('Creating folder...')}>
Create New Folder
</Command.Item>
</Command.Group>
<Command.Separator />
<Command.Group heading="Navigation">
<Command.Item onSelect={() => alert('Going home...')}>
Go to Home
</Command.Item>
<Command.Item onSelect={() => alert('Opening settings...')}>
Open Settings
</Command.Item>
</Command.Group>
</Command.List>
</Command>
</>
)
}
export default App 带图标
为命令项添加图标以提供视觉上下文。
import { Command, Button } from 'asterui'
import { useState } from 'react'
function App() {
const [open, setOpen] = useState(false);
const items = [
{ key: 'new-file', label: 'Create New File', group: 'Actions', icon: <FileIcon /> },
{ key: 'new-folder', label: 'Create New Folder', group: 'Actions', icon: <FolderIcon /> },
{ key: 'search', label: 'Search Files', group: 'Actions', icon: <SearchIcon /> },
{ key: 'home', label: 'Go to Home', group: 'Navigation', icon: <HomeIcon /> },
{ key: 'settings', label: 'Open Settings', group: 'Navigation', icon: <SettingsIcon /> },
];
return (
<>
<Button color="primary" onClick={() => setOpen(true)}>
Open Command Palette
</Button>
<Command
open={open}
onOpenChange={setOpen}
items={items}
placeholder="Type a command or search..."
/>
</>
)
}
export default App 搜索关键词
添加额外的关键词使项可以通过替代术语找到。
import { Command, Button } from 'asterui'
import { useState } from 'react'
function App() {
const [open, setOpen] = useState(false);
const items = [
{
key: 'new-file',
label: 'Create New File',
group: 'Actions',
keywords: ['add', 'create', 'new', 'file', 'document']
},
{
key: 'search',
label: 'Search Files',
group: 'Actions',
keywords: ['find', 'lookup', 'query']
},
{
key: 'settings',
label: 'Open Settings',
group: 'Navigation',
keywords: ['preferences', 'config', 'options']
},
{
key: 'profile',
label: 'View Profile',
group: 'Navigation',
keywords: ['user', 'account', 'me']
},
];
return (
<>
<Button color="primary" onClick={() => setOpen(true)}>
Open (try searching "preferences")
</Button>
<Command
open={open}
onOpenChange={setOpen}
items={items}
placeholder="Try 'preferences' or 'config'..."
/>
</>
)
}
export default App 嵌套页面
导航到带返回导航支持的子页面。在搜索为空时按 Backspace 或点击返回箭头返回。
import { Command, Button } from 'asterui'
import { useState } from 'react'
function App() {
const [open, setOpen] = useState(false);
return (
<>
<Button color="primary" onClick={() => setOpen(true)}>
Open Command Palette
</Button>
<Command open={open} onOpenChange={setOpen}>
<Command.List>
<Command.Empty>No results found</Command.Empty>
{/* Root page content */}
<Command.Group heading="Quick Actions">
<Command.Item onSelect={() => alert('Creating file...')}>
Create New File
</Command.Item>
<Command.Item onSelect={() => alert('Searching...')}>
Search Files
</Command.Item>
</Command.Group>
<Command.Separator />
<Command.Group heading="Navigate">
<Command.Item value="settings-menu">
Settings →
</Command.Item>
<Command.Item value="theme-menu">
Theme →
</Command.Item>
</Command.Group>
{/* Settings page */}
<Command.Page id="settings">
<Command.Group heading="Settings">
<Command.Item onSelect={() => alert('Opening account settings...')}>
Account
</Command.Item>
<Command.Item onSelect={() => alert('Opening privacy settings...')}>
Privacy
</Command.Item>
<Command.Item onSelect={() => alert('Opening notification settings...')}>
Notifications
</Command.Item>
</Command.Group>
</Command.Page>
{/* Theme page */}
<Command.Page id="theme">
<Command.Group heading="Choose Theme">
<Command.Item onSelect={() => alert('Theme set to Light')}>
Light
</Command.Item>
<Command.Item onSelect={() => alert('Theme set to Dark')}>
Dark
</Command.Item>
<Command.Item onSelect={() => alert('Theme set to System')}>
System
</Command.Item>
</Command.Group>
</Command.Page>
</Command.List>
</Command>
</>
)
}
export default App 禁用项
禁用特定项以防止选择。
import { Command, Button } from 'asterui'
import { useState } from 'react'
function App() {
const [open, setOpen] = useState(false);
const items = [
{ key: 'new-file', label: 'Create New File', group: 'Actions' },
{ key: 'new-folder', label: 'Create New Folder', group: 'Actions', disabled: true },
{ key: 'search', label: 'Search Files', group: 'Actions' },
{ key: 'delete', label: 'Delete Files', group: 'Danger', disabled: true },
];
return (
<>
<Button color="primary" onClick={() => setOpen(true)}>
Open Command Palette
</Button>
<Command
open={open}
onOpenChange={setOpen}
items={items}
placeholder="Some items are disabled..."
/>
</>
)
}
export default App 自定义快捷键
将全局键盘快捷键从 ⌘K 更改为另一个键。
import { Command, Button, Space } from 'asterui'
import { useState } from 'react'
function App() {
const [open1, setOpen1] = useState(false);
const [open2, setOpen2] = useState(false);
const items = [
{ key: 'action1', label: 'Action 1' },
{ key: 'action2', label: 'Action 2' },
];
return (
<>
<Space direction="horizontal" size="sm">
<Button onClick={() => setOpen1(true)}>
Default (⌘K)
</Button>
<Button onClick={() => setOpen2(true)}>
Custom (⌘J)
</Button>
</Space>
<Command
open={open1}
onOpenChange={setOpen1}
items={items}
placeholder="Default shortcut ⌘K..."
/>
<Command
open={open2}
onOpenChange={setOpen2}
items={items}
shortcut={['j']}
placeholder="Custom shortcut ⌘J..."
/>
</>
)
}
export default App 自定义过滤
提供自定义过滤函数以实现高级匹配逻辑。
import { Command, Button } from 'asterui'
import { useState } from 'react'
function App() {
const [open, setOpen] = useState(false);
const items = [
{ key: 'apple', label: 'Apple', keywords: ['fruit', 'red'] },
{ key: 'banana', label: 'Banana', keywords: ['fruit', 'yellow'] },
{ key: 'carrot', label: 'Carrot', keywords: ['vegetable', 'orange'] },
{ key: 'date', label: 'Date', keywords: ['fruit', 'brown'] },
];
// Custom filter that only matches from the start of words
const customFilter = (value: string, search: string, keywords?: string[]) => {
const searchLower = search.toLowerCase();
if (value.toLowerCase().startsWith(searchLower)) return true;
return (keywords || []).some(k => k.toLowerCase().startsWith(searchLower));
};
return (
<>
<Button color="primary" onClick={() => setOpen(true)}>
Open (prefix matching only)
</Button>
<Command
open={open}
onOpenChange={setOpen}
items={items}
filter={customFilter}
placeholder="Type 'fr' for fruits..."
/>
</>
)
}
export default App Command
Section titled “Command”| 属性 | 描述 | 类型 | 默认值 |
|---|---|---|---|
open | 受控的打开状态 | boolean | - |
onOpenChange | 打开状态改变时的回调函数 | (open: boolean) => void | - |
defaultOpen | 默认打开状态(非受控) | boolean | false |
items | 数据驱动的项配置 | CommandItemConfig[] | - |
filter | 自定义过滤函数 | (value: string, search: string, keywords?: string[]) => boolean | - |
loop | 在边缘处循环键盘导航 | boolean | true |
shortcut | 全局键盘快捷键 | string[] | ['k'] |
placeholder | 搜索输入占位符 | string | '输入命令或搜索...' |
emptyMessage | 未找到结果时的消息 | ReactNode | '未找到结果。' |
data-testid | 用于测试的测试 ID | string | - |
CommandItemConfig
Section titled “CommandItemConfig”使用数据驱动的 items 属性时:
| 属性 | 描述 | 类型 | 默认值 |
|---|---|---|---|
key | 项的唯一键 | string | - |
label | 显示标签 | ReactNode | - |
group | 分类的组名 | string | - |
keywords | 额外的搜索关键词 | string[] | - |
disabled | 禁用项 | boolean | false |
onSelect | 选择项时的回调函数 | () => void | - |
icon | 要显示的图标元素 | ReactNode | - |
data-testid | 用于测试的测试 ID | string | - |
要获得更多控制,请使用复合组件:
| 组件 | 描述 |
|---|---|
Command.List | 组和项的容器 |
Command.Group | 带可选标题的分组项 |
Command.Item | 可选择的命令项 |
Command.Empty | 无匹配结果时显示 |
Command.Page | 用于导航的嵌套页面 |
Command.Separator | 部分之间的视觉分隔符 |
- 使用原生
<dialog>元素进行焦点捕获和 ESC 处理 - 搜索输入具有
role="combobox"及适当的 ARIA 属性 - 列表使用
role="listbox"及role="option"项 - 方向键键盘导航,Enter 选择,Escape 关闭
aria-activedescendant跟踪高亮的项- 组使用
role="group"及aria-label
⌘K/Ctrl+K- 打开命令面板(可自定义)↑↓- 导航项Enter- 选择高亮的项Escape- 关闭面板(或在嵌套页面上返回)Backspace- 返回上一页(当搜索为空时)