Pular para o conteúdo

Command

Uma paleta de comandos (⌘K) para pesquisa rápida e ações. Suporta navegação por teclado, itens agrupados, páginas aninhadas e padrões orientados a dados e de componentes compostos.

import { Command } from 'asterui'

Uso Básico

Paleta de comandos orientada a dados com itens agrupados.

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

Componentes Compostos

Construir paletas de comandos usando componentes compostos para mais controle.

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

Com Ícones

Adicionar ícones aos itens de comando para contexto visual.

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

Palavras-chave de Pesquisa

Adicionar palavras-chave extras para tornar itens encontráveis por termos alternativos.

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

Páginas Aninhadas

Navegar para subpáginas com suporte de navegação de retorno. Pressione Backspace (quando a pesquisa estiver vazia) ou clique na seta de voltar para retornar.

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

Itens Desabilitados

Desabilitar itens específicos para prevenir seleção.

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

Atalho Personalizado

Mudar o atalho de teclado global de ⌘K para outra tecla.

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

Filtro Personalizado

Fornecer uma função de filtro personalizada para lógica de correspondência avançada.

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
PropriedadeDescriçãoTipoPadrão
openEstado aberto controladoboolean-
onOpenChangeCallback quando o estado aberto muda(open: boolean) => void-
defaultOpenEstado aberto padrão (não controlado)booleanfalse
itemsConfiguração de itens orientada a dadosCommandItemConfig[]-
filterFunção de filtro personalizada(value: string, search: string, keywords?: string[]) => boolean-
loopLoop de navegação por teclado nas bordasbooleantrue
shortcutTecla(s) de atalho de teclado globalstring[]['k']
placeholderPlaceholder do input de pesquisastring'Type a command or search...'
emptyMessageMensagem quando nenhum resultado é encontradoReactNode'No results found.'
data-testidID de teste para testesstring-

Ao usar a prop items orientada a dados:

PropriedadeDescriçãoTipoPadrão
keyChave única para o itemstring-
labelRótulo de exibiçãoReactNode-
groupNome do grupo para categorizaçãostring-
keywordsPalavras-chave de pesquisa adicionaisstring[]-
disabledDesabilitar o itembooleanfalse
onSelectCallback quando o item é selecionado() => void-
iconElemento de ícone para exibirReactNode-
data-testidID de teste para testesstring-

Para mais controle, use componentes compostos:

ComponenteDescrição
Command.ListContêiner para grupos e itens
Command.GroupAgrupa itens com título opcional
Command.ItemItem de comando selecionável
Command.EmptyMostrado quando nenhum resultado corresponde
Command.PagePágina aninhada para navegação
Command.SeparatorSeparador visual entre seções
  • Usa elemento <dialog> nativo para captura de foco e tratamento de ESC
  • Input de pesquisa tem role="combobox" com atributos ARIA apropriados
  • Lista usa role="listbox" com itens role="option"
  • Navegação por teclado com teclas de seta, Enter para selecionar, Escape para fechar
  • aria-activedescendant rastreia o item destacado
  • Grupos usam role="group" com aria-label
  • ⌘K / Ctrl+K - Abrir paleta de comandos (personalizável)
  • - Navegar itens
  • Enter - Selecionar item destacado
  • Escape - Fechar paleta (ou voltar na página aninhada)
  • Backspace - Voltar para página anterior (quando a pesquisa está vazia)