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.
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.jsonUż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>
)
}Podmenu
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.
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ą.
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.
| Klawisz | Dział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
labelto, 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
DropdownMenu
Komponent główny. Przyjmuje wszystkie propsy Menu.Root z Base UI.
DropdownMenuTrigger
Element, który otwiera menu. Użyj render, żeby podać Button.
DropdownMenuContent
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.
DropdownMenuItem
DropdownMenuCheckboxItem
DropdownMenuRadioGroup
DropdownMenuRadioItem
DropdownMenuSub, DropdownMenuSubTrigger i DropdownMenuSubContent
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, DropdownMenuSeparator, DropdownMenuShortcut
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.