Menubar
Desktop-style menu bar.
Usage
Compose Root > Menu > (Trigger + Content). Menu pairs one trigger with its panel; a menubar holds several. Give
Root an aria-label.
Menubar vs Dropdown Menu
A menubar is not a row of Dropdown Menus. Two behaviours make it a single control rather than several:
- Arrow keys move between the top-level menus, so the whole bar is one tab stop.
- Once one menu is open, hovering a sibling switches to it — no second click. That is the desktop-app behaviour people already expect from a menu bar.
Build it from separate dropdowns and you lose both, which is exactly the kind of regression nobody notices with a mouse.
When not to use it
A menubar is a desktop-application pattern. On a website it is usually the wrong shape.
It assumes a pointer that hovers and a screen wide enough for several always-visible triggers — neither holds on a phone. For site navigation reach for a Navigation Menu; for a handful of actions on a toolbar, a Dropdown Menu or Toolbar. Use a menubar when you are genuinely building an application chrome — an editor, an IDE-like tool.
Props
Menubar.Root
| Prop | Type | Default |
|---|---|---|
class Extra classes merged onto the menubar. | string | — |
child bits-ui | Snippet<[{ props: Record<string, unknown>; }]> | undefined | — |
children bits-ui | Snippet<[]> | undefined | — |
dir bits-ui The reading direction of the menubar. | Direction | undefined | — |
id bits-ui | string | undefined | — |
loop bits-ui When `true`, the roving focus will loop back to the first menu item when the last menu item is reached and vice verse. | boolean | undefined | — |
onValueChange bits-ui A callback that is called when the active menu changes. | OnChangeFn<string> | undefined | — |
ref bits-ui | HTMLElement | null | undefined | — |
value bits-ui The 'value' assigned to the currently active menu in the menubar. | string | undefined | — |
Menubar.Menu
| Prop | Type | Default |
|---|---|---|
children bits-ui | Snippet<[]> | undefined | — |
onOpenChange bits-ui A callback that is called when the menu is opened or closed. | OnChangeFn<boolean> | undefined | — |
value bits-ui The `value` assigned to the menu. Used to programmatically control the menu's open state within the menubar. | string | undefined | — |
Menubar.Trigger
| Prop | Type | Default |
|---|---|---|
class Extra classes merged onto the trigger. | string | — |
child bits-ui | Snippet<[{ props: Record<string, unknown>; }]> | undefined | — |
children bits-ui | Snippet<[]> | undefined | — |
disabled bits-ui Whether the trigger for the menubar item is disabled. | boolean | null | undefined | false |
id bits-ui | string | undefined | — |
ref bits-ui | HTMLElement | null | undefined | — |
Menubar.Content
| Prop | Type | Default |
|---|---|---|
class Extra classes merged onto the menu panel. | string | — |
align bits-ui The preferred alignment of the anchor to render against when open. This may change when collisions occur. | "start" | "center" | "end" | undefined | — |
alignOffset bits-ui An offset in pixels from the "start" or "end" alignment options. | number | undefined | — |
arrowPadding bits-ui This describes the padding between the arrow and the edges of the floating element. If your floating element has border-radius, this will prevent it from overflowing the corners. | number | undefined | — |
avoidCollisions bits-ui When `true`, overrides the `side` and `align` options to prevent collisions with the boundary edges. | boolean | undefined | true |
child bits-ui | Snippet<[FloatingContentSnippetProps & { props: Record<string, unknown>; }]> | undefined | — |
children bits-ui | Snippet<[]> | undefined | — |
collisionBoundary bits-ui A boundary element or array of elements to check for collisions against. | Arrayable<Boundary> | undefined | — |
collisionPadding bits-ui The amount in pixels of virtual padding around the viewport edges to check for overflow which will cause a collision. | number | Partial<Record<"top" | "right" | "bottom" | "left", number>> | undefined | 8 |
customAnchor bits-ui Use an element other than the trigger to anchor the content to. If provided, the content will be anchored to the provided element instead of the trigger. You can pass a selector string or an HTMLElement. | string | HTMLElement | Measurable | null | undefined | — |
dir bits-ui The text direction of the content. | Direction | undefined | — |
escapeKeydownBehavior bits-ui Escape behavior type. `close`: Closes the element immediately. `defer-otherwise-close`: Delegates the action to its parent component that has an escape keydown handler. If no parent is found, it closes the element. `defer-otherwise-ignore`: Delegates the action to the parent element. If no parent is found, nothing is done. `ignore`: Prevents the element from closing and also blocks the parent element from closing in response to an escape key press. | EscapeBehaviorType | undefined | `close` |
forceMount bits-ui Whether to force mount the component. | boolean | undefined | — |
hideWhenDetached bits-ui | boolean | undefined | — |
id bits-ui | string | undefined | — |
interactOutsideBehavior bits-ui Interact outside behavior type. `close`: Closes the element immediately. `defer-otherwise-close`: Delegates the action to the parent element. If no parent is found, it closes the element. `defer-otherwise-ignore`: Delegates the action to the parent element. If no parent is found, nothing is done. `ignore`: Prevents the element from closing and also blocks the parent element from closing in response to an outside interaction. | InteractOutsideBehaviorType | undefined | `close` |
loop bits-ui When `true`, the menu will loop through items when navigating with the keyboard. | boolean | undefined | false |
onCloseAutoFocus bits-ui Event handler called when auto-focusing on close. Can be prevented. | EventCallback | undefined | — |
onEscapeKeydown bits-ui Callback fired when escape is pressed. | ((e: KeyboardEvent) => void) | undefined | — |
onFocusOutside bits-ui Callback fired when focus leaves the dismissible layer. | ((event: FocusEvent) => void) | undefined | — |
onInteractOutside bits-ui Callback fired when an outside interaction event completes, which is either a `pointerup`, `mouseup`, or `touchend` event, depending on the user's input device. | InteractOutsideEventHandler | undefined | — |
onOpenAutoFocus bits-ui Event handler called when auto-focusing on open. Can be prevented. | EventCallback | undefined | — |
preventOverflowTextSelection bits-ui Passing `true` will prevent the overflow of text selection outside the element, provided the element is the top layer. | boolean | undefined | `true` |
preventScroll bits-ui Whether to prevent scrolling the body when the content is open. Whether to prevent body scrolling when the content is open. | boolean | undefined | true |
ref bits-ui | HTMLElement | null | undefined | — |
side bits-ui The preferred side of the anchor to render against when open. Will be reversed when collisions occur. | "top" | "right" | "bottom" | "left" | undefined | — |
sideOffset bits-ui The distance in pixels from the anchor to the floating element. | number | undefined | — |
sticky bits-ui | "partial" | "always" | undefined | — |
strategy bits-ui The positioning strategy to use for the floating element. | "absolute" | "fixed" | undefined | — |
trapFocus bits-ui Whether focus is trapped within the focus scope. | boolean | undefined | false |
updatePositionStrategy bits-ui "optimized" will only update the position when necessary, while "always" will update the position on each animation frame, which is useful if the floating content is following something like a mouse cursor. | "always" | "optimized" | undefined | "optimized" |
Menubar.Item (shared)
| Prop | Type | Default |
|---|---|---|
class Extra classes merged onto the item. | string | — |
child bits-ui | Snippet<[{ props: Record<string, unknown>; }]> | undefined | — |
children bits-ui | Snippet<[]> | undefined | — |
closeOnSelect bits-ui Whether or not the menu item should close when selected. | boolean | undefined | true |
disabled bits-ui When `true`, the user will not be able to interact with the menu item. | boolean | undefined | false |
id bits-ui | string | undefined | — |
onSelect bits-ui A callback fired when the menu item is selected. Prevent default behavior of selection with `event.preventDefault()`. | ((event: Event) => void) | undefined | — |
ref bits-ui | HTMLElement | null | undefined | — |
textValue bits-ui Optional text to use for typeahead filtering. By default, typeahead will use the `.textContent` of the menu item. When the content is more complex, you can provide a string here instead. | string | undefined | undefined |
Menubar.Trigger
Menubar.Content
Menu, Sub, SubTrigger, SubContent, CheckboxItem, RadioItem, RadioGroup and Arrow are re-exported from Bits unchanged.