# Dropdown Menu Displays a menu to the user —such as a set of actions or functions— triggered by a button. ## Import ``` Copyts import { DropdownMenu } from "@kobalte/core/dropdown-menu"; // or import { Root, Trigger, ... } from "@kobalte/core/dropdown-menu"; // or (deprecated) import { DropdownMenu } from "@kobalte/core"; ``` ``` Copyts import { DropdownMenu } from "@kobalte/core/dropdown-menu"; // or import { Root, Trigger, ... } from "@kobalte/core/dropdown-menu"; // or (deprecated) import { DropdownMenu } from "@kobalte/core"; ``` ## Features - Exposed to assistive technology as a button with a menu using the [WAI ARIA Menu Button](https://www.w3.org/WAI/ARIA/apg/patterns/menubutton/) design pattern. - Supports modal and non-modal modes. - Supports submenus. - Supports items, labels, groups of items. - Supports checkable items (single or multiple) with optional indeterminate state. - Support disabled items. - Complex item labeling support for accessibility. - Keyboard opening and navigation support. - Automatic scrolling support during keyboard navigation. - Typeahead to allow focusing items by typing text. - Optionally render a pointing arrow. - Focus is fully managed. - Can be controlled or uncontrolled. ## Anatomy The dropdown menu consists of: - **DropdownMenu:** The root container for a dropdown menu. - **DropdownMenu.Trigger:** The button that toggles the menu. - **DropdownMenu.Icon:** A small icon often displayed next to the menu trigger as a visual affordance for the fact it can be open. - **DropdownMenu.Portal:** Portals its children into the `body` when the menu is open. - **DropdownMenu.Content:** Contains the content to be rendered when the menu is open. - **DropdownMenu.Arrow:** An optional arrow element to render alongside the menu content. - **DropdownMenu.Separator:** Used to visually separate items in the menu. - **DropdownMenu.Group:** Used to group multiple items. Use in conjunction with `DropdownMenu.GroupLabel` to ensure good accessibility via automatic labelling. - **DropdownMenu.GroupLabel:** Used to render the label of a group. It won't be focusable using arrow keys. - **DropdownMenu.Sub:** Contains all the parts of a submenu. - **DropdownMenu.SubTrigger:** An item that opens a submenu. Must be rendered inside `DropdownMenu.Sub`. - **DropdownMenu.SubContent:** The component that pops out when a submenu is open. Must be rendered inside `DropdownMenu.Sub`. The menu item consists of: - **DropdownMenu.Item:** An item of the select. - **DropdownMenu.ItemLabel:** An accessible label to be announced for the item. - **DropdownMenu.ItemDescription:** An optional accessible description to be announced for the item. - **DropdownMenu.ItemIndicator:** The visual indicator rendered when the item is checked. The checkable menu item consists of: - **DropdownMenu.RadioGroup:** Used to group multiple `DropdownMenu.RadioItem`s and manage the selection. - **DropdownMenu.RadioItem:** An item that can be controlled and rendered like a radio. - **DropdownMenu.CheckboxItem:** An item that can be controlled and rendered like a checkbox. ``` Copytsx ``` ``` Copytsx ``` ## Example Git SettingsChevron index.tsxstyle.css ``` Copytsx import { DropdownMenu } from "@kobalte/core/dropdown-menu"; import { createSignal } from "solid-js"; import { CheckIcon, ChevronDownIcon, ChevronRightIcon, DotFilledIcon } from "some-icon-library"; import "./style.css"; function App() { const [showGitLog, setShowGitLog] = createSignal(true); const [showHistory, setShowHistory] = createSignal(false); const [branch, setBranch] = createSignal("main"); return ( Git Settings Commit Push Update Project GitHub Create Pull Request… View Pull Requests Sync Fork Open on GitHub Show Git Log Show History Branches main develop ); } ``` ``` Copytsx import { DropdownMenu } from "@kobalte/core/dropdown-menu"; import { createSignal } from "solid-js"; import { CheckIcon, ChevronDownIcon, ChevronRightIcon, DotFilledIcon } from "some-icon-library"; import "./style.css"; function App() { const [showGitLog, setShowGitLog] = createSignal(true); const [showHistory, setShowHistory] = createSignal(false); const [branch, setBranch] = createSignal("main"); return ( Git Settings Commit Push Update Project GitHub Create Pull Request… View Pull Requests Sync Fork Open on GitHub Show Git Log Show History Branches main develop ); } ``` ## Usage ### Default open An initial, uncontrolled open value can be provided using the `defaultOpen` prop. ``` Copytsx ... ``` ``` Copytsx ... ``` ### Controlled open The `open` prop can be used to make the open state controlled. The `onOpenChange` event is fired when the user presses the trigger, an item or interact outside, and receives the new value. Open ``` Copytsx import { createSignal } from "solid-js"; function ControlledExample() { const [open, setOpen] = createSignal(false); return ( {open() ? "Close" : "Open"} ... ); } ``` ``` Copytsx import { createSignal } from "solid-js"; function ControlledExample() { const [open, setOpen] = createSignal(false); return ( {open() ? "Close" : "Open"} ... ); } ``` ### Origin-aware animations We expose a CSS custom property `--kb-menu-content-transform-origin` which can be used to animate the content from its computed origin. ``` Copycss /* style.css */ .dropdown-menu__content, .dropdown-menu__sub-content { transform-origin: var(--kb-menu-content-transform-origin); animation: contentHide 250ms ease-in forwards; } .dropdown-menu__content[data-expanded], .dropdown-menu__sub-content[data-expanded] { animation: contentShow 250ms ease-out; } @keyframes contentShow { from { opacity: 0; transform: scale(0.96); } to { opacity: 1; transform: scale(1); } } @keyframes contentHide { from { opacity: 1; transform: scale(1); } to { opacity: 0; transform: scale(0.96); } } ``` ``` Copycss /* style.css */ .dropdown-menu__content, .dropdown-menu__sub-content { transform-origin: var(--kb-menu-content-transform-origin); animation: contentHide 250ms ease-in forwards; } .dropdown-menu__content[data-expanded], .dropdown-menu__sub-content[data-expanded] { animation: contentShow 250ms ease-out; } @keyframes contentShow { from { opacity: 0; transform: scale(0.96); } to { opacity: 1; transform: scale(1); } } @keyframes contentHide { from { opacity: 1; transform: scale(1); } to { opacity: 0; transform: scale(0.96); } } ``` ## API Reference ### DropdownMenu `DropdownMenu` is equivalent to the `Root` import from `@kobalte/core/dropdown-menu` (and deprecated `DropdownMenu.Root`). | Prop | Description | | --- | --- | | open | `boolean`
The controlled open state of the menu. | | defaultOpen | `boolean`
The default open state when initially rendered. Useful when you do not need to control the open state. | | onOpenChange | `(open: boolean) => void`
Event handler called when the open state of the menu changes. | | id | `string`
A unique identifier for the component. The id is used to generate id attributes for nested components. If no id prop is provided, a generated id will be used. | | modal | `boolean`
Whether the menu should be the only visible content for screen readers, when set to `true`:
\- interaction with outside elements will be disabled.
\- scroll will be locked.
\- focus will be locked inside the menu content.
\- elements outside the menu content will not be visible for screen readers. | | preventScroll | `boolean`
Whether the scroll should be locked even if the menu is not modal. | | forceMount | `boolean`
Used to force mounting the menu (portal and content) when more control is needed. Useful when controlling animation with SolidJS animation libraries. | `DropdownMenu` also accepts the following props to customize the placement of the `DropdownMenu.Content`. | Prop | Description | | --- | --- | | getAnchorRect | `(anchor?: HTMLElement) => AnchorRect | undefined`
Function that returns the trigger element's DOMRect. | | placement | `Placement`
The placement of the menu content. | | gutter | `number`
The distance between the menu content and the trigger element. By default, it's 0 plus half of the arrow offset, if it exists. | | shift | `number`
The skidding of the menu content along the trigger element. | | flip | `boolean | string`
Controls the behavior of the menu content when it overflows the viewport:
\- If a `boolean`, specifies whether the menu content should flip to the opposite side when it overflows.
\- If a `string`, indicates the preferred fallback placements when it overflows.
The placements must be spaced-delimited, e.g. "top left". | | slide | `boolean`
Whether the menu content should slide when it overflows. | | overlap | `boolean`
Whether the menu content can overlap the trigger element when it overflows. | | sameWidth | `boolean`
Whether the menu content should have the same width as the trigger element. This will be exposed to CSS as `--kb-popper-anchor-width`. | | fitViewport | `boolean`
Whether the menu content should fit the viewport. If this is set to true, the menu content will have `maxWidth` and `maxHeight` set to the viewport size. This will be exposed to CSS as `--kb-popper-content-available-width` and `--kb-popper-content-available-height`. | | hideWhenDetached | `boolean`
Whether to hide the menu content when the trigger element becomes occluded. | | detachedPadding | `number`
The minimum padding in order to consider the trigger element occluded. | | arrowPadding | `number`
The minimum padding between the arrow and the menu content corner. | | overflowPadding | `number`
The minimum padding between the menu content and the viewport edge. This will be exposed to CSS as `--kb-popper-overflow-padding`. | ### DropdownMenu.Trigger `DropdownMenu.Trigger` consists of [Button](https://kobalte.dev/docs/core/components/button). | Data attribute | Description | | --- | --- | | data-expanded | Present when the menu is open. | | data-closed | Present when the menu is close. | `DropdownMenu.Icon`, `DropdownMenu.Content`, `DropdownMenu.SubTrigger` and `DropdownMenu.SubContent` share the same data-attributes. ### DropdownMenu.Content The popper positioner will copy the same `z-index` as the `DropdownMenu.Content`. | Prop | Description | | --- | --- | | onOpenAutoFocus | `(event: Event) => void`
Event handler called when focus moves into the component after opening. It can be prevented by calling `event.preventDefault`. | | onCloseAutoFocus | `(event: Event) => void`
Event handler called when focus moves to the trigger after closing. It can be prevented by calling `event.preventDefault`. | | onEscapeKeyDown | `(event: KeyboardEvent) => void`
Event handler called when the escape key is down. It can be prevented by calling `event.preventDefault`. | | onPointerDownOutside | `(event: PointerDownOutsideEvent) => void`
Event handler called when a pointer event occurs outside the bounds of the component. It can be prevented by calling `event.preventDefault`. | | onFocusOutside | `(event: FocusOutsideEvent) => void`
Event handler called when the focus moves outside the bounds of the component. It can be prevented by calling `event.preventDefault`. | | onInteractOutside | `(event: InteractOutsideEvent) => void`
Event handler called when an interaction (pointer or focus event) happens outside the bounds of the component. It can be prevented by calling `event.preventDefault`. | ### DropdownMenu.Arrow | Prop | Description | | --- | --- | | size | `number`
The size of the arrow. | ### DropdownMenu.Item | Prop | Description | | --- | --- | | textValue | `string`
Optional text used for typeahead purposes. By default, the typeahead behavior will use the .textContent of the `DropdownMenu.ItemLabel` part if provided, or fallback to the .textContent of the `DropdownMenu.Item`. Use this when the content is complex, or you have non-textual content inside. | | disabled | `boolean`
Whether the item is disabled or not. | | closeOnSelect | `boolean`
Whether the menu should close when the item is activated. | | onSelect | `() => void`
Event handler called when the user selects an item (via mouse or keyboard). | | Data attribute | Description | | --- | --- | | data-disabled | Present when the item is disabled. | | data-highlighted | Present when the item is highlighted. | `DropdownMenu.ItemLabel`, `DropdownMenu.ItemDescription` and `DropdownMenu.ItemIndicator` shares the same data-attributes. ### DropdownMenu.ItemIndicator | Prop | Description | | --- | --- | | forceMount | `boolean`
Used to force mounting when more control is needed. Useful when controlling animation with SolidJS animation libraries. | ### DropdownMenu.RadioGroup | Prop | Description | | --- | --- | | value | `string`
The controlled value of the menu radio item to check. | | defaultValue | `string`
The value of the menu radio item that should be checked when initially rendered. Useful when you do not need to control the state of the radio group. | | onChange | `(value: string) => void`
Event handler called when the value changes. | | disabled | `boolean`
Whether the radio group is disabled or not. | ### DropdownMenu.RadioItem | Prop | Description | | --- | --- | | value | `string`
The value of the menu item radio. | | textValue | `string`
Optional text used for typeahead purposes. By default, the typeahead behavior will use the .textContent of the `DropdownMenu.ItemLabel` part if provided, or fallback to the .textContent of the `DropdownMenu.Item`. Use this when the content is complex, or you have non-textual content inside. | | disabled | `boolean`
Whether the item is disabled or not. | | closeOnSelect | `boolean`
Whether the menu should close when the item is checked. | | onSelect | `() => void`
Event handler called when the user selects an item (via mouse or keyboard). | | Data attribute | Description | | --- | --- | | data-disabled | Present when the item is disabled. | | data-checked | Present when the item is checked. | | data-highlighted | Present when the item is highlighted. | ### DropdownMenu.CheckboxItem | Prop | Description | | --- | --- | | checked | `boolean`
The controlled checked state of the item. | | defaultChecked | `boolean`
The default checked state when initially rendered. Useful when you do not need to control the checked state. | | onChange | `(checked: boolean) => void`
Event handler called when the checked state of the item changes. | | textValue | `string`
Optional text used for typeahead purposes. By default, the typeahead behavior will use the .textContent of the `DropdownMenu.ItemLabel` part if provided, or fallback to the .textContent of the `DropdownMenu.Item`. Use this when the content is complex, or you have non-textual content inside. | | indeterminate | `boolean`
Whether the item is in an indeterminate state. | | disabled | `boolean`
Whether the item is disabled or not. | | closeOnSelect | `boolean`
Whether the menu should close when the item is checked/unchecked. | | onSelect | `() => void`
Event handler called when the user selects an item (via mouse or keyboard). | | Data attribute | Description | | --- | --- | | data-disabled | Present when the item is disabled. | | data-indeterminate | Present when the item is in an indeterminate state. | | data-checked | Present when the item is checked. | | data-highlighted | Present when the item is highlighted. | ### DropdownMenu.Sub | Prop | Description | | --- | --- | | open | `boolean`
The controlled open state of the sub menu. | | defaultOpen | `boolean`
The default open state when initially rendered. Useful when you do not need to control the open state. | | onOpenChange | `(open: boolean) => void`
Event handler called when the open state of the sub menu changes. | `DropdownMenu.Sub` also accepts the following props to customize the placement of the `DropdownMenu.SubContent`. | Prop | Description | | --- | --- | | getAnchorRect | `(anchor?: HTMLElement) => AnchorRect | undefined`
Function that returns the trigger element's DOMRect. | | gutter | `number`
The distance between the sub menu content and the trigger element. By default, it's 0 plus half of the arrow offset, if it exists. | | shift | `number`
The skidding of the sub menu content along the trigger element. | | slide | `boolean`
Whether the sub menu content should slide when it overflows. | | overlap | `boolean`
Whether the sub menu content can overlap the trigger element when it overflows. | | fitViewport | `boolean`
Whether the sub menu content should fit the viewport. If this is set to true, the sub menu content will have `maxWidth` and `maxHeight` set to the viewport size. This will be exposed to CSS as `--kb-popper-content-available-width` and `--kb-popper-content-available-height`. | | hideWhenDetached | `boolean`
Whether to hide the sub menu content when the trigger element becomes occluded. | | detachedPadding | `number`
The minimum padding in order to consider the trigger element occluded. | | arrowPadding | `number`
The minimum padding between the arrow and the sub menu content corner. | | overflowPadding | `number`
The minimum padding between the sub menu content and the viewport edge. This will be exposed to CSS as `--kb-popper-overflow-padding`. | ### DropdownMenu.SubTrigger | Prop | Description | | --- | --- | | textValue | `string`
Optional text used for typeahead purposes. By default, the typeahead behavior will use the .textContent of the `DropdownMenu.SubTrigger`. Use this when the content is complex, or you have non-textual content inside. | | disabled | `boolean`
Whether the sub menu trigger is disabled or not. | | Data attribute | Description | | --- | --- | | data-disabled | Present when the item is disabled. | | data-highlighted | Present when the item is highlighted. | ### DropdownMenu.SubContent | Prop | Description | | --- | --- | | onEscapeKeyDown | `(event: KeyboardEvent) => void`
Event handler called when the escape key is down. It can be prevented by calling `event.preventDefault`. | | onPointerDownOutside | `(event: PointerDownOutsideEvent) => void`
Event handler called when a pointer event occurs outside the bounds of the component. It can be prevented by calling `event.preventDefault`. | | onFocusOutside | `(event: FocusOutsideEvent) => void`
Event handler called when the focus moves outside the bounds of the component. It can be prevented by calling `event.preventDefault`. | | onInteractOutside | `(event: InteractOutsideEvent) => void`
Event handler called when an interaction (pointer or focus event) happens outside the bounds of the component. It can be prevented by calling `event.preventDefault`. | ## Rendered elements | Component | Default rendered element | | --- | --- | | `DropdownMenu` | none | | `DropdownMenu.Trigger` | `button` | | `DropdownMenu.Icon` | `span` | | `DropdownMenu.Portal` | `Portal` | | `DropdownMenu.Content` | `div` | | `DropdownMenu.Arrow` | `div` | | `DropdownMenu.Separator` | `hr` | | `DropdownMenu.Group` | `div` | | `DropdownMenu.GroupLabel` | `span` | | `DropdownMenu.Sub` | none | | `DropdownMenu.SubTrigger` | `div` | | `DropdownMenu.SubContent` | `div` | | `DropdownMenu.Item` | `div` | | `DropdownMenu.ItemLabel` | `div` | | `DropdownMenu.ItemDescription` | `div` | | `DropdownMenu.ItemIndicator` | `div` | | `DropdownMenu.RadioGroup` | `div` | | `DropdownMenu.RadioItem` | `div` | | `DropdownMenu.CheckboxItem` | `div` | ## Accessibility ### Keyboard Interactions | Key | Description | | --- | --- | | `Space` | When focus is on the trigger, opens the menu and focuses the first item.
When focus is on an item, activates the item. | | `Enter` | When focus is on the trigger, opens the menu and focuses the first item.
When focus is on an item, activates the item. | | `ArrowDown` | When focus is on the trigger, opens the menu and focuses the first item.
When focus is on an item, moves focus to the next item. | | `ArrowUp` | When focus is on the trigger, opens the menu and focuses the last item.
When focus is on an item, moves focus to the previous item. | | `ArrowRight` / `ArrowLeft` | When focus is on a sub menu trigger, opens or closes the submenu depending on reading direction. | | `Home` | When focus is on an item, moves focus to first item. | | `End` | When focus is on an item, moves focus to last item. | | `Esc` | Closes the menu and moves focus to the trigger. | Previous[←Dialog](https://kobalte.dev/docs/core/components/dialog)Next[File Field→](https://kobalte.dev/docs/core/components/file-field)