Aller au contenu

Command

Une palette de commandes (⌘K) pour la recherche et les actions rapides. Prend en charge la navigation au clavier, les éléments groupés, les pages imbriquées et les modèles de composants pilotés par données et composés.

import { Command } from 'asterui'

Utilisation de base

Palette de commandes pilotée par données avec éléments groupés.

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

Composants composés

Créer des palettes de commandes en utilisant des composants composés pour plus de contrôle.

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

Avec icônes

Ajouter des icônes aux éléments de commande pour le contexte visuel.

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

Mots-clés de recherche

Ajouter des mots-clés supplémentaires pour rendre les éléments trouvables par des termes alternatifs.

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

Pages imbriquées

Naviguer vers des sous-pages avec support de navigation arrière. Appuyez sur Retour arrière (lorsque la recherche est vide) ou cliquez sur la flèche arrière pour revenir.

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

Éléments désactivés

Désactiver des éléments spécifiques pour empêcher la sélection.

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

Raccourci personnalisé

Changer le raccourci clavier global de ⌘K à une autre touche.

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

Filtre personnalisé

Fournir une fonction de filtre personnalisée pour une logique de correspondance avancée.

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
PropriétéDescriptionTypeDéfaut
openÉtat d’ouverture contrôléboolean-
onOpenChangeCallback lors du changement d’état d’ouverture(open: boolean) => void-
defaultOpenÉtat d’ouverture par défaut (non contrôlé)booleanfalse
itemsConfiguration d’élément pilotée par donnéesCommandItemConfig[]-
filterFonction de filtre personnalisée(value: string, search: string, keywords?: string[]) => boolean-
loopBoucler la navigation au clavier aux extrémitésbooleantrue
shortcutTouche(s) de raccourci clavier globalstring[]['k']
placeholderEspace réservé d’entrée de recherchestring'Type a command or search...'
emptyMessageMessage lorsqu’aucun résultat n’est trouvéReactNode'No results found.'
data-testidID de test pour les testsstring-

Lors de l’utilisation de la prop items pilotée par données :

PropriétéDescriptionTypeDéfaut
keyClé unique pour l’élémentstring-
labelLibellé d’affichageReactNode-
groupNom de groupe pour la catégorisationstring-
keywordsMots-clés de recherche supplémentairesstring[]-
disabledDésactiver l’élémentbooleanfalse
onSelectCallback lorsque l’élément est sélectionné() => void-
iconÉlément d’icône à afficherReactNode-
data-testidID de test pour les testsstring-

Pour plus de contrôle, utilisez des composants composés :

ComposantDescription
Command.ListConteneur pour les groupes et les éléments
Command.GroupGrouper les éléments avec en-tête optionnel
Command.ItemÉlément de commande sélectionnable
Command.EmptyAffiché lorsqu’aucun résultat ne correspond
Command.PagePage imbriquée pour la navigation
Command.SeparatorSéparateur visuel entre les sections
  • Utilise l’élément natif <dialog> pour le piégeage du focus et la gestion d’ESC
  • L’entrée de recherche a role="combobox" avec les attributs ARIA appropriés
  • La liste utilise role="listbox" avec des éléments role="option"
  • Navigation au clavier avec les touches fléchées, Entrée pour sélectionner, Échap pour fermer
  • aria-activedescendant suit l’élément surligné
  • Les groupes utilisent role="group" avec aria-label
  • ⌘K / Ctrl+K - Ouvrir la palette de commandes (personnalisable)
  • - Naviguer dans les éléments
  • Entrée - Sélectionner l’élément surligné
  • Échap - Fermer la palette (ou revenir en arrière sur la page imbriquée)
  • Retour arrière - Revenir à la page précédente (lorsque la recherche est vide)