DropdownMenu
A scoped action menu with nested, checkbox, and radio items.@gemologic/sheen · overlaysPlayground
This example has no scalar controls. Its validated source remains interactive below.
<DropdownMenu trigger="Workspace actions" matchTriggerWidth items={[{ kind: "action", id: "refresh", label: "Refresh", icon: () => <span aria-hidden="true">↻</span>, onSelect: () => {} }]} />Variant matrix
Workspace actions
Anatomy
- Package
@gemologic/sheen- Source
packages/ui/src/primitives/DropdownMenu.tsx- Tokens
--sheen-color-bg-raised--sheen-color-focus-ring--sheen-elevation-overlay
Accessibility
Role: menuKeyboard: Enter, Space, ArrowDown, ArrowUp, ArrowLeft, ArrowRight, Home, End, EscapeDo
- Keep item IDs stable across data refreshes.
- Keep checkbox and radio state in the app.
Do not
- Do not put form fields or arbitrary interactive content in an ARIA menu.
- Do not use action items for URL navigation.
Generated props
| Name | Type | Default | Description |
|---|---|---|---|
trigger * | JSX.Element | — | Visible native opening-button content. It must provide a clear accessible name. |
triggerLabel | string | — | Optional explicit accessible trigger name for icon-only or composite content. |
items * | readonly MenuItem[] | — | Sheen-owned discriminated items with stable, unique sibling IDs. Labeled items may include a lazy decorative icon renderer; checkbox and radio values are app-owned; shortcuts are display-only. |
open | boolean | — | App-owned open state. |
defaultOpen | boolean | false | Uncontrolled initial state; content mounts when the scoped portal is ready. |
onOpenChange | (open: boolean) => void | — | Open-state requests; controlled owners may reject them. |
onCloseAutoFocus | (event: Event) => void | — | Close-focus lifecycle event. Prevent default only when supplying an alternative focus destination; layouts may use it to defer moving the trigger until restoration. |
disabled | boolean | false | Disable the opening button. |
placement | DropdownMenuPlacement | bottom-start | Logical menu placement. Sidebar footers normally use top-end; topbars use bottom-end. |
matchTriggerWidth | boolean | false | Size the root menu to the trigger width, capped by the available viewport width. |
class | string | — | Additional root menu content classes. |