Menubar
Move across top-level menus before navigating each command hierarchy.
Usage
Application
Move across top-level application menus, then enter the open command list.
Move across top-level application menus, then enter the open command list.
Choose a command from the menu bar
<!-- Menubar / Application -->
<script setup lang="ts">
import { MenubarRoot, MenubarItem, MenubarContent, MenubarSeparator } from '@sectile/vue/menubar'
import { ref } from 'vue'
const lastAction = ref('')
const items = [
{ id: 'file', parentID: null },
{ id: 'new-project', parentID: 'file' },
{ id: 'open-project', parentID: 'file' },
{ id: 'edit', parentID: null },
{ id: 'undo', parentID: 'edit' },
{ id: 'redo', parentID: 'edit' },
{ id: 'help', parentID: null },
{ id: 'shortcuts', parentID: 'help' },
]
const labels = {
file: 'File',
'new-project': 'New project',
'open-project': 'Open project',
edit: 'Edit',
undo: 'Undo',
redo: 'Redo',
help: 'Help',
shortcuts: 'Keyboard shortcuts',
}
const textValue = id => labels[id] ?? id
</script>
<template>
<MenubarRoot
:items="items"
:text-value="textValue"
default-highlighted-value="file"
label="Application commands"
@invoke="lastAction = $event"
>
<MenubarItem value="file" as="button">File</MenubarItem>
<MenubarContent for="file">
<MenubarItem value="new-project" as="button">New project</MenubarItem>
<MenubarSeparator />
<MenubarItem value="open-project" as="button">Open project</MenubarItem>
</MenubarContent>
<MenubarItem value="edit" as="button">Edit</MenubarItem>
<MenubarContent for="edit">
<MenubarItem value="undo" as="button">Undo</MenubarItem>
<MenubarItem value="redo" as="button">Redo</MenubarItem>
</MenubarContent>
<MenubarItem value="help" as="button">Help</MenubarItem>
<MenubarContent for="help">
<MenubarItem value="shortcuts" as="button">Keyboard shortcuts</MenubarItem>
</MenubarContent>
</MenubarRoot>
<p role="status">{{ lastAction ? lastAction + ' invoked' : 'Choose an action' }}</p>
</template>Disabled root
Skip an unavailable top-level menu while preserving movement between its siblings.
Skip an unavailable top-level menu while preserving movement between its siblings.
View menu is unavailable in this workspace
<!-- Menubar / Disabled Root -->
<script setup lang="ts">
import { MenubarRoot, MenubarItem, MenubarContent, MenubarSeparator } from '@sectile/vue/menubar'
import { ref } from 'vue'
const lastAction = ref('')
const items = [
{ id: 'file', parentID: null },
{ id: 'new-project', parentID: 'file' },
{ id: 'open-project', parentID: 'file' },
{ id: 'edit', parentID: null },
{ id: 'undo', parentID: 'edit' },
{ id: 'redo', parentID: 'edit' },
{ id: 'help', parentID: null },
{ id: 'shortcuts', parentID: 'help' },
]
const labels = {
file: 'File',
'new-project': 'New project',
'open-project': 'Open project',
edit: 'Edit',
undo: 'Undo',
redo: 'Redo',
help: 'Help',
shortcuts: 'Keyboard shortcuts',
}
const textValue = id => labels[id] ?? id
</script>
<template>
<MenubarRoot
:items="items"
:text-value="textValue"
default-highlighted-value="file"
label="Application commands"
@invoke="lastAction = $event"
>
<MenubarItem value="file" as="button">File</MenubarItem>
<MenubarContent for="file">
<MenubarItem value="new-project" as="button">New project</MenubarItem>
<MenubarSeparator />
<MenubarItem value="open-project" as="button">Open project</MenubarItem>
</MenubarContent>
<MenubarItem value="edit" as="button">Edit</MenubarItem>
<MenubarContent for="edit">
<MenubarItem value="undo" as="button">Undo</MenubarItem>
<MenubarItem value="redo" as="button">Redo</MenubarItem>
</MenubarContent>
<MenubarItem value="help" as="button">Help</MenubarItem>
<MenubarContent for="help">
<MenubarItem value="shortcuts" as="button">Keyboard shortcuts</MenubarItem>
</MenubarContent>
</MenubarRoot>
<p role="status">{{ lastAction ? lastAction + ' invoked' : 'Choose an action' }}</p>
</template>Typeahead
Move to the next menu whose label matches the typed prefix.
Move to the next menu whose label matches the typed prefix.
Focus the menu bar and type a menu name
<!-- Menubar / Typeahead -->
<script setup lang="ts">
import { MenubarRoot, MenubarItem, MenubarContent, MenubarSeparator } from '@sectile/vue/menubar'
import { ref } from 'vue'
const lastAction = ref('')
const items = [
{ id: 'file', parentID: null },
{ id: 'new-project', parentID: 'file' },
{ id: 'open-project', parentID: 'file' },
{ id: 'edit', parentID: null },
{ id: 'undo', parentID: 'edit' },
{ id: 'redo', parentID: 'edit' },
{ id: 'help', parentID: null },
{ id: 'shortcuts', parentID: 'help' },
]
const labels = {
file: 'File',
'new-project': 'New project',
'open-project': 'Open project',
edit: 'Edit',
undo: 'Undo',
redo: 'Redo',
help: 'Help',
shortcuts: 'Keyboard shortcuts',
}
const textValue = id => labels[id] ?? id
</script>
<template>
<MenubarRoot
:items="items"
:text-value="textValue"
default-highlighted-value="file"
label="Application commands"
@invoke="lastAction = $event"
>
<MenubarItem value="file" as="button">File</MenubarItem>
<MenubarContent for="file">
<MenubarItem value="new-project" as="button">New project</MenubarItem>
<MenubarSeparator />
<MenubarItem value="open-project" as="button">Open project</MenubarItem>
</MenubarContent>
<MenubarItem value="edit" as="button">Edit</MenubarItem>
<MenubarContent for="edit">
<MenubarItem value="undo" as="button">Undo</MenubarItem>
<MenubarItem value="redo" as="button">Redo</MenubarItem>
</MenubarContent>
<MenubarItem value="help" as="button">Help</MenubarItem>
<MenubarContent for="help">
<MenubarItem value="shortcuts" as="button">Keyboard shortcuts</MenubarItem>
</MenubarContent>
</MenubarRoot>
<p role="status">{{ lastAction ? lastAction + ' invoked' : 'Choose an action' }}</p>
</template>API
Vue package: @sectile/vue/menubar
MenubarItemMenubarSeparatorMenubarContentMenubarRoot
Props
MenubarItemProps
as- Type
PrimitiveAsDefaultundefinedElement or component rendered for this part.
asChild- Type
booleanDefaultundefinedWhether to merge this part into its single child instead of rendering a wrapper.
disabled- Type
booleanDefaultundefinedWhether interaction is unavailable.
value- Type
stringDefaultRequiredCurrent value exposed by this contract.
MenubarPartProps
as- Type
PrimitiveAsDefaultVaries by partElement or component rendered for this part.
asChild- Type
booleanDefaultfalseWhether to merge this part into its single child instead of rendering a wrapper.
MenubarRootProps
as- Type
PrimitiveAsDefaultundefinedElement or component rendered for this part.
asChild- Type
booleanDefaultundefinedWhether to merge this part into its single child instead of rendering a wrapper.
defaultHighlightedValue- Type
string | nullDefaultundefinedInitially highlighted value for uncontrolled state.
disabled- Type
booleanDefaultundefinedWhether interaction is unavailable.
disabledItems- Type
readonly string[]DefaultundefinedItem values excluded from focus and selection.
items- Type
readonly MenuItemDefinition<string>[]DefaultRequiredOrdered item values managed by the component.
label- Type
stringDefaultundefinedAccessible name announced for the control.
policies- Type
MenuPolicies<string>DefaultundefinedBehavior policies that customize validation, movement, or selection.
textValue- Type
(id: string) => stringDefaultundefinedReturns searchable or presentational text for an item value.
MenubarContentProps
as- Type
PrimitiveAsDefaultundefinedElement or component rendered for this part.
asChild- Type
booleanDefaultundefinedWhether to merge this part into its single child instead of rendering a wrapper.
for- Type
stringDefaultRequiredValue or ID of the related part targeted by this component.
Slots
MenubarItemSlotProps
disabled- Type
booleanWhether interaction is unavailable.
highlighted- Type
booleanWhether this item is highlighted for interaction.
open- Type
booleanWhether the associated popup or disclosure is open.
value- Type
stringCurrent value exposed by this contract.
MenubarRootSlotProps
disabled- Type
booleanWhether interaction is unavailable.
highlightedValue- Type
string | nullValue currently highlighted for interaction.
open- Type
booleanWhether the associated popup or disclosure is open.
openPath- Type
readonly string[]Ordered values in the open menu path.
Events
MenubarRoot
invoke- Payload
stringEmitted when the current action is invoked.
update:open- Payload
booleanEmitted when the component requests a new open state.
Parts
Shared scope: [data-scope="menubar"]. Combine it with a part selector to keep styles local to this component.
| Part | Selector | Role | Extra attributes |
|---|---|---|---|
root | [data-part="root"] | Defines the component boundary and owns its composed parts. | — |
item | [data-part="item"] | Menu item at any hierarchy depth; use data-level to distinguish top-level and nested items | data-level="<depth>" |
sub-content | [data-part="sub-content"] | Popup content owned by a parent menu item | data-scope="menu"data-level="<depth>" |
separator | [data-part="separator"] | Separates related groups without becoming an action. | data-scope="menu" |
Keyboard interaction
| Key | Behavior |
|---|---|
| Arrow Left / Arrow Right | Move between root menu items. |
| Arrow Down / Arrow Up | Open a branch or move inside its vertical item list. |
| Home / End | Move to the first or last item at the current level. |
| Enter / Space | Open a branch or invoke the current item. |
| Escape | Close the branch and return to its owner. |
Accessibility
The root exposes menubar semantics while opened branches use hierarchical menu items and roving focus.
See the corresponding WAI-ARIA pattern for the host accessibility contract.
