Combobox
StabilnyPole tekstowe z filtrowaną listą do wyboru spośród większej liczby opcji, niż wygodnie pomieści lista wyboru.
Instalacja
$ pnpm dlx shadcn@latest add https://www.prfct.dev/r/combobox.jsonUżycie
import {
Combobox,
ComboboxContent,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
} from "@/components/ui/combobox"const frameworks = ["Next.js", "Remix", "Astro", "SvelteKit"]
<Combobox items={frameworks}>
<ComboboxInput placeholder="Search frameworks…" />
<ComboboxContent>
<ComboboxEmpty>No frameworks found.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item} value={item}>
{item}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>Przekaż komponentowi głównemu pełną tablicę items, a listę renderuj funkcją: Base UI filtruje pozycje w trakcie pisania i wywołuje funkcję tylko dla trafień. ComboboxEmpty pojawia się automatycznie, gdy nic nie pasuje.
Przykłady
Czyszczenie wartości
Gdy pole ma wartość, showClear zamienia strzałkę na przycisk czyszczenia. Dodawaj go zawsze, gdy pusta wartość jest poprawna — zadanie bez przypisanej osoby, brak filtra — żeby nikt nie musiał zaznaczać tekstu i go kasować.
Grupy
Grupy to po prostu pozycje z własną tablicą items. Renderuj je za pomocą ComboboxGroup, nagłówka ComboboxLabel i ComboboxCollection dla elementów grupy; podczas filtrowania grupa zostaje na liście tylko wtedy, gdy ma trafienia. InputGroupAddon przekazany jako element potomny dodaje ikonę na początku pola.
Wybór wielokrotny
Wybrane wartości stają się chipami wewnątrz pola. useComboboxAnchor zwraca ref do kontenera chipów, dzięki czemu lista jest wyrównana do całego pola, a nie tylko do inputu tekstowego. autoHighlight sprawia z kolei, że w trakcie pisania Enter wybiera pierwsze trafienie.
Naciśnij Backspace w pustym polu, aby usunąć ostatnią etykietę.
Rozbudowane opcje
Opcja może pokazywać wszystko, co pomaga rozpoznać właściwą — awatar i adres e-mail odróżnią dwie osoby o tym samym imieniu i nazwisku. Gdy wartościami są obiekty, itemToStringLabel decyduje, co trafia do pola, a itemToStringValue — co wysyła formularz.
Przycisk jako wyzwalacz
Gdy pole ma wyglądać jak przycisk — przełącznik repozytoriów, filtr na pasku narzędzi — wyrenderuj ComboboxTrigger jako Button, a pole tekstowe przenieś do popupu z showTrigger={false}.
Wyszukiwanie po stronie serwera
Gdy dane są na serwerze, ustaw filter={null}, żeby wyłączyć lokalne filtrowanie w Base UI, pobieraj wyniki w onInputValueChange i przekazuj je z powrotem jako items. Nie wysyłaj zapytania po każdym znaku (debounce), ignoruj nieaktualne odpowiedzi i pokazuj, że wyszukiwanie trwa — tutaj ikona lupy zamienia się w spinner.
Wytyczne
Kiedy używać
- Przy długich listach — krajów, osób, stref czasowych, repozytoriów — gdzie wpisanie kilku liter jest szybsze niż przewijanie.
- Gdy użytkownicy zwykle wiedzą, czego szukają.
- Do wyboru kilku wartości z długiej listy: etykiet, odbiorców, tagów.
Kiedy nie używać
- Przy mniej niż około piętnastu opcjach, które użytkownicy raczej przeglądają, niż przeszukują — użyj Select.
- Do dowolnego tekstu z opcjonalnymi podpowiedziami, np. w polu wyszukiwania — użyj Input z własną listą sugestii; wartością Comboboxa może być tylko jedna z jego pozycji.
- Do uruchamiania poleceń — użyj palety Command.
Dopasowywanie
Dopasowuj w dowolnym miejscu etykiety, nie tylko od początku (york powinno znaleźć New York), i ignoruj wielkość liter oraz znaki diakrytyczne (krakow powinno znaleźć Kraków — przekaż locale, gdy dane nie są po angielsku). Najbardziej prawdopodobne trafienia pokazuj na początku, a stan pusty formułuj konkretnie: powiedz, czego nie znaleziono, i jeśli to możliwe — co zrobić zamiast tego.
Dostępność
Pole ma role="combobox", aria-expanded i aria-autocomplete="list" oraz steruje rozwijaną listą listbox. Zgodnie z wzorcem ARIA combobox fokus zostaje w polu, a po opcjach przesuwa się podświetlenie.
| Klawisz | Działanie |
|---|---|
A–Z | Wpisywanie filtruje listę i ją otwiera. |
↓↑ | Otwiera listę i przesuwa podświetlenie. Na obu końcach listy podświetlenie wraca do pola. |
Enter | Wybiera podświetloną opcję. |
Esc | Zamyka listę; tekst w polu zostaje. |
Backspace | Przy wyborze wielokrotnym, gdy pole jest puste, usuwa ostatni chip. |
Tab | Przenosi fokus do następnej kontrolki i zamyka listę. |
- Opisz pole etykietą. Powiąż widoczny
FieldLabelzidpola albo użyjaria-labelna paskach narzędzi. - Informuj o ładowaniu. Gdy wyniki przychodzą z serwera, nadaj spinnerowi dostępną etykietę (komponent
Spinnerma domyślnie etykietę Loading) i zadbaj, żeby tekst stanu pustego był zrozumiały. - Chipy. Przycisk usuwania w każdym chipie bierze nazwę od chipu — „Usuń Design”, a nie samo „przycisk” — w języku ustawionym przez LocaleProvider. Gdy treść chipu nie jest zwykłym tekstem, przekaż
removeLabel. Przyciski usuwania są poza kolejnością tabulacji; z klawiatury chipy usuwa się klawiszem Backspace. - Przycisk rozwijania. Strzałka ma etykietę „Pokaż lub ukryj opcje” i jest pomijana przez Tab — to ułatwienie dla myszy, a z klawiatury listę otwiera już samo pole.
- Krawędzie i obszary klikalne. Obramowanie pola korzysta z tokenu
input(3:1, WCAG 1.4.11); opcje mają co najmniej 32 px wysokości.
Dokumentacja API
Combobox
Komponent główny. Nie renderuje żadnego elementu. Przyjmuje wszystkie propsy Combobox.Root z Base UI.
ComboboxInput
Pole tekstowe renderowane wewnątrz Input Group. Elementy potomne trafiają do grupy — np. InputGroupAddon z ikoną.
ComboboxContent
Pozycjonowany popup z listą.
ComboboxList, ComboboxItem, ComboboxEmpty
Grupy
ComboboxGroup przyjmuje items grupy; ComboboxLabel nadaje jej tytuł; ComboboxCollection renderuje jej elementy funkcją; ComboboxSeparator oddziela grupy.
Chipy
ComboboxChips to pole z chipami do wyboru wielokrotnego (podepnij do niego ref z useComboboxAnchor()), ComboboxValue renderuje wybrane wartości funkcją, ComboboxChip pokazuje jedną wartość z przyciskiem usuwania (showRemove, domyślnie true; removeLabel zastępuje jego dostępną nazwę), a ComboboxChipsInput to input tekstowy wewnątrz tego pola.
ComboboxTrigger i ComboboxValue
ComboboxTrigger otwiera listę z własnego elementu — użyj render, żeby był nim Button. ComboboxValue renderuje etykietę bieżącej wartości.