Vitral 0.2
Menu

Menubar

The application menu bar, with nested menus, that becomes a single menu button on narrow screens.

Import

main.ts
import { Menubar } from '@vitral/vue';

Basic

Vitral
GW
Last command: —
<script setup lang="ts">import { Avatar, InputText, Menubar, type MenuItem } from '@vitral/vue';import { ref } from 'vue'; const last = ref('—');const run = ({ item }: { item: MenuItem }) => (last.value = item.label ?? '');const items: MenuItem[] = [    { label: 'Home', icon: 'home', command: run },    {        label: 'Projects',        icon: 'folder',        items: [            { label: 'Vitral', icon: 'star', command: run },            { label: 'Archive', icon: 'folderOpen', items: [{ label: '2025', command: run }, { label: '2024', command: run }] },            { separator: true },            { label: 'New project', icon: 'plus', command: run }        ]    },    {        label: 'Team',        icon: 'user',        items: [            { label: 'Members', command: run },            { label: 'Invitations', command: run, disabled: true }        ]    },    { label: 'Docs', icon: 'externalLink', url: '#' }];</script> <template>    <Menubar :model="items" aria-label="Application">        <template #start><strong style="padding-inline: 0.5rem">Vitral</strong></template>        <template #end>            <div style="display: flex; align-items: center; gap: 0.5rem">                <InputText size="small" placeholder="Search" aria-label="Search" />                <Avatar label="GW" shape="circle" />            </div>        </template>    </Menubar>    <small style="color: var(--vt-text-muted-color)">Last command: {{ last }}</small></template>

Small screens

A breakpoint wider than any screen keeps this one in its small-screen form.
<script setup lang="ts">import { Menubar, type MenuItem } from '@vitral/vue'; const items: MenuItem[] = [    { label: 'Home', icon: 'home' },    {        label: 'Projects',        icon: 'folder',        items: [            { label: 'Vitral', icon: 'star' },            { label: 'Archive', icon: 'folderOpen', items: [{ label: '2025' }, { label: '2024' }] },            { separator: true },            { label: 'New project', icon: 'plus' }        ]    },    {        label: 'Team',        icon: 'user',        items: [{ label: 'Members' }, { label: 'Invitations', disabled: true }]    },    { label: 'Docs', icon: 'externalLink', url: '#' }];</script> <template>    <Menubar :model="items" aria-label="Application (compact)" breakpoint="100000px" />    <small style="color: var(--vt-text-muted-color)">A breakpoint wider than any screen keeps this one in its small-screen form.</small></template>

API

Read from packages/vue/src/components/Menubar/types.ts, so it says what the component actually accepts.

Props

NameTypeDescription
modelMenuItem[]The top-level items; their `items` drop down as menus, which may nest further.
breakpointstringBelow this width the bar becomes a menu button with the items in a column. Defaults to `'960px'`.
ariaLabelstringNames the menubar.
ariaLabelledbystring—

Plus pt, dt and unstyled from BaseProps, see pass-through and unstyled mode.

Emits

EventPayloadDescription
mobile-toggleopen: booleanThe small-screen menu was opened or closed.

Slots

NameSlot propsDescription
start—Before the items: a logo.
end—After the items: a search box, an avatar.
item(props: NestedMenuItemSlotProps)—
buttonicon—The small-screen menu button's icon.