Select
StabilnyPozwala wybrać jedną opcję — albo kilka — z listy, która pozostaje schowana, dopóki nie jest potrzebna.
Anatomia
- 1WyzwalaczWygląda jak pole tekstowe i ma te same wysokości, więc w formularzu równa się z pozostałymi polami.
- 2WartośćEtykieta wybranej opcji — albo placeholder w przygaszonym kolorze, gdy nic nie jest wybrane.
- 3IkonaSzewrony w górę i w dół: lista otwiera się, przykrywając wyzwalacz, a wybrana opcja wypada dokładnie w jego miejscu.
Instalacja
$ pnpm dlx shadcn@latest add https://www.prfct.dev/r/select.jsonUżycie
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"const regions = [
{ label: "Select a region", value: null },
{ label: "Frankfurt", value: "fra1" },
{ label: "Tokyo", value: "hnd1" },
]
<Select items={regions}>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectItem value="fra1">Frankfurt</SelectItem>
<SelectItem value="hnd1">Tokyo</SelectItem>
</SelectGroup>
</SelectContent>
</Select>Przekaż items do komponentu głównego. Dzięki temu SelectValue wyświetla etykietę wybranej opcji zamiast jej surowej wartości, a element z value: null staje się placeholderem widocznym, dopóki nic nie jest wybrane. Umieszczaj ten element na liście tylko wtedy, gdy wyczyszczenie wyboru to pełnoprawna opcja — i wtedy nazwij go jak opcję, na przykład Brak roli.
Przykłady
Grupy
Długie listy podziel na grupy z etykietami i oddziel je separatorami. Etykiety niech będą krótkimi rzeczownikami — to nagłówki, a nie opcje, więc nie da się ich wybrać.
Rozmiary
Wyzwalacz ma rozmiary sm, default i lg — te same wysokości 32, 36 i 40 px co Input i Button, więc pasek filtrów układa się w równej linii bez ani jednej własnej klasy.
Wyrównanie do opcji i tryb popper
Domyślnie lista otwiera się wyrównana do wyzwalacza: wybrana opcja leży dokładnie na wyzwalaczu, jak w natywnym menu macOS, więc wzrok nie musi nigdzie wędrować. Ustaw alignItemWithTrigger={false} na SelectContent, aby uzyskać klasyczną listę rozwijaną, która otwiera się pod spodem — to lepszy wybór przy dolnej krawędzi okna, w gęstych paskach narzędzi i wszędzie tam, gdzie zasłonięcie wyzwalacza ukryłoby kontekst.
Zaznaczona opcja nakrywa wyzwalacz — jak w natywnym menu.
Lista rozwija się pod wyzwalaczem i nigdy go nie zasłania.
Wielokrotny wybór
Ustaw multiple, a do defaultValue przekaż tablicę. Funkcja przekazana do SelectValue pozwala zdecydować, ile wybranych opcji wymienić z nazwy, zanim zastąpi je podsumowanie — długie listy po przecinku zostają ucięte i przestają być czytelne.
<Select items={channels} multiple defaultValue={["email", "slack"]}>
<SelectTrigger>
<SelectValue>
{(value: string[]) =>
value.length === 1 ? labelFor(value[0]) : `${value.length} channels`
}
</SelectValue>
</SelectTrigger>
…
</Select>Rozbudowane opcje i obiekty jako wartości
Opcja może zawierać więcej niż samą etykietę. Gdy wartości są obiektami, za pomocą itemToStringValue powiedz liście wyboru, jak serializować je na potrzeby formularzy, a wybraną opcję wyrenderuj sam przez funkcję renderującą SelectValue. Klasa h-auto! pozwoli wyzwalaczowi urosnąć.
Z ikonami i wyłączonymi opcjami
Elementy wizualne na początku opcji — kropki statusu, flagi, awatary — ułatwiają szybkie przejrzenie listy. Umieść je zarówno w opcji, jak i w funkcji renderującej wartość, żeby wyzwalacz odzwierciedlał wybór. Wyłączone opcje pozostają widoczne, więc wiadomo, że istnieją, ale nie da się ich podświetlić ani wybrać.
W formularzu
Połącz z Field, aby dodać etykietę, opis i komunikat błędu. htmlFor w FieldLabel wskazuje id wyzwalacza; name i required wysyłają i walidują wartość jak natywna kontrolka. Aby pokazać błąd, oznacz wyzwalacz atrybutem aria-invalid, a pole — atrybutem data-invalid.
Używany w e-mailach i w panelu.
Wytyczne
Kiedy używać
- Do wyboru spośród pięciu do piętnastu wzajemnie wykluczających się opcji, których nie trzeba porównywać obok siebie.
- Gdy brakuje miejsca, a bieżący wybór jest ważniejszy niż pozostałe możliwości.
Kiedy nie używać
- Przy dwóch do pięciu opcjach, które mieszczą się na ekranie — pokaż je wszystkie za pomocą Radio Group lub Toggle Group; chowanie ich za kliknięciem spowalnia pracę.
- Przy długich listach, które trzeba przeszukiwać — użyj komponentu Combobox.
- Do wywoływania akcji, takich jak Duplikuj czy Usuń — użyj komponentu Dropdown Menu. Lista wyboru przechowuje wartość, a menu wykonuje polecenie.
- Gdy lepiej sprawdzi się natywny selektor platformy, na przykład w formularzach wypełnianych głównie na telefonach — użyj komponentu Native Select.
Kolejność i sformułowania
Układaj opcje tak, jak myślą o nich ludzie: według częstości, według wielkości (Mały, Średni, Duży) albo alfabetycznie — nigdy w kolejności, w jakiej trafiły do bazy danych. Pisz krótkie etykiety o jednakowej budowie, a placeholder niech opisuje czynność (Wybierz region), a nie pole (Region).
Wartości domyślne
Wybierz wartość z góry, gdy istnieje bezpieczna, typowa odpowiedź — większości osób oszczędzisz w ten sposób jednej decyzji. Zostaw listę pustą, gdy zły wybór ma konsekwencje (kraj rozliczeniowy, poziom uprawnień) — wtedy wybór jest świadomy, a walidacja może wychwycić pominięcie.
Dostępność
Wyzwalacz to button z role="combobox", który steruje rozwijaną listą listbox. Base UI zarządza fokusem, aria-expanded, podświetlaniem z klawiatury i wyszukiwaniem przez wpisywanie, a wartość wysyła przez ukryte pole formularza.
| Klawisz | Działanie |
|---|---|
EnterSpacja↓↑ | Otwiera listę z podświetloną wybraną opcją. Gdy lista jest otwarta, Enter lub Spacja wybiera podświetloną opcję. |
↓↑ | Przesuwa podświetlenie między opcjami, pomijając wyłączone. |
HomeEnd | Podświetla pierwszą lub ostatnią opcję. |
A–Z | Wyszukiwanie przez wpisywanie: przechodzi do następnej opcji, która zaczyna się od wpisanych znaków. |
Esc | Zamyka listę bez zmiany wartości i przywraca fokus na wyzwalacz. |
Tab | Zamyka listę i przenosi fokus do następnej kontrolki. |
- Nadaj etykietę każdej liście wyboru. Powiąż widoczny
FieldLabelz wyzwalaczem przezhtmlForalbo nadaj wyzwalaczowiaria-label, gdy kontekst wizualnie jasno pokazuje jego przeznaczenie (na przykład w pasku narzędzi). - Krawędzie. Obramowanie wyzwalacza używa tokenu
input, który ma kontrast co najmniej 3:1 względem strony, zgodnie z WCAG 1.4.11. Stany zaznaczenia i podświetlenia nigdy nie opierają się wyłącznie na kolorze: wybraną opcję oznacza znacznik wyboru. - Rozmiar celu. Opcje mają co najmniej 32 px wysokości, wyzwalacz również — więcej niż minimum 24 × 24 px z WCAG 2.2.
- Modalność. Otwarta lista jest domyślnie modalna: przewijanie strony jest zablokowane, a kliknięcie poza listą najpierw ją zamyka. Ustaw
modal={false}naSelect, jeśli strona musi pozostać interaktywna.
Dokumentacja API
Select
Komponent główny. Nie renderuje żadnego elementu. Przyjmuje wszystkie propsy Select.Root z Base UI.
SelectTrigger
Przycisk, który pokazuje wartość i otwiera listę. Renderuje <button>.
SelectValue
Wyświetla wybór wewnątrz wyzwalacza. Renderuje <span>.
SelectContent
Pozycjonowany popup z przewijaną listą opcji.
SelectItem
Opcja. Renderuje <div> z role="option".
SelectGroup, SelectLabel, SelectSeparator
SelectGroup grupuje opcje (i musi je otaczać), SelectLabel nadaje grupie tytuł, a SelectSeparator rysuje linię podziału między grupami. Przyjmują propsy swoich odpowiedników z Base UI.