Przejdź do treści

Select

Pozwala wybrać jedną opcję — albo kilka — z listy, która pozostaje schowana, dopóki nie jest potrzebna.

Kod źródłowyBase UIRejestr
import { Field, FieldLabel } from "@/components/ui/field"
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"

const regions = [
  { label: "Wybierz region", value: null },
  { label: "Frankfurt (eu-central-1)", value: "fra1" },
  { label: "Londyn (eu-west-2)", value: "lhr1" },
  { label: "Waszyngton (us-east-1)", value: "iad1" },
  { label: "San Francisco (us-west-1)", value: "sfo1" },
  { label: "Tokio (ap-northeast-1)", value: "hnd1" },
]

export default function SelectDemo() {
  return (
    <Field className="w-72">
      <FieldLabel htmlFor="region">Region wdrożenia</FieldLabel>
      <Select items={regions} defaultValue="fra1">
        <SelectTrigger id="region" className="w-full">
          <SelectValue />
        </SelectTrigger>
        <SelectContent>
          <SelectGroup>
            {regions.slice(1).map((region) => (
              <SelectItem key={region.value} value={region.value}>
                {region.label}
              </SelectItem>
            ))}
          </SelectGroup>
        </SelectContent>
      </Select>
    </Field>
  )
}

Anatomia

  1. 1WyzwalaczWygląda jak pole tekstowe i ma te same wysokości, więc w formularzu równa się z pozostałymi polami.
  2. 2WartośćEtykieta wybranej opcji — albo placeholder w przygaszonym kolorze, gdy nic nie jest wybrane.
  3. 3IkonaStrzałki 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.json

Uż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ć.

import * as React from "react"

import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectLabel,
  SelectSeparator,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"

const timezones = [
  {
    region: "Ameryka",
    zones: [
      { label: "Nowy Jork (GMT−5)", value: "america/new_york" },
      { label: "Chicago (GMT−6)", value: "america/chicago" },
      { label: "Los Angeles (GMT−8)", value: "america/los_angeles" },
      { label: "São Paulo (GMT−3)", value: "america/sao_paulo" },
    ],
  },
  {
    region: "Europa",
    zones: [
      { label: "Londyn (GMT+0)", value: "europe/london" },
      { label: "Berlin (GMT+1)", value: "europe/berlin" },
      { label: "Warszawa (GMT+1)", value: "europe/warsaw" },
    ],
  },
  {
    region: "Azja i Pacyfik",
    zones: [
      { label: "Singapur (GMT+8)", value: "asia/singapore" },
      { label: "Tokio (GMT+9)", value: "asia/tokyo" },
      { label: "Sydney (GMT+11)", value: "australia/sydney" },
    ],
  },
]

const items = [
  { label: "Wybierz strefę czasową", value: null },
  ...timezones.flatMap((group) => group.zones),
]

export default function SelectGroups() {
  return (
    <Select items={items}>
      <SelectTrigger className="w-64" aria-label="Strefa czasowa">
        <SelectValue />
      </SelectTrigger>
      <SelectContent>
        {timezones.map((group, index) => (
          <React.Fragment key={group.region}>
            {index > 0 && <SelectSeparator />}
            <SelectGroup>
              <SelectLabel>{group.region}</SelectLabel>
              {group.zones.map((zone) => (
                <SelectItem key={zone.value} value={zone.value}>
                  {zone.label}
                </SelectItem>
              ))}
            </SelectGroup>
          </React.Fragment>
        ))}
      </SelectContent>
    </Select>
  )
}

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.

import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"

const periods = [
  { label: "Ostatnie 7 dni", value: "7d" },
  { label: "Ostatnie 30 dni", value: "30d" },
  { label: "Ostatnie 90 dni", value: "90d" },
]

const sizes = ["sm", "default", "lg"] as const

export default function SelectSizes() {
  return (
    <div className="flex flex-col items-center gap-4">
      {sizes.map((size) => (
        <div key={size} className="flex items-center gap-2">
          <Select items={periods} defaultValue="30d">
            <SelectTrigger size={size} className="w-40" aria-label="Okres">
              <SelectValue />
            </SelectTrigger>
            <SelectContent>
              <SelectGroup>
                {periods.map((period) => (
                  <SelectItem key={period.value} value={period.value}>
                    {period.label}
                  </SelectItem>
                ))}
              </SelectGroup>
            </SelectContent>
          </Select>
          <Input size={size} placeholder="Filtruj zdarzenia" className="w-40" />
          <Button size={size} variant="outline">
            Eksportuj
          </Button>
        </div>
      ))}
    </div>
  )
}

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.

import { Field, FieldDescription, FieldLabel } from "@/components/ui/field"
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"

const fonts = [
  { label: "Inter", value: "inter" },
  { label: "Geist Mono", value: "geist-mono" },
  { label: "System UI", value: "system" },
  { label: "Georgia", value: "georgia" },
]

function FontSelect({ popper }: { popper?: boolean }) {
  return (
    <Select items={fonts} defaultValue="geist-mono">
      <SelectTrigger
        id={popper ? "font-popper" : "font-aligned"}
        className="w-full"
      >
        <SelectValue />
      </SelectTrigger>
      <SelectContent alignItemWithTrigger={!popper}>
        <SelectGroup>
          {fonts.map((font) => (
            <SelectItem key={font.value} value={font.value}>
              {font.label}
            </SelectItem>
          ))}
        </SelectGroup>
      </SelectContent>
    </Select>
  )
}

export default function SelectPositioning() {
  return (
    <div className="grid w-full max-w-lg gap-8 sm:grid-cols-2">
      <Field>
        <FieldLabel htmlFor="font-aligned">Wyrównanie do opcji</FieldLabel>
        <FontSelect />
        <FieldDescription>
          Zaznaczona opcja nakrywa wyzwalacz — jak w natywnym menu.
        </FieldDescription>
      </Field>
      <Field>
        <FieldLabel htmlFor="font-popper">Popper</FieldLabel>
        <FontSelect popper />
        <FieldDescription>
          Lista rozwija się pod wyzwalaczem i nigdy go nie zasłania.
        </FieldDescription>
      </Field>
    </div>
  )
}

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.

"use client"

import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"

const channels = [
  { label: "E-mail", value: "email" },
  { label: "Powiadomienia push", value: "push" },
  { label: "SMS", value: "sms" },
  { label: "Slack", value: "slack" },
  { label: "Microsoft Teams", value: "teams" },
]

export default function SelectMultiple() {
  return (
    <Select items={channels} multiple defaultValue={["email", "slack"]}>
      <SelectTrigger className="w-64" aria-label="Kanały powiadomień">
        <SelectValue>
          {(value: string[]) => {
            if (value.length === 0) return "Wybierz kanały"
            if (value.length === 1) {
              return channels.find((channel) => channel.value === value[0])
                ?.label
            }
            return `Kanały: ${value.length}`
          }}
        </SelectValue>
      </SelectTrigger>
      <SelectContent>
        <SelectGroup>
          {channels.map((channel) => (
            <SelectItem key={channel.value} value={channel.value}>
              {channel.label}
            </SelectItem>
          ))}
        </SelectGroup>
      </SelectContent>
    </Select>
  )
}
<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ąć: rozmiar to zwykła klasa wysokości, więc wysokość podana w className ją zastępuje.

"use client"

import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"

const plans = [
  {
    name: "Hobby",
    price: "0 $",
    description: "Do projektów osobistych i eksperymentów.",
  },
  {
    name: "Pro",
    price: "20 $",
    description: "Dla profesjonalistów wdrażających na produkcję.",
  },
  {
    name: "Team",
    price: "60 $",
    description: "Wspólne przestrzenie robocze, role i dzienniki audytu.",
  },
]

type Plan = (typeof plans)[number]

function PlanOption({ plan }: { plan: Plan }) {
  return (
    <span className="flex w-full flex-col items-start gap-0.5 text-left">
      <span className="flex w-full items-baseline justify-between gap-4 text-sm font-medium text-foreground">
        {plan.name}
        <span className="font-normal text-muted-foreground tabular-nums">
          {plan.price}/mies.
        </span>
      </span>
      <span className="text-xs whitespace-normal text-muted-foreground">
        {plan.description}
      </span>
    </span>
  )
}

export default function SelectRichItems() {
  return (
    <Select
      defaultValue={plans[1]}
      itemToStringValue={(plan: Plan) => plan.name}
    >
      <SelectTrigger
        className="h-auto w-full max-w-80 py-2.5"
        aria-label="Plan"
      >
        <SelectValue>{(plan: Plan) => <PlanOption plan={plan} />}</SelectValue>
      </SelectTrigger>
      <SelectContent>
        <SelectGroup>
          {plans.map((plan) => (
            <SelectItem key={plan.name} value={plan} className="py-2">
              <PlanOption plan={plan} />
            </SelectItem>
          ))}
        </SelectGroup>
      </SelectContent>
    </Select>
  )
}

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ć.

"use client"

import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"
import { cn } from "@/lib/utils"

const statuses = [
  {
    label: "Backlog",
    value: "backlog",
    dot: "border border-gray-9 bg-transparent",
  },
  { label: "Do zrobienia", value: "todo", dot: "bg-gray-9" },
  { label: "W toku", value: "in-progress", dot: "bg-warning-9" },
  { label: "W przeglądzie", value: "in-review", dot: "bg-brand-9" },
  { label: "Gotowe", value: "done", dot: "bg-success-9" },
  { label: "Anulowane", value: "canceled", dot: "bg-danger-9", disabled: true },
]

function StatusDot({ className }: { className?: string }) {
  return (
    <span
      aria-hidden="true"
      className={cn("size-2 shrink-0 rounded-full", className)}
    />
  )
}

export default function SelectStatus() {
  return (
    <Select items={statuses} defaultValue="in-progress">
      <SelectTrigger className="w-48" aria-label="Status">
        <SelectValue>
          {(value: string) => {
            const status = statuses.find((item) => item.value === value)
            return (
              <>
                <StatusDot className={status?.dot} />
                {status?.label}
              </>
            )
          }}
        </SelectValue>
      </SelectTrigger>
      <SelectContent>
        <SelectGroup>
          {statuses.map((status) => (
            <SelectItem
              key={status.value}
              value={status.value}
              disabled={status.disabled}
            >
              <StatusDot className={status.dot} />
              {status.label}
            </SelectItem>
          ))}
        </SelectGroup>
      </SelectContent>
    </Select>
  )
}

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.

import {
  Field,
  FieldDescription,
  FieldError,
  FieldGroup,
  FieldLabel,
} from "@/components/ui/field"
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"

const roles = [
  { label: "Wybierz rolę", value: null },
  { label: "Przeglądający", value: "viewer" },
  { label: "Edytujący", value: "editor" },
  { label: "Administrator", value: "admin" },
  { label: "Właściciel", value: "owner" },
]

const languages = [
  { label: "English", value: "en" },
  { label: "Polski", value: "pl" },
  { label: "Deutsch", value: "de" },
]

export default function SelectForm() {
  return (
    <FieldGroup className="w-full max-w-sm">
      <Field>
        <FieldLabel htmlFor="language">Język</FieldLabel>
        <Select items={languages} name="language" defaultValue="en">
          <SelectTrigger id="language" className="w-full">
            <SelectValue />
          </SelectTrigger>
          <SelectContent>
            <SelectGroup>
              {languages.map((language) => (
                <SelectItem key={language.value} value={language.value}>
                  {language.label}
                </SelectItem>
              ))}
            </SelectGroup>
          </SelectContent>
        </Select>
        <FieldDescription>Używany w e-mailach i w panelu.</FieldDescription>
      </Field>
      <Field data-invalid>
        <FieldLabel htmlFor="role">Rola</FieldLabel>
        <Select items={roles} name="role" required>
          <SelectTrigger id="role" className="w-full" aria-invalid>
            <SelectValue />
          </SelectTrigger>
          <SelectContent>
            <SelectGroup>
              {roles.slice(1).map((role) => (
                <SelectItem key={role.value} value={role.value}>
                  {role.label}
                </SelectItem>
              ))}
            </SelectGroup>
          </SelectContent>
        </Select>
        <FieldError>Wybierz rolę przed wysłaniem zaproszenia.</FieldError>
      </Field>
      <Field data-disabled>
        <FieldLabel htmlFor="workspace">Przestrzeń robocza</FieldLabel>
        <Select
          items={[{ label: "Acme Inc.", value: "acme" }]}
          defaultValue="acme"
          disabled
        >
          <SelectTrigger id="workspace" className="w-full">
            <SelectValue />
          </SelectTrigger>
          <SelectContent>
            <SelectGroup>
              <SelectItem value="acme">Acme Inc.</SelectItem>
            </SelectGroup>
          </SelectContent>
        </Select>
      </Field>
    </FieldGroup>
  )
}

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).

Rozmiar instancjiMały · 1 vCPUŚredni · 2 vCPUDuży · 4 vCPU
DobrzeOpcje uporządkowane według wielkości, z krótkimi etykietami o tej samej budowie.
large-4cpuMała instancja (1 vCPU)ŚREDNI
ŹlePrzypadkowa kolejność i niespójne etykiety zmuszają do przeczytania każdej opcji.

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.

KlawiszDział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 FieldLabel z wyzwalaczem przez htmlFor albo nadaj wyzwalaczowi aria-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} na Select, jeśli strona musi pozostać interaktywna.

Dokumentacja API

Select

Komponent główny. Nie renderuje żadnego elementu. Przyjmuje wszystkie propsy Select.Root z Base UI.

PropTypDomyślnie
items

Etykiety opcji. Pozwalają SelectValue wyświetlić etykietę zamiast surowej wartości; element z wartością null dostarcza placeholder.

Record<string, ReactNode> | { label, value }[] | Group[]Brak wartości domyślnej
value

Wybrana wartość. W połączeniu z onValueChange tworzy kontrolowaną listę wyboru.

Value | Value[] | nullBrak wartości domyślnej
defaultValue

Początkowo wybrana wartość w trybie niekontrolowanym.

Value | Value[] | nullBrak wartości domyślnej
onValueChange

Wywoływana, gdy zmienia się wybór.

(value, details) => voidBrak wartości domyślnej
multiple

Pozwala wybrać kilka opcji; wartość staje się tablicą.

booleanfalse
itemToStringValue

Serializuje wartości obiektowe na potrzeby wysyłki formularza.

(value) => stringBrak wartości domyślnej
itemToStringLabel

Zamienia wartości obiektowe na tekst wyświetlany w wyzwalaczu.

(value) => stringBrak wartości domyślnej
isItemEqualToValue

Własny sposób porównywania wartości obiektowych. Domyślnie Object.is.

(itemValue, value) => booleanBrak wartości domyślnej
name

Wysyła wartość z formularzem pod tą nazwą.

stringBrak wartości domyślnej
required

Wymaga wybrania wartości przed wysłaniem formularza.

booleanfalse
disabled

Wyłącza całą listę wyboru.

booleanfalse
readOnly

Pokazuje wartość, ale nie pozwala jej zmienić.

booleanfalse
open / defaultOpen / onOpenChange

Sterują widocznością rozwijanej listy.

boolean / boolean / (open, details) => voidBrak wartości domyślnej
modal

Gdy lista jest otwarta, blokuje przewijanie strony i interakcję poza nią.

booleantrue

SelectTrigger

Przycisk, który pokazuje wartość i otwiera listę. Renderuje <button>.

PropTypDomyślnie
size

Wysokość i wewnętrzne odstępy: 32, 36 lub 40 px — takie same jak w Input i Button.

"sm" | "default" | "lg""default"
aria-invalid

Pokazuje stan błędu. Połącz z data-invalid na otaczającym Field.

booleanBrak wartości domyślnej

SelectValue

Wyświetla wybór wewnątrz wyzwalacza. Renderuje <span>.

PropTypDomyślnie
children

Własny sposób wyświetlania wybranej wartości, np. podsumowanie przy wielokrotnym wyborze.

ReactNode | (value) => ReactNodeBrak wartości domyślnej
placeholder

Wyświetlany, gdy nic nie jest wybrane. Pierwszeństwo ma element z wartością null w items.

ReactNodeBrak wartości domyślnej

SelectContent

Pozycjonowany popup z przewijaną listą opcji. Sam renderuje SelectScrollUpButton i SelectScrollDownButton na krawędziach listy; oba są eksportowane na potrzeby własnego popupu.

PropTypDomyślnie
alignItemWithTrigger

Nakłada listę na wyzwalacz tak, że wybrana opcja leży dokładnie na nim. Ustaw false, aby lista otwierała się obok wyzwalacza jak klasyczna lista rozwijana.

booleantrue
side

Preferowana strona, gdy lista nie jest wyrównana do wyzwalacza.

"top" | "right" | "bottom" | "left" | "inline-start" | "inline-end""bottom"
sideOffset

Odstęp między wyzwalaczem a listą, w pikselach.

number6
align

Wyrównanie wzdłuż wybranej strony.

"start" | "center" | "end""center"
alignOffset

Przesunięcie wzdłuż osi wyrównania, w pikselach.

number0

SelectItem

Opcja. Renderuje <div> z role="option".

PropTypDomyślnie
valuewymagany

Wartość, którą reprezentuje ta opcja.

anyBrak wartości domyślnej
disabled

Uniemożliwia podświetlenie i wybranie opcji.

booleanfalse
label

Tekst używany przy wyszukiwaniu przez wpisywanie, gdy zawartość opcji nie jest zwykłym tekstem.

stringBrak wartości domyślnej

SelectGroup, SelectLabel, SelectSeparator

SelectGroup grupuje opcje, SelectLabel nadaje grupie tytuł i musi znajdować się wewnątrz grupy, a SelectSeparator rysuje linię podziału między grupami. Przyjmują propsy swoich odpowiedników z Base UI.