Przejdź do treści

Command

Stabilny

Szybka, projektowana z myślą o klawiaturze lista poleceń i wyników z wyszukiwaniem rozmytym — osadzona w stronie albo jako paleta ⌘K nad jej treścią.

Brak wyników.

Anatomia

  1. 1Pole wyszukiwaniaFiltruje listę w trakcie pisania. Fokus zostaje tutaj, a strzałki przesuwają podświetlenie.
  2. 2Nagłówek grupyOpisuje zestaw powiązanych wyników. Nagłówki zostają na miejscu, gdy ich pozycje są filtrowane.
  3. 3Podświetlona pozycjaPozycja, którą uruchomi Enter. Podświetlenie podąża za strzałkami i kursorem.
  4. 4SkrótKlawisze, które uruchamiają pozycję bez otwierania palety. Pełni wyłącznie funkcję informacyjną.

Instalacja

$ pnpm dlx shadcn@latest add https://www.prfct.dev/r/command.json

Użycie

import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
} from "@/components/ui/command"
<Command>
  <CommandInput placeholder="Type a command or search…" />
  <CommandList>
    <CommandEmpty>No results found.</CommandEmpty>
    <CommandGroup heading="Suggestions">
      <CommandItem onSelect={() => openCalendar()}>Calendar</CommandItem>
      <CommandItem onSelect={() => openEmoji()}>Search emoji</CommandItem>
    </CommandGroup>
  </CommandList>
</Command>

Command opiera się na cmdk. W trakcie pisania filtruje pozycje i układa je według trafności, zawsze trzyma jedną z nich podświetloną i uruchamia jej onSelect po naciśnięciu Enter lub kliknięciu. Gdy zmieniają się wyniki, lista płynnie animuje swoją wysokość, więc paleta nigdy nie skacze.

Przykłady

Osadzony w treści

Renderuj Command bezpośrednio, gdy selektor albo launcher ma być osadzony w stronie. Grupy ułatwiają przeglądanie wyników, a CommandShortcut podpowiada szybszą drogę.

Brak wyników.

Paleta poleceń

CommandDialog umieszcza listę poleceń w oknie Dialog zakotwiczonym wysoko na ekranie, więc wyniki rosną w dół, a pole wyszukiwania się nie przesuwa. Przypisz paletę do skrótu K (ten przykład używa J, żeby nie kolidować z wyszukiwarką tej strony, zbudowaną z tego samego komponentu) i dodaj CommandFooter z podpowiedziami klawiszy.

const [open, setOpen] = React.useState(false)

React.useEffect(() => {
  const onKeyDown = (event: KeyboardEvent) => {
    if (event.key === "k" && (event.metaKey || event.ctrlKey)) {
      event.preventDefault()
      setOpen((value) => !value)
    }
  }
  document.addEventListener("keydown", onKeyDown)
  return () => document.removeEventListener("keydown", onKeyDown)
}, [])

return (
  <CommandDialog open={open} onOpenChange={setOpen}>
    <CommandInput placeholder="Search…" />
    <CommandList>{/* groups and items */}</CommandList>
    <CommandFooter />
  </CommandDialog>
)

Stan pusty

CommandEmpty renderuje się tylko wtedy, gdy nic nie pasuje. Zadbaj, żeby był przydatny: powiedz, czego szukano, i zaproponuj, co zrobić dalej.

Nie znaleziono repozytoriówSprawdź pisownię albo szukaj we wszystkich organizacjach z prefiksem org:

Słowa kluczowe i aliasy

Użytkownicy szukają własnymi słowami. Dodaj keywords, żeby tryb ciemny znajdował Wygląd, a faktura — Płatności. Słowa kluczowe liczą się przy dopasowaniu, ale nie są wyświetlane.

Brak pasujących ustawień.

Wybór wielokrotny

W selektorach, w których można zaznaczyć kilka wartości, nie zamykaj listy po wybraniu pozycji i ustawiaj na pozycjach data-checked — prfct wyświetli na ich końcu znacznik wyboru.

Nie znaleziono etykiet.

Wyniki asynchroniczne

Gdy wyniki przychodzą z serwera, wyłącz wbudowane filtrowanie przez shouldFilter={false}, steruj wyszukiwaniem za pomocą valueonValueChange na CommandInput i renderuj pobrane pozycje.

<Command shouldFilter={false}>
  <CommandInput value={query} onValueChange={setQuery} />
  <CommandList>
    {isLoading && <CommandEmpty>Searching…</CommandEmpty>}
    {results.map((result) => (
      <CommandItem key={result.id} value={result.id} onSelect={open}>
        {result.title}
      </CommandItem>
    ))}
  </CommandList>
</Command>

Wytyczne

Kiedy używać

  • Jako globalna paleta ( K) do nawigacji i akcji w aplikacjach, które mają więcej niż kilka ekranów.
  • Jako osadzona lista z wyszukiwaniem tam, gdzie Select już nie wystarcza: przypisane osoby, etykiety, emoji, pliki.

Kiedy nie używać

  • Do wyboru pojedynczej wartości w formularzu — kontrolką formularza jest Combobox, z widoczną wartością, walidacją i etykietą.
  • Do krótkich, stałych list akcji — Dropdown Menu szybciej się przegląda, niż przeszukuje.
  • Gdy paleta miałaby być jedyną drogą do polecenia. Paleta to skrót; wszystko, co w niej jest, powinno istnieć także w interfejsie.

Nazywanie pozycji

Nazywaj pozycje tak, jak ludzie ich szukają: miejsca docelowe rzeczownikami (Ustawienia, Płatności), akcje wyrażeniami z czasownikiem (Utwórz projekt…, Zaproś do zespołu…). Wielokropek dodawaj do pozycji, które wymagają dalszych danych. Grupuj wyniki według rodzaju — Nawigacja, Akcje, Ostatnie — a najbardziej prawdopodobne trzymaj w pierwszej grupie.

Akcje
Utwórz projekt… ⌘N
Zaproś do zespołu…
Dobrze.Konkretne, łatwe do wyszukania etykiety pogrupowane według rodzaju, ze skrótem, który następnym razem pozwoli pominąć paletę.
Nowy
Sprawy z ludźmi
Różne
Źle.Mgliste etykiety, które nie pasują do niczego, co ludzie faktycznie wpisują.

Kolejność wyników

W trakcie pisania pozycje są szeregowane w obrębie swojej grupy — najpierw dopasowania od początku słowa i całe słowa, na końcu litery rozrzucone po etykiecie — ale grupy zachowują kolejność, w jakiej je renderujesz. Na początku umieść grupę, po którą ludzie sięgają najczęściej. W palecie, która przeszukuje wiele sekcji, np. dokumentację, renderuj wyniki jako jedną grupę, dopóki zapytanie nie jest puste — wtedy podświetlone jest zawsze najlepsze trafienie. Ogranicz keywords do kilku słów: przy długich opisach pasuje niemal każde zapytanie.

Wydajność

cmdk bez trudu radzi sobie z kilkoma tysiącami pozycji. Przy większej liczbie filtruj na serwerze (zobacz Wyniki asynchroniczne) albo ogranicz liczbę renderowanych wyników — lista nie jest wirtualizowana.

Dostępność

Command implementuje wzorzec WAI-ARIA combobox: pole ma rolę combobox i steruje listą listbox, a podświetlona opcja (option) jest ogłaszana przez aria-activedescendant, podczas gdy fokus zostaje w polu — dzięki temu można jednocześnie pisać i nawigować.

KlawiszDziałanie
Podświetla następną lub poprzednią pozycję. Z ustawionym loop przechodzi z końca listy na początek i odwrotnie.
HomeEnd
Podświetla pierwszą lub ostatnią pozycję.
Przeskakuje do ostatniej lub pierwszej pozycji.
AltAlt
Przeskakuje do pierwszej pozycji następnej lub poprzedniej grupy.
CtrlNCtrlJ
Podświetla następną pozycję (wyłączysz to przez vimBindings={false}).
CtrlPCtrlK
Podświetla poprzednią pozycję.
Enter
Wywołuje onSelect podświetlonej pozycji.
Esc
W CommandDialog zamyka paletę i przywraca fokus do elementu, który ją otworzył.
  • Nazwij paletę. CommandDialog renderuje wizualnie ukryty tytuł i opis — przekaż sensowne propsy titledescription.
  • Wyłączone pozycje są pomijane podczas nawigacji i ogłaszane jako niedostępne.
  • Ikony w pozycjach są dekoracyjne; ogłaszany i dopasowywany jest tekst pozycji.

Dokumentacja API

Command

Komponent główny z cmdk.

PropTypDomyślnie
label

Dostępna etykieta menu poleceń.

stringBrak wartości domyślnej
shouldFilter

Ustaw false, żeby samodzielnie filtrować i sortować pozycje, np. wyniki z serwera.

booleantrue
filter

Własna funkcja oceny trafności. Zwróć 0, żeby ukryć pozycję, i 1 dla idealnego dopasowania.

(value: string, search: string, keywords?: string[]) => numberBrak wartości domyślnej
value

Kontrolowana wartość podświetlonej pozycji.

stringBrak wartości domyślnej
defaultValue

Początkowo podświetlona pozycja w trybie niekontrolowanym.

stringBrak wartości domyślnej
onValueChange

Wywoływana, gdy zmienia się podświetlona pozycja.

(value: string) => voidBrak wartości domyślnej
loop

Czy strzałki przechodzą z ostatniej pozycji na pierwszą.

booleanfalse
vimBindings

Włącza nawigację skrótami Ctrl+N/J/P/K.

booleantrue

CommandDialog

Command wewnątrz okna Dialog. Umieść CommandInput, CommandListCommandFooter bezpośrednio w środku — okno samo dostarcza komponent główny Command (jeśli przekażesz własny Command, to on posłuży jako komponent główny). Przyjmuje propsy komponentu głównego Dialog (open, onOpenChange, …), a ponadto:

PropTypDomyślnie
title

Wizualnie ukryty tytuł okna dla technologii wspomagających. Domyślnie komunikat bieżącego języka.

stringmessages.commandPalette
description

Wizualnie ukryty opis okna. Domyślnie komunikat bieżącego języka.

stringmessages.commandDescription
showCloseButton

Pokazuje przycisk zamykania okna.

booleanfalse
className

Klasy dla powierzchni okna.

stringBrak wartości domyślnej
commandProps

Propsy wewnętrznego komponentu głównego Command, np. filter, shouldFilter, loop albo kontrolowane value.

ComponentProps<typeof Command>Brak wartości domyślnej

CommandInput

PropTypDomyślnie
value

Kontrolowany tekst wyszukiwania.

stringBrak wartości domyślnej
onValueChange

Wywoływana przy każdej zmianie wyszukiwanego tekstu.

(search: string) => voidBrak wartości domyślnej
placeholder

Podpowiedź widoczna, gdy pole jest puste.

stringBrak wartości domyślnej

CommandItem

PropTypDomyślnie
onSelect

Wywoływana po naciśnięciu Enter lub kliknięciu.

(value: string) => voidBrak wartości domyślnej
value

Wartość używana do filtrowania i wyboru. Domyślnie treść tekstowa pozycji.

stringBrak wartości domyślnej
keywords

Dodatkowe terminy, do których pozycja pasuje, choć nie są wyświetlane.

string[]Brak wartości domyślnej
disabled

Pomija pozycję podczas nawigacji i ignoruje jej wybór.

booleanfalse
forceMount

Renderuje pozycję zawsze, niezależnie od wyszukiwania.

booleanfalse
data-checked

Pokazuje znacznik wyboru na końcu pozycji w listach wielokrotnego wyboru.

booleanBrak wartości domyślnej

CommandGroup

PropTypDomyślnie
heading

Nagłówek wyświetlany nad grupą i używany jako jej dostępna nazwa.

ReactNodeBrak wartości domyślnej
value

Wymagany, gdy grupa nie ma nagłówka; musi być unikalny.

stringBrak wartości domyślnej
forceMount

Renderuje grupę zawsze, nawet gdy żadna z jej pozycji nie pasuje.

booleanfalse

CommandList, CommandEmpty, CommandSeparator, CommandShortcut, CommandFooter

CommandList to przewijany obszar wyników; jego wysokość nie przekracza min(24rem, 60dvh) i jest animowana. CommandEmpty renderuje się, gdy nie ma wyników. CommandSeparator przyjmuje alwaysRender, żeby pozostać widocznym podczas wyszukiwania. CommandShortcut to czysto prezentacyjna podpowiedź na końcu pozycji. CommandFooter domyślnie renderuje podpowiedzi nawigacji — przekaż własne elementy potomne, żeby je zastąpić.