跳转到内容

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
属性描述类型默认值
open受控的打开状态boolean-
onOpenChange打开状态改变时的回调函数(open: boolean) => void-
defaultOpen默认打开状态(非受控)booleanfalse
items数据驱动的项配置CommandItemConfig[]-
filter自定义过滤函数(value: string, search: string, keywords?: string[]) => boolean-
loop在边缘处循环键盘导航booleantrue
shortcut全局键盘快捷键string[]['k']
placeholder搜索输入占位符string'输入命令或搜索...'
emptyMessage未找到结果时的消息ReactNode'未找到结果。'
data-testid用于测试的测试 IDstring-

使用数据驱动的 items 属性时:

属性描述类型默认值
key项的唯一键string-
label显示标签ReactNode-
group分类的组名string-
keywords额外的搜索关键词string[]-
disabled禁用项booleanfalse
onSelect选择项时的回调函数() => void-
icon要显示的图标元素ReactNode-
data-testid用于测试的测试 IDstring-

要获得更多控制,请使用复合组件:

组件描述
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 - 返回上一页(当搜索为空时)