Przejdź do treści

Dropdown Menu

Lista akcji lub opcji rozwijana z wyzwalacza, dzięki której polecenia drugorzędne są o jedno kliknięcie stąd i nie zagracają interfejsu.

Kod źródłowyBase UIRejestr
import {
  ChevronsUpDownIcon,
  CreditCardIcon,
  KeyboardIcon,
  LifeBuoyIcon,
  LogOutIcon,
  SettingsIcon,
  UserIcon,
} from "lucide-react"

import { Avatar, AvatarFallback } from "@/components/ui/avatar"
import { Button } from "@/components/ui/button"
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuShortcut,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"

export default function DropdownMenuDemo() {
  return (
    <DropdownMenu>
      <DropdownMenuTrigger
        render={
          <Button variant="outline" className="h-10 gap-2.5 pr-2.5 pl-1.5" />
        }
      >
        <Avatar size="sm">
          <AvatarFallback>AL</AvatarFallback>
        </Avatar>
        <span className="flex flex-col items-start leading-tight">
          <span className="text-sm font-medium">Ada Lovelace</span>
        </span>
        <ChevronsUpDownIcon
          data-icon="inline-end"
          className="text-muted-foreground"
        />
      </DropdownMenuTrigger>
      <DropdownMenuContent className="w-60">
        <DropdownMenuGroup>
          <DropdownMenuLabel>
            <span className="block text-sm font-medium text-foreground">
              Ada Lovelace
            </span>
            <span className="block font-normal">ada@analytical.engine</span>
          </DropdownMenuLabel>
        </DropdownMenuGroup>
        <DropdownMenuSeparator />
        <DropdownMenuGroup>
          <DropdownMenuItem>
            <UserIcon />
            Profil
            <DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut>
          </DropdownMenuItem>
          <DropdownMenuItem>
            <CreditCardIcon />
            Płatności
            <DropdownMenuShortcut>⌘B</DropdownMenuShortcut>
          </DropdownMenuItem>
          <DropdownMenuItem>
            <SettingsIcon />
            Ustawienia
            <DropdownMenuShortcut>⌘,</DropdownMenuShortcut>
          </DropdownMenuItem>
          <DropdownMenuItem>
            <KeyboardIcon />
            Skróty klawiszowe
            <DropdownMenuShortcut>⌘K</DropdownMenuShortcut>
          </DropdownMenuItem>
        </DropdownMenuGroup>
        <DropdownMenuSeparator />
        <DropdownMenuGroup>
          <DropdownMenuItem>
            <LifeBuoyIcon />
            Pomoc
          </DropdownMenuItem>
          <DropdownMenuItem>
            <LogOutIcon />
            Wyloguj się
            <DropdownMenuShortcut>⇧⌘Q</DropdownMenuShortcut>
          </DropdownMenuItem>
        </DropdownMenuGroup>
      </DropdownMenuContent>
    </DropdownMenu>
  )
}

Instalacja

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

Użycie

import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuShortcut,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
<DropdownMenu>
  <DropdownMenuTrigger render={<Button variant="outline" />}>
    Options
  </DropdownMenuTrigger>
  <DropdownMenuContent>
    <DropdownMenuGroup>
      <DropdownMenuLabel>My account</DropdownMenuLabel>
      <DropdownMenuItem>
        Profile
        <DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut>
      </DropdownMenuItem>
      <DropdownMenuItem>Settings</DropdownMenuItem>
    </DropdownMenuGroup>
    <DropdownMenuSeparator />
    <DropdownMenuGroup>
      <DropdownMenuItem>Log out</DropdownMenuItem>
    </DropdownMenuGroup>
  </DropdownMenuContent>
</DropdownMenu>

Wyzwalacz renderuje dowolny element przez render — zwykle Button. Pozycje zawsze umieszczaj w DropdownMenuGroup, żeby czytniki ekranu ogłaszały etykietę grupy, a separatory miały co oddzielać.

Przykłady

Menu konta

Najczęstsze menu: na górze informacja, kim jesteś, pośrodku akcje konta, a na końcu wylogowanie. Skróty są wyrównane do prawej krawędzi i mają stonowany kolor, więc łatwo je wyłapać wzrokiem, a przy tym nie konkurują z etykietami.

import {
  ChevronsUpDownIcon,
  CreditCardIcon,
  KeyboardIcon,
  LifeBuoyIcon,
  LogOutIcon,
  SettingsIcon,
  UserIcon,
} from "lucide-react"

import { Avatar, AvatarFallback } from "@/components/ui/avatar"
import { Button } from "@/components/ui/button"
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuShortcut,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"

export default function DropdownMenuDemo() {
  return (
    <DropdownMenu>
      <DropdownMenuTrigger
        render={
          <Button variant="outline" className="h-10 gap-2.5 pr-2.5 pl-1.5" />
        }
      >
        <Avatar size="sm">
          <AvatarFallback>AL</AvatarFallback>
        </Avatar>
        <span className="flex flex-col items-start leading-tight">
          <span className="text-sm font-medium">Ada Lovelace</span>
        </span>
        <ChevronsUpDownIcon
          data-icon="inline-end"
          className="text-muted-foreground"
        />
      </DropdownMenuTrigger>
      <DropdownMenuContent className="w-60">
        <DropdownMenuGroup>
          <DropdownMenuLabel>
            <span className="block text-sm font-medium text-foreground">
              Ada Lovelace
            </span>
            <span className="block font-normal">ada@analytical.engine</span>
          </DropdownMenuLabel>
        </DropdownMenuGroup>
        <DropdownMenuSeparator />
        <DropdownMenuGroup>
          <DropdownMenuItem>
            <UserIcon />
            Profil
            <DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut>
          </DropdownMenuItem>
          <DropdownMenuItem>
            <CreditCardIcon />
            Płatności
            <DropdownMenuShortcut>⌘B</DropdownMenuShortcut>
          </DropdownMenuItem>
          <DropdownMenuItem>
            <SettingsIcon />
            Ustawienia
            <DropdownMenuShortcut>⌘,</DropdownMenuShortcut>
          </DropdownMenuItem>
          <DropdownMenuItem>
            <KeyboardIcon />
            Skróty klawiszowe
            <DropdownMenuShortcut>⌘K</DropdownMenuShortcut>
          </DropdownMenuItem>
        </DropdownMenuGroup>
        <DropdownMenuSeparator />
        <DropdownMenuGroup>
          <DropdownMenuItem>
            <LifeBuoyIcon />
            Pomoc
          </DropdownMenuItem>
          <DropdownMenuItem>
            <LogOutIcon />
            Wyloguj się
            <DropdownMenuShortcut>⇧⌘Q</DropdownMenuShortcut>
          </DropdownMenuItem>
        </DropdownMenuGroup>
      </DropdownMenuContent>
    </DropdownMenu>
  )
}

Pozycje z polem wyboru

Używaj DropdownMenuCheckboxItem do niezależnych ustawień typu włącz/wyłącz, takich jak widoczne kolumny. Kliknięcie takiej pozycji nie zamyka menu (closeOnClick ma domyślnie wartość false), więc za jednym razem można przełączyć kilka z nich.

"use client"

import * as React from "react"
import { Settings2Icon } from "lucide-react"

import { Button } from "@/components/ui/button"
import {
  DropdownMenu,
  DropdownMenuCheckboxItem,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuLabel,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"

const columns = [
  { id: "status", label: "Status" },
  { id: "assignee", label: "Osoba przypisana" },
  { id: "priority", label: "Priorytet" },
  { id: "due", label: "Termin" },
  { id: "estimate", label: "Oszacowanie" },
]

export default function DropdownMenuCheckboxes() {
  const [visible, setVisible] = React.useState<Record<string, boolean>>({
    status: true,
    assignee: true,
    priority: true,
    due: false,
    estimate: false,
  })
  const count = Object.values(visible).filter(Boolean).length

  return (
    <DropdownMenu>
      <DropdownMenuTrigger render={<Button variant="outline" />}>
        <Settings2Icon data-icon="inline-start" />
        Kolumny
        <span className="text-muted-foreground tabular-nums">{count}</span>
      </DropdownMenuTrigger>
      <DropdownMenuContent className="w-52">
        <DropdownMenuGroup>
          <DropdownMenuLabel>Widoczne kolumny</DropdownMenuLabel>
          {columns.map((column) => (
            <DropdownMenuCheckboxItem
              key={column.id}
              checked={visible[column.id]}
              onCheckedChange={(checked) =>
                setVisible((current) => ({ ...current, [column.id]: checked }))
              }
            >
              {column.label}
            </DropdownMenuCheckboxItem>
          ))}
        </DropdownMenuGroup>
        <DropdownMenuSeparator />
        <DropdownMenuGroup>
          <DropdownMenuCheckboxItem
            checked={count === columns.length}
            onCheckedChange={(checked) =>
              setVisible(
                Object.fromEntries(columns.map((c) => [c.id, checked]))
              )
            }
          >
            Pokaż wszystkie
          </DropdownMenuCheckboxItem>
        </DropdownMenuGroup>
      </DropdownMenuContent>
    </DropdownMenu>
  )
}

Grupa radiowa

DropdownMenuRadioGroup grupuje wzajemnie wykluczające się opcje — kolejność sortowania, gęstość, tryb widoku. Pokaż bieżący wybór w etykiecie wyzwalacza, żeby stan był widoczny także przy zamkniętym menu.

"use client"

import * as React from "react"
import { ArrowDownWideNarrowIcon } from "lucide-react"

import { Button } from "@/components/ui/button"
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuLabel,
  DropdownMenuRadioGroup,
  DropdownMenuRadioItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"

const sortOptions = {
  updated: "Ostatnia aktualizacja",
  created: "Data utworzenia",
  name: "Nazwa",
  priority: "Priorytet",
}

type SortKey = keyof typeof sortOptions

export default function DropdownMenuRadioGroupDemo() {
  const [sort, setSort] = React.useState<SortKey>("updated")
  const [direction, setDirection] = React.useState("desc")

  return (
    <DropdownMenu>
      <DropdownMenuTrigger render={<Button variant="outline" />}>
        <ArrowDownWideNarrowIcon data-icon="inline-start" />
        Sortowanie: {sortOptions[sort]}
      </DropdownMenuTrigger>
      <DropdownMenuContent className="w-52">
        <DropdownMenuGroup>
          <DropdownMenuLabel>Sortuj według</DropdownMenuLabel>
          <DropdownMenuRadioGroup
            value={sort}
            onValueChange={(value) => setSort(value as SortKey)}
          >
            {Object.entries(sortOptions).map(([value, label]) => (
              <DropdownMenuRadioItem key={value} value={value}>
                {label}
              </DropdownMenuRadioItem>
            ))}
          </DropdownMenuRadioGroup>
        </DropdownMenuGroup>
        <DropdownMenuSeparator />
        <DropdownMenuGroup>
          <DropdownMenuLabel>Kolejność</DropdownMenuLabel>
          <DropdownMenuRadioGroup
            value={direction}
            onValueChange={setDirection}
          >
            <DropdownMenuRadioItem value="asc">Rosnąco</DropdownMenuRadioItem>
            <DropdownMenuRadioItem value="desc">
              Malejąco
            </DropdownMenuRadioItem>
          </DropdownMenuRadioGroup>
        </DropdownMenuGroup>
      </DropdownMenuContent>
    </DropdownMenu>
  )
}

Zagnieżdżaj powiązane akcje za pomocą DropdownMenuSub. Podmenu otwiera się po najechaniu, z krótkim opóźnieniem, a z klawiatury — klawiszem →. Ogranicz zagnieżdżanie do jednego poziomu — drugi poziom to znak, że menu wykonuje pracę strony.

import {
  CopyIcon,
  LinkIcon,
  MailIcon,
  MessageSquareIcon,
  PlusIcon,
  Share2Icon,
  UserPlusIcon,
} from "lucide-react"

import { Button } from "@/components/ui/button"
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuShortcut,
  DropdownMenuSub,
  DropdownMenuSubContent,
  DropdownMenuSubTrigger,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"

export default function DropdownMenuSubmenu() {
  return (
    <DropdownMenu>
      <DropdownMenuTrigger render={<Button variant="outline" />}>
        <PlusIcon data-icon="inline-start" />
        Nowy
      </DropdownMenuTrigger>
      <DropdownMenuContent className="w-56">
        <DropdownMenuGroup>
          <DropdownMenuItem>
            Nowy dokument
            <DropdownMenuShortcut>⌘N</DropdownMenuShortcut>
          </DropdownMenuItem>
          <DropdownMenuItem>
            Nowy folder
            <DropdownMenuShortcut>⇧⌘N</DropdownMenuShortcut>
          </DropdownMenuItem>
          <DropdownMenuItem>
            <CopyIcon />
            Duplikuj
          </DropdownMenuItem>
        </DropdownMenuGroup>
        <DropdownMenuSeparator />
        <DropdownMenuGroup>
          <DropdownMenuSub>
            <DropdownMenuSubTrigger>
              <UserPlusIcon />
              Zaproś osoby
            </DropdownMenuSubTrigger>
            <DropdownMenuSubContent>
              <DropdownMenuGroup>
                <DropdownMenuItem>
                  <MailIcon />
                  E-mail
                </DropdownMenuItem>
                <DropdownMenuItem>
                  <MessageSquareIcon />
                  Wiadomość
                </DropdownMenuItem>
                <DropdownMenuItem>
                  <LinkIcon />
                  Kopiuj link z zaproszeniem
                </DropdownMenuItem>
              </DropdownMenuGroup>
            </DropdownMenuSubContent>
          </DropdownMenuSub>
          <DropdownMenuSub>
            <DropdownMenuSubTrigger>
              <Share2Icon />
              Udostępnij
            </DropdownMenuSubTrigger>
            <DropdownMenuSubContent>
              <DropdownMenuGroup>
                <DropdownMenuItem>Kopiuj link</DropdownMenuItem>
                <DropdownMenuItem>Eksportuj jako PDF</DropdownMenuItem>
                <DropdownMenuItem>Opublikuj w internecie…</DropdownMenuItem>
              </DropdownMenuGroup>
            </DropdownMenuSubContent>
          </DropdownMenuSub>
        </DropdownMenuGroup>
      </DropdownMenuContent>
    </DropdownMenu>
  )
}

Akcje wiersza

Ikonowy przycisk w wariancie ghost ze znakiem ⋯ to przyjęte miejsce na akcje pojedynczego elementu listy lub tabeli. Wyrównaj menu do końca wyzwalacza (align="end"), żeby otwierało się w stronę treści, i nadaj wyzwalaczowi aria-label, który nazywa element, na którym działa.

Planowanie kwartalneEdytowano 2 godz. temu
Aktywne
import {
  ArchiveIcon,
  CopyIcon,
  MoreHorizontalIcon,
  PencilIcon,
  Trash2Icon,
} from "lucide-react"

import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuShortcut,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"

export default function DropdownMenuRowActions() {
  return (
    <div className="flex w-full max-w-md items-center gap-3 rounded-xl border bg-card px-4 py-3 shadow-raised">
      <div className="flex min-w-0 flex-1 flex-col">
        <span className="truncate text-sm font-medium">Planowanie kwartalne</span>
        <span className="text-body-xs text-muted-foreground">
          Edytowano 2 godz. temu
        </span>
      </div>
      <Badge variant="success">Aktywne</Badge>
      <DropdownMenu>
        <DropdownMenuTrigger
          render={
            <Button
              variant="ghost"
              size="icon-sm"
              aria-label="Akcje: Planowanie kwartalne"
            />
          }
        >
          <MoreHorizontalIcon />
        </DropdownMenuTrigger>
        <DropdownMenuContent align="end" className="w-48">
          <DropdownMenuGroup>
            <DropdownMenuItem>
              <PencilIcon />
              Zmień nazwę
              <DropdownMenuShortcut>R</DropdownMenuShortcut>
            </DropdownMenuItem>
            <DropdownMenuItem>
              <CopyIcon />
              Duplikuj
              <DropdownMenuShortcut>⌘D</DropdownMenuShortcut>
            </DropdownMenuItem>
            <DropdownMenuItem>
              <ArchiveIcon />
              Archiwizuj
            </DropdownMenuItem>
          </DropdownMenuGroup>
          <DropdownMenuSeparator />
          <DropdownMenuGroup>
            <DropdownMenuItem variant="destructive">
              <Trash2Icon />
              Usuń
              <DropdownMenuShortcut>⌘⌫</DropdownMenuShortcut>
            </DropdownMenuItem>
          </DropdownMenuGroup>
        </DropdownMenuContent>
      </DropdownMenu>
    </div>
  )
}

Wyłączone pozycje

Wyłącz pozycję, gdy akcja istnieje, ale jest chwilowo niedostępna, i wyjaśnij w etykiecie dlaczego. Wyłączonej pozycji nie da się aktywować, ale nadal można do niej dojść strzałkami, więc osoby korzystające z czytnika ekranu dowiadują się, że akcja istnieje. Jeśli akcja w ogóle nie ma zastosowania w bieżącym kontekście, usuń ją.

import { DownloadIcon, FileTextIcon, LockIcon, PrinterIcon } from "lucide-react"

import { Button } from "@/components/ui/button"
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"

export default function DropdownMenuDisabled() {
  return (
    <DropdownMenu>
      <DropdownMenuTrigger render={<Button variant="outline" />}>
        <DownloadIcon data-icon="inline-start" />
        Eksportuj
      </DropdownMenuTrigger>
      <DropdownMenuContent className="w-56">
        <DropdownMenuGroup>
          <DropdownMenuLabel>Eksportuj raport jako</DropdownMenuLabel>
          <DropdownMenuItem>
            <FileTextIcon />
            CSV
          </DropdownMenuItem>
          <DropdownMenuItem>
            <PrinterIcon />
            PDF
          </DropdownMenuItem>
          <DropdownMenuItem disabled>
            <LockIcon />
            Excel — plan Pro
          </DropdownMenuItem>
        </DropdownMenuGroup>
      </DropdownMenuContent>
    </DropdownMenu>
  )
}

Wytyczne

Kiedy używać

  • Aby zebrać drugorzędne akcje pod jednym wyzwalaczem: akcje wiersza, nadmiarowe akcje z paska narzędzi, menu konta.
  • Aby udostępnić kilka ustawień widoku — przełączniki i wybory jednokrotne — bez osobnej strony ustawień.

Kiedy nie używać

  • Do wyboru wartości, która staje się częścią formularza — użyj Select albo Combobox.
  • Do głównej akcji widoku — niech będzie widoczna jako Button.
  • Do nawigacji po witrynie lub aplikacji z rozbudowanymi panelami — użyj Navigation Menu.
  • Do akcji dotyczących obszaru, odkrywanych prawym przyciskiem myszy — użyj Context Menu i zawsze udostępnij te same akcje w widocznym miejscu.

Treść pozycji

Zaczynaj każdą pozycję od czasownika albo od rzeczownika, który nazywa miejsce docelowe: Zmień nazwę, Duplikuj, Ustawienia. Wielką literą pisz tylko pierwsze słowo, mieść pozycje w jednej linii i dodawaj wielokropek (…) tylko wtedy, gdy pozycja otwiera okno, które prosi o dodatkowe dane, zanim cokolwiek się stanie.

Ikony są opcjonalne, ale w obrębie grupy obowiązuje zasada „wszystkie albo żadna”: kolumna etykiet, z których część ma ikony, a część nie, wygląda na zepsutą. Gdy reszta menu ma ikony lub wskaźniki, dodaj inset do pozycji, które ich nie mają.

Zmień nazwę
Duplikuj
Archiwizuj
Usuń
DobrzeCzasowniki na początku, spójne ikony i jedna pozycja destrukcyjna na końcu.
Zmiana nazwy
Usuń na zawsze
Zrób kopię tego
Wybierz kraj…
ŹleNiespójne sformułowania, akcja destrukcyjna ukryta w środku i menu, które wykonuje pracę formularza.

Akcje destrukcyjne

Umieszczaj pozycje destrukcyjne na końcu, oddzielone od reszty, i używaj dla nich variant="destructive". Jeśli akcji nie da się cofnąć, pozycja powinna otwierać Alert Dialog, zamiast działać od razu. Pozycja destrukcyjna nigdy nie może być pierwszą, na którą trafia fokus klawiatury.

Skróty klawiszowe

DropdownMenuShortcut to podpowiedź, a nie przypisanie klawisza — właściwą obsługę skrótu zarejestruj gdzie indziej. Pokazuj skróty tylko przy akcjach, które naprawdę je mają, używaj symboli platformy (⌘ ⇧ ⌥ ⌃ ⌫ ↵) w przyjętej kolejności (⌃ ⌥ ⇧ ⌘) i nie pokazuj skrótu przy wyłączonej pozycji.

Rozmiar i grupowanie

Siedem do dziesięciu pozycji to wygodne maksimum. Grupuj powiązane pozycje i oddzielaj grupy za pomocą DropdownMenuSeparator; gdy przeznaczenie grupy nie jest oczywiste, nadaj jej etykietę DropdownMenuLabel. Menu rozszerza się do najdłuższej pozycji i nigdy nie jest węższe niż wyzwalacz ani niż 11 rem (176 px). Żeby miało stałą szerokość, ustaw ją na DropdownMenuContent, np. className="w-56".

Dostępność

Dropdown Menu, oparty na Base UI, realizuje wzorzec WAI-ARIA menu button. Wyzwalacz otrzymuje aria-haspopup i aria-expanded, pozycje — rolę menuitem, menuitemcheckbox lub menuitemradio; po otwarciu fokus przechodzi do menu, a po zamknięciu wraca do wyzwalacza.

KlawiszDziałanie
EnterSpacja↓
Na wyzwalaczu: otwiera menu i przenosi fokus na pierwszą pozycję.
↑
Na wyzwalaczu: otwiera menu i przenosi fokus na ostatnią pozycję.
↓↑
Przenosi fokus między pozycjami. Z ostatniej pozycji fokus przechodzi na pierwszą.
HomeEnd
Przenosi fokus na pierwszą lub ostatnią pozycję.
→
Na wyzwalaczu podmenu: otwiera podmenu i przenosi fokus na jego pierwszą pozycję.
←
W podmenu: zamyka je i przywraca fokus do jego wyzwalacza.
EnterSpacja
Aktywuje pozycję z fokusem. Pozycje z polem wyboru i pozycje radiowe przełączają się bez zamykania menu.
A–Z
Wyszukiwanie przez wpisywanie: przenosi fokus na następną pozycję, której etykieta zaczyna się od wpisanych znaków.
Esc
Zamyka menu i przywraca fokus do wyzwalacza.
  • Wyzwalacze z samą ikoną potrzebują aria-label, który nazywa zarówno akcję, jak i obiekt: Akcje: Planowanie kwartalne, a nie Więcej.
  • Wyszukiwanie przez wpisywanie dopasowuje tekst pozycji. Gdy treść pozycji nie jest zwykłym tekstem, ustaw w propie label to, co wpisaliby użytkownicy.
  • Podświetlenie a najechanie. Pozycje podświetlają się tak samo po najechaniu kursorem, jak przy fokusie z klawiatury (data-highlighted), więc aktywna jest zawsze tylko jedna pozycja.

Dokumentacja API

Komponent główny. Przyjmuje wszystkie propsy Menu.Root z Base UI.

PropTypDomyślnie
open

Kontrolowany stan otwarcia.

booleanBrak wartości domyślnej
defaultOpen

Początkowy stan otwarcia w trybie niekontrolowanym.

booleanfalse
onOpenChange

Wywoływana, gdy menu się otwiera lub zamyka.

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

true blokuje przewijanie strony i interakcje wskaźnikiem poza menu, dopóki jest otwarte. Menu otwarte przez najechanie nigdy nie jest modalne.

booleantrue
loopFocus

Czy fokus przesuwany strzałkami przechodzi z ostatniej pozycji na pierwszą.

booleantrue
disabled

Ignoruje interakcję użytkownika z wyzwalaczem.

booleanfalse

Element, który otwiera menu. Użyj render, żeby podać Button.

PropTypDomyślnie
render

Element do wyrenderowania, zwykle <Button />.

ReactElement | (props, state) => ReactElementBrak wartości domyślnej
openOnHover

Otwiera menu także po najechaniu na wyzwalacz.

booleanfalse
delay

Opóźnienie otwarcia po najechaniu, w ms. Wymaga openOnHover.

number100
disabled

Wyłącza wyzwalacz.

booleanfalse

Popup renderowany w portalu i pozycjonowany względem wyzwalacza. Przyjmuje też wszystkie propsy Menu.Popup z Base UI. DropdownMenuContent renderuje własny portal, więc eksportowany DropdownMenuPortal jest potrzebny tylko wtedy, gdy samodzielnie składasz popup z części Base UI.

PropTypDomyślnie
side

Preferowana strona wyzwalacza. Automatycznie zmienia się na przeciwną, żeby menu pozostało widoczne.

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

Wyrównanie względem wyzwalacza po wybranej stronie.

"start" | "center" | "end""start"
sideOffset

Odstęp między wyzwalaczem a menu w px.

number6
alignOffset

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

number0
PropTypDomyślnie
variant

Pozycje destrukcyjne mają kolor danger w tekście, ikonie i podświetleniu.

"default" | "destructive""default"
inset

Dodaje odstęp na początku, żeby wyrównać pozycję z pozycjami, które mają ikony lub wskaźniki.

booleanfalse
onClick

Wywoływana, gdy pozycja zostanie aktywowana myszą lub klawiaturą.

(event) => voidBrak wartości domyślnej
closeOnClick

Czy aktywowanie pozycji zamyka menu.

booleantrue
disabled

Ignoruje kliknięcia i naciśnięcia klawiszy. Do pozycji nadal można dojść strzałkami, więc technologie wspomagające ogłaszają ją jako niedostępną.

booleanfalse
label

Tekst do wyszukiwania przez wpisywanie, gdy treść pozycji nie jest zwykłym tekstem.

stringBrak wartości domyślnej
PropTypDomyślnie
checked

Kontrolowany stan zaznaczenia.

booleanBrak wartości domyślnej
defaultChecked

Początkowy stan zaznaczenia w trybie niekontrolowanym.

booleanfalse
onCheckedChange

Wywoływana, gdy pozycja zostanie przełączona.

(checked: boolean, details) => voidBrak wartości domyślnej
closeOnClick

Czy przełączenie zamyka menu.

booleanfalse
inset

Zachowany dla spójności API; pozycje z polem wyboru zawsze rezerwują miejsce na wskaźnik.

booleanfalse
PropTypDomyślnie
value

Kontrolowana wybrana wartość.

anyBrak wartości domyślnej
defaultValue

Początkowo wybrana wartość w trybie niekontrolowanym.

anyBrak wartości domyślnej
onValueChange

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

(value: any, details) => voidBrak wartości domyślnej
disabled

Wyłącza wszystkie pozycje w grupie.

booleanfalse
PropTypDomyślnie
valuewymagany

Wartość, którą wybiera ta pozycja.

anyBrak wartości domyślnej
closeOnClick

Czy wybranie pozycji zamyka menu.

booleanfalse
disabled

Ignoruje wybór. Do pozycji nadal można dojść strzałkami.

booleanfalse
inset

Zachowany dla spójności API; pozycje radiowe zawsze rezerwują miejsce na wskaźnik.

booleanfalse

DropdownMenuSub otacza zagnieżdżone menu. DropdownMenuSubTrigger przyjmuje inset, disabled, openOnHover (domyślnie true), delay (domyślnie 100) i closeDelay (domyślnie 0). DropdownMenuSubContent przyjmuje te same propsy pozycjonowania co DropdownMenuContent, z wartościami domyślnymi side="right", align="start", alignOffset={-5} i sideOffset={2}.

DropdownMenuLabel nadaje etykietę otaczającej ją grupie DropdownMenuGroup i przyjmuje inset. DropdownMenuSeparator rysuje cienką linię między grupami. DropdownMenuShortcut to czysto prezentacyjny <span> dosunięty do końcowej krawędzi pozycji.