Dropdown
A floating panel of actions. The classes paint the panel and its rows; nothing here positions anything. Kobalte positions with a popper that writes inline styles, and a CSS-only dropdown anchors the panel itself, so placement stays with whatever opens the menu.
alpha The class names and states here are stable. The look is not: these styles can change in a minor release, without a major version bump.
| Class | Does what |
|---|---|
dropdown-content | The floating panel: raised surface, border, shadow |
menu | The list inside it: a column with gaps |
menu-item | A row: padding, radius, hover surface |
menu-active | The highlighted row |
menu-disabled | A disabled row: greyed out and inert |
menu-title | A group heading inside the menu |
menu-shortcut | Trailing text in a row, pushed to the end |
The panel
Shown open and in place. Use <ul> and <li> and
the rows stay semantic; Kobalte renders divs with menu roles instead.
<ul class="dropdown-content menu">
<li class="menu-item">Commit <span class="menu-shortcut">⌘K</span></li>
<li class="menu-item menu-active">Push <span class="menu-shortcut">⇧⌘K</span></li>
<li class="menu-item menu-disabled">Update project</li>
<li><hr /></li>
<li>
<ul class="menu">
<li class="menu-title">Branches</li>
<li class="menu-item">main</li>
<li class="menu-item">develop</li>
</ul>
</li>
</ul>
<ul class="dropdown-content menu">
<li class="menu-item">Commit <span class="menu-shortcut">⌘K</span></li>
<li class="menu-item menu-active">Push <span class="menu-shortcut">⇧⌘K</span></li>
<li class="menu-item menu-disabled">Update project</li>
<li><hr /></li>
<li>
<ul class="menu">
<li class="menu-title">Branches</li>
<li class="menu-item">main</li>
<li class="menu-item">develop</li>
</ul>
</li>
</ul>
import { DropdownMenu } from "@kobalte/core/dropdown-menu";
<DropdownMenu>
<DropdownMenu.Trigger class="btn">
Git settings
<DropdownMenu.Icon>▾</DropdownMenu.Icon>
</DropdownMenu.Trigger>
<DropdownMenu.Portal>
<DropdownMenu.Content>
<DropdownMenu.Item>
Commit <span class="menu-shortcut">⌘K</span>
</DropdownMenu.Item>
<DropdownMenu.Item>
Push <span class="menu-shortcut">⇧⌘K</span>
</DropdownMenu.Item>
<DropdownMenu.Item disabled>Update project</DropdownMenu.Item>
<DropdownMenu.Separator />
<DropdownMenu.Group>
<DropdownMenu.GroupLabel>Branches</DropdownMenu.GroupLabel>
<DropdownMenu.RadioGroup value={branch()} onChange={setBranch}>
<DropdownMenu.RadioItem value="main">main</DropdownMenu.RadioItem>
<DropdownMenu.RadioItem value="develop">develop</DropdownMenu.RadioItem>
</DropdownMenu.RadioGroup>
</DropdownMenu.Group>
</DropdownMenu.Content>
</DropdownMenu.Portal>
</DropdownMenu>
<div role="menu" data-expanded>
<div role="menuitem">Commit <span class="menu-shortcut">⌘K</span></div>
<div role="menuitem" data-highlighted>Push <span class="menu-shortcut">⇧⌘K</span></div>
<div role="menuitem" data-disabled>Update project</div>
<hr />
<div role="group">
<span>Branches</span>
<div role="menuitemradio" data-checked>main</div>
<div role="menuitemradio">develop</div>
</div>
</div>
On the Kobalte tab the rows carry no classes: role="menuitem",
data-highlighted and data-disabled are bound to
.menu-item, .menu-active and
.menu-disabled by /classless/kobalte.
With a trigger
The trigger is an ordinary button. Kobalte marks it data-expanded
while the menu is open, and flips a DropdownMenu.Icon inside it.
<details open>
<summary class="btn">Git settings ▾</summary>
<ul class="dropdown-content menu" style="margin-top: 0.25rem">
<li class="menu-item">Commit</li>
<li class="menu-item">Push</li>
</ul>
</details>
<details open>
<summary class="btn">Git settings ▾</summary>
<ul class="dropdown-content menu" style="margin-top: 0.25rem">
<li class="menu-item">Commit</li>
<li class="menu-item">Push</li>
</ul>
</details>
<DropdownMenu>
<DropdownMenu.Trigger class="btn">
Git settings
<DropdownMenu.Icon>▾</DropdownMenu.Icon>
</DropdownMenu.Trigger>
<DropdownMenu.Portal>
<DropdownMenu.Content>
<DropdownMenu.Item>Commit</DropdownMenu.Item>
<DropdownMenu.Item>Push</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu.Portal>
</DropdownMenu>
<div>
<button aria-haspopup="true" aria-expanded="true" data-expanded class="btn">
Git settings <span data-expanded>▾</span>
</button>
<div role="menu" data-expanded style="margin-top: 0.25rem">
<div role="menuitem">Commit</div>
<div role="menuitem">Push</div>
</div>
</div>
Submenus
A DropdownMenu.SubTrigger is a row that is also a trigger, so it
takes .menu-item and picks up data-highlighted like
any other row. Its SubContent is another panel.
<ul class="dropdown-content menu">
<li class="menu-item menu-active">GitHub <span class="menu-shortcut">›</span></li>
</ul>
</div>
<ul class="dropdown-content menu" style="margin-top: 0.25rem">
<li class="menu-item">Create pull request…</li>
<li class="menu-item">Sync fork</li>
</ul>
<ul class="dropdown-content menu">
<li class="menu-item menu-active">GitHub <span class="menu-shortcut">›</span></li>
</ul>
</div>
<ul class="dropdown-content menu" style="margin-top: 0.25rem">
<li class="menu-item">Create pull request…</li>
<li class="menu-item">Sync fork</li>
</ul>
<DropdownMenu.Sub overlap gutter={4} shift={-8}>
<DropdownMenu.SubTrigger>
GitHub <span class="menu-shortcut">›</span>
</DropdownMenu.SubTrigger>
<DropdownMenu.Portal>
<DropdownMenu.SubContent>
<DropdownMenu.Item>Create pull request…</DropdownMenu.Item>
<DropdownMenu.Item>Sync fork</DropdownMenu.Item>
</DropdownMenu.SubContent>
</DropdownMenu.Portal>
</DropdownMenu.Sub>
<div>
<div role="menu" data-expanded>
<div role="menuitem" aria-haspopup="true" data-highlighted data-expanded>
GitHub <span class="menu-shortcut">›</span>
</div>
</div>
<div role="menu" data-expanded style="margin-top: 0.25rem">
<div role="menuitem">Create pull request…</div>
<div role="menuitem">Sync fork</div>
</div>
</div>