Back to components
Components

NavSidebar

A vertical navigation component used to display page links in a sidebar layout. Optimized for documentation and dashboard structures.

Component

Props

Props Required Default Type
sidebarIdtrue — string
menuItems — An example arraySidebarMenuItem[]
expandedWidth — 240number
collapsedWidth — 60number
multipleSubmenusOpen — falseboolean
isCollapsed — falseboolean
showCollapseDivider — falseboolean
dividerClass — border-border-neutral-subtlestring
collapsedSubmenuOffset — 20number
collapsedSubmenuWidth — 200number
collapsedSubmenuTrigger — Trigger.CLICKTrigger
collapsedFlipLimit — 8number
showCollapseToggle — falseboolean
collapseTogglePosition — Position.BOTTOMPosition
collapsedStateIcon — mdi:menu-closestring
expandedStateIcon — mdi:menu-openstring
showMobileSidebarClose — falseboolean
mobileSidebarCloseIcon — mdi:closestring
mobileBreakpoint — 1024number
isFixed — trueboolean
stickOnScroll — falseboolean
stickyScrollHeight — 0number
headerHeight — 0number
footerHeight — 0number
footerSafeAreaHeight — 180number
itemsStyleType — — SidebarNavMenuItemStyleType
itemsCustomClass — — string
itemsTextClass — — string
itemsIconClass — — string
subItemsCustomClass — — string
subItemsTextClass — — string
subItemsIconClass — — string
thirdLevelItemsCustomClass — — string
showNestedSectionLevelGuide — trueboolean
prefetchOn — PrefetchOn.VISIBILITYPrefetchOnStrategy
truncateDepth — []SidebarMenuDepth[]
marquee — falseboolean
moreActionsPosition — Position.BOTTOMPosition
moreActionsPositionYOffset — 4number | string
closeSidebarAriaLabel — 'Close sidebar'string
collapseSidebarAriaLabel — 'Collapse sidebar'string
expandSidebarAriaLabel — 'Expand sidebar'string

Slots

Name Description
sidebar-header

Template to render a header for the sidebar. It is commonly used for logos, language selectors, etc.

sidebar-menu

Template to fully replace the default menu. When used, it renders instead of the built-in menu built from the `menuItems` prop.

sidebar-menu-prefix-content

Template to render the prefix content before the menu items. It will render the content before the menu items inside the menu.

sidebar-menu-suffix-content

Template to render the suffix content before the menu items. It will render the content after the menu items inside the menu.

sidebar-footer

Template to render a footer for the sidebar. It is commonly used for footer menus, banners, etc.

 <template>
    <NavSidebar
        sidebarId="example-nav-sidebar"
        :menuItems="routeItems"
    >
        <template #sidebar-header>
            <!-- Add content here -->
        </template>

        <template #sidebar-menu>
            <!-- Add content here -->
        </template>

        <template #sidebar-menu-prefix-content>
            <!-- Add content here -->
        </template>

        <template #sidebar-menu-suffix-content>
            <!-- Add content here -->
        </template>

        <template #sidebar-footer>
            <!-- Add content here -->
        </template>
    </NavSidebar>
</template>
<script setup lang="ts">
const routeItems: SidebarMenuItem[] = [
    // ...
]
</script>
 

Usage

sidebarId

A unique identifier for the sidebar. It is used to manage the state of the sidebar (collapsed or expanded) when using multiple sidebars in the same application.

 <template>
    <NavSidebar
        sidebarId="main-sidebar"
    />
</template>
 
  • Type: string
  • Required: true

An array of objects used to render the menu items.

 <template>
    <NavSidebar
        :menuItems="routeItems"
    />
</template>
<script setup lang="ts">
const routeItems: SidebarMenuItem[] = [
    {
        isSectionTitle: true,
        text: 'Section title',
        icon: 'mdi:bullseye',
    },
    {
        text: 'Item 1',
        icon: 'mdi:help',
        to: '/',
    },
    {
        text: 'Item 2',
        icon: 'mdi:help',
        to: '/',
    },
    {
        isDivider: true,
    },
    {
        text: 'Item 3',
        icon: 'mdi:help',
        children: [
            {
                isSectionTitle: true,
                text: 'Subsection title',
                icon: 'mdi:shape-outline',
            },
            {
                text: 'Subitem 1',
                icon: 'mdi:help',
                children: [
                    {
                        isSectionTitle: true,
                        text: 'Nested subsection title',
                        icon: 'mdi:format-list-bulleted-square',
                    },
                    {
                        text: 'Third level item',
                        icon: 'mdi:help-circle-outline',
                        to: '/',
                    },
                ],
            },
            {
                text: 'Subitem 2',
                icon: 'mdi:help',
                to: '/',
            },
        ],
    },
]
</script>
 
  • Type: SidebarMenuItem[]
  • Default: An example array

NavSidebar supports up to 3 nested menu levels. You can render subsection headers at any level by setting isSectionTitle: true.

When the sidebar is collapsed, submenu labels are rendered as plain text labels without prefix markers.

Set isDivider: true on an item to render a horizontal Divider between entries instead of a link. Divider items need no other fields. They work at any nesting level and, when the sidebar is collapsed, become a separator line inside the submenu dropdown.

Set detectActive: false on an item to opt it out of route-based active highlighting. By default every item with a to highlights itself when the current route matches.

TypeScript interface

 interface SidebarMenuItem {
    text?: string
    icon?: string
    to?: string
    isSectionTitle?: boolean
    isDivider?: boolean
    children?: SidebarMenuItem[]
    disabled?: boolean
    detectActive?: boolean
    moreActionsItems?: DropdownMenuItem[]
    suffix?: () => VNode | VNode[]
    textSuffix?: () => VNode | VNode[]
}
 

Per-item slots

Name Description
suffix

Replaces the built-in more-actions trigger entirely. Renders right-aligned on row hover/focus.

text-suffix

Renders inline right after the item's label, e.g. for a badge or a count. Never clipped by `truncate`/`marquee`, and hidden when the sidebar is collapsed.


Set suffix/textSuffix on a menuItems entry as a render function:

 <template>
    <NavSidebar sidebarId="main-sidebar" :menuItems="routeItems" />
</template>
<script setup lang="ts">
import { h } from 'vue'

const routeItems: SidebarMenuItem[] = [
    {
        text: 'Inbox',
        icon: 'mdi:inbox-outline',
        to: '/inbox',
        textSuffix: () => h(Badge, { text: '12', color: ColorAccent.SUCCESS }),
    },
]
</script>
 

Or pass them as template slots when rendering NavSidebarMenuItem directly, e.g. inside NavSidebar's #sidebar-menu slot:

 <template>
    <NavSidebar sidebarId="main-sidebar">
        <template #sidebar-menu>
            <NavSidebarMenu>
                <NavSidebarMenuItem text="Inbox" icon="mdi:inbox-outline" to="/inbox">
                    <template #text-suffix>
                        <Badge text="12" :color="ColorAccent.SUCCESS" />
                    </template>
                </NavSidebarMenuItem>
            </NavSidebarMenu>
        </template>
    </NavSidebar>
</template>
 

expandedWidth

A number value that sets the width of the sidebar when it is expanded.

 <template>
    <NavSidebar
        :expandedWidth="300"
    />
</template>
 
  • Type: number
  • Default: 240

collapsedWidth

A number value that sets the width of the sidebar when it is collapsed.

 <template>
    <NavSidebar
        :collapsedWidth="80"
    />
</template>
 
  • Type: number
  • Default: 60

multipleSubmenusOpen

A boolean value that determines whether multiple submenus can be open at the same time.

 <template>
    <NavSidebar
        multipleSubmenusOpen
    />
</template>
 
  • Type: boolean
  • Default: false

isCollapsed

A boolean value that determines whether to render the sidebar in a collapsed state.

There are two ways to control the collapsed state of the sidebar:

With v-model

 <template>
    <NavSidebar
        v-model:isCollapsed="isSidebarCollapsed"
    />
</template>
<script setup lang="ts">
const isSidebarCollapsed = ref(false)
</script>
 
  • Type: boolean
  • Default: false

With the useSidebar composable

 <template>
    <NavSidebar
        :isCollapsed="isSidebarCollapsed('example-nav-sidebar')"
    /> 
</template>
<script setup lang="ts">
const { isSidebarCollapsed } = useSidebar()
</script>
 

Note

 <template>
    <NavSidebar
        sidebarId="example-nav-sidebar"
        isCollapsed
    />
</template>
 

showCollapseDivider

A boolean value that determines whether to render the section title as a divider when the sidebar is collapsed.

 <template>
    <NavSidebar
        isCollapsed
        showCollapseDivider
    />
</template>
 
  • Type: boolean
  • Default: false

dividerClass

Sets the border class applied to divider items ({ isDivider: true }) in the menu. Use it to change the divider color or thickness.

 <template>
    <NavSidebar
        dividerClass="border-border-default"
    />
</template>
 
  • Type: string
  • Default: border-border-neutral-subtle

collapsedSubmenuOffset

The collapsedSubmenuOffset prop allows you to set the horizontal offset for submenus when the sidebar is in a collapsed state. This offset determines how far the submenu will be positioned horizontally from the edge of the icon.

 <template>
    <NavSidebar
        isCollapsed
        :collapsedSubmenuOffset="30"
    />
</template>
 
  • Type: number
  • Default: 20

collapsedSubmenuWidth

The collapsedSubmenuWidth prop allows you to set the width for submenus dropdown when the sidebar is in a collapsed state.

 
<template>
    <NavSidebar
        isCollapsed
        :collapsedSubmenuMinWidth="250"
    />
</template>
 
  • Type: number
  • Default: 200

collapsedSubmenuTrigger

The collapsedSubmenuTrigger prop allows you to control how submenu dropdowns are opened when the sidebar is collapsed.

Collapsed submenu dropdowns support contextual lateral nesting up to 3 levels and render section titles (isSectionTitle: true) as non-interactive headers.

 <template>
    <NavSidebar
        isCollapsed
        :collapsedSubmenuTrigger="Trigger.HOVER"
    />
</template>
 
  • Type: Trigger
  • Default: Trigger.CLICK

Options

Value Description
CLICK

Open the collapsed submenu when clicking the icon item.

HOVER

Open the collapsed submenu when hovering the icon item.

collapsedFlipLimit

The submenu dropdown will have two possible opening directions in the collapsed state: upwards or downwards.

The collapsedFlipLimit prop allows you to specify how many of the submenu dropdowns should open downwards when the sidebar is in a collapsed state.

This is particularly useful for ensuring that submenus do not extend beyond the viewport when there are many items in the sidebar.

 <template>
    <NavSidebar
        :collapsedDropdownTopCount="5"
    />
</template>
 
  • Type: number
  • Default: 8

showCollapseToggle

A boolean value that determines whether to render the collapse toggle button to collapse or expand the sidebar.

 <template>
    <NavSidebar
        showCollapseToggle
    />
</template>
 
  • Type: boolean
  • Default: false

collapseTogglePosition

The collapseTogglePosition prop allows you to set the position of the collapse toggle button. It uses the Position enum.

 <template>
    <NavSidebar
        showCollapseToggle
        :collapseTogglePosition="Position.TOP"
    />
</template>
 
  • Type: Position
  • Default: Position.BOTTOM

Options

Value Description
TOP

The toggle button is rendered at the top of the sidebar.

BOTTOM

The toggle button is rendered at the bottom of the sidebar.

collapsedStateIcon

The collapsedStateIcon prop allows you to set a custom icon for the collapse toggle button when the sidebar is in a collapsed state.

 <template>
    <NavSidebar
        showCollapseToggle
        collapsedStateIcon="mdi:arrow-right-bold-circle"
    />
</template>
 
  • Type: string
  • Default: mdi:menu-close

expandedStateIcon

The expandedStateIcon prop allows you to set a custom icon for the collapse toggle button when the sidebar is in an expanded state.

 <template>
    <NavSidebar
        showCollapseToggle
        expandedStateIcon="mdi:arrow-left-bold-circle"
    />
</template>
 
  • Type: string
  • Default: mdi:menu-open

showMobileSidebarClose

A boolean value that determines whether to render the close button in the for the mobile sidebar.

It will only be visible on small screen widths and when the sidebar do not use the collapsed mode.

 <template>
    <NavSidebar
        showMobileSidebarClose
    />
</template>
 
  • Type: boolean
  • Default: false

mobileSidebarCloseIcon

The mobileSidebarCloseIcon prop allows you to set a custom icon for the close button in the mobile sidebar.

 <template>
    <NavSidebar
        showMobileSidebarClose
        mobileSidebarCloseIcon="mdi:close-circle"
    />
</template>
 
  • Type: string
  • Default: mdi:close-circle

mobileBreakpoint

The mobileBreakpoint prop sets the viewport width (in pixels) below which the sidebar switches to its mobile layout. It is the single source of truth for responsive switching: below it the sidebar behaves as a slide-in drawer (toggled by the mobile sidebar control); at or above it the sidebar is always visible. The value is reactive: changing it updates the layout immediately.

 <template>
    <NavSidebar
        :mobileBreakpoint="1024"
    />
</template>
 
  • Type: number
  • Default: 1024

isFixed

A boolean value that determines whether to render the sidebar as a fixed element.

 <template>
    <NavSidebar
        isFixed
    />
</template>
 

stickOnScroll

The stickOnScroll prop allows the sidebar to adjust its vertical position dynamically based on the user's scroll position. When enabled, it simulates a "sticky" behavior: the sidebar initially appears slightly offset from the top (defined by stickyScrollHeight), and as the user scrolls past that threshold, the sidebar sticks to the very top.

It requires isFixed to be true.

 <template>
    <NavSidebar
        stickOnScroll
    />
</template>
 
  • Type: boolean
  • Default: false

stickyScrollHeight

The stickyScrollHeight prop determines the height at which the sidebar will stick to the top when stickOnScroll is enabled. This value is used to calculate the initial offset of the sidebar.

It requires isFixed to be true.

 <template>
    <NavSidebar
        stickOnScroll
        stickyScrollHeight="85"
    />
</template>
 
  • Type: number
  • Default: 0

headerHeight

The headerHeight prop specifies the height of the header to the sidebar menu. It is used to calculate the total height of the sidebar menu and is particularly useful in layouts where the sidebar is below a sticky header.

 <template>
    <NavSidebar
        :headerHeight="100"
    />
</template>
 
  • Type: number
  • Default: 0

footerHeight

The footerHeight prop specifies the height of the footer to the sidebar menu. It is used to calculate the total height of the sidebar menu and is particularly useful in layouts where the sidebar is above a sticky footer.

 <template>
    <NavSidebar
        :footerHeight="40"
    />
</template>
 
  • Type: number
  • Default: 0

footerSafeAreaHeight

The footerSafeAreaHeight prop specifies a safe height for the sidebar menu in the event of using the bottom footer of the sidebar. It is used to calculate the total height of the sidebar menu.

 <template>
    <NavSidebar
        :footerSafeAreaHeight="180"
    />
</template>
 
  • Type: number
  • Default: 0

itemsStyleType

The itemsStyleType prop allows you to set the style of the menu items. It uses the SidebarNavMenuItemStyleType enum.

Important: It only works when menu items are passed as an array by using the menuItems props.

 <template>
    <NavSidebar
        :itemsStyleType="SidebarNavMenuItemStyleType.SPACED"
    />
</template>
 
  • Type: SidebarNavMenuItemStyleType
  • Default: SPACED

Options

Value Description
SPACED

The items have more space around them.

COMPACT

The items padding is more condensed and the optional icon is slightly smaller.

itemsCustomClass

The itemsCustomClass prop allows you to set custom classes on the menu item wrapper.

Use this prop for wrapper-level styles such as spacing, background, border, or font weight.

 <template>
    <NavSidebar
        :itemsCustomClass="'!rounded-xl !border !border-border-brand'"
    />
</template>
 

itemsTextClass

The itemsTextClass prop allows you to set custom classes specifically for top-level menu item text.

 <template>
    <NavSidebar
        :itemsTextClass="'!text-text-primary-brand-default'"
    />
</template>
 

itemsIconClass

The itemsIconClass prop allows you to set custom classes specifically for top-level menu item icon.

 <template>
    <NavSidebar
        :itemsIconClass="'!text-icon-primary-brand-default'"
    />
</template>
 

subItemsCustomClass

The subItemsCustomClass prop allows you to set custom classes on expanded child menu item wrappers (nested items).

 <template>
    <NavSidebar
        :subItemsCustomClass="'!rounded-lg !font-bold'"
    />
</template>
 

subItemsTextClass

The subItemsTextClass prop allows you to set custom classes specifically for expanded child menu item text.

 <template>
    <NavSidebar
        :subItemsTextClass="'!text-text-danger'"
    />
</template>
 

subItemsIconClass

The subItemsIconClass prop allows you to set custom classes specifically for expanded child menu item icon.

 <template>
    <NavSidebar
        :subItemsIconClass="'!text-icon-danger'"
    />
</template>
 

thirdLevelItemsCustomClass

The thirdLevelItemsCustomClass prop allows you to set custom classes on expanded third-level menu item wrappers.

 <template>
    <NavSidebar
        :thirdLevelItemsCustomClass="'!text-text-primary-brand-default !italic'"
    />
</template>
 

showNestedSectionLevelGuide

Controls whether nested entries (section titles and submenu items on level 2 and level 3) render a left vertical guide line in expanded mode.

 <template>
    <NavSidebar
        :showNestedSectionLevelGuide="true"
    />
</template>
 
  • Type: boolean
  • Default: true

prefetchOn

Controls when sidebar route targets should be prefetched. It uses either the PrefetchOnStrategy type or the PrefetchOn enum.

 <template>
    <NavSidebar
        sidebarId="main-sidebar"
        :menuItems="routeItems"
        :prefetchOn="PrefetchOn.INTERACTION"
    />
</template>
 
  • Type: PrefetchOnStrategy
  • Default: PrefetchOn.VISIBILITY

Options

Value Description
VISIBILITY

Prefetches routes based on visibility strategy.

INTERACTION

Prefetches routes when users hover or focus a sidebar item with a route target.

truncateDepth

An array of SidebarMenuDepth values that determines which nesting levels render their item text as single-line, ellipsis-truncated labels instead of wrapping across multiple lines. Levels don't need to be contiguous: you can truncate level 1 and level 3 while leaving level 2 items free to wrap.

 <template>
    <NavSidebar
        sidebarId="main-sidebar"
        :menuItems="routeItems"
        :truncateDepth="[SidebarMenuDepth.LEVEL_1, SidebarMenuDepth.LEVEL_2]"
    />
</template>
 
  • Type: SidebarMenuDepth[]
  • Default: []

Options

Value Description
LEVEL_1

Top-level menu items.

LEVEL_2

First-level nested (child) items.

LEVEL_3

Second-level nested (grandchild) items.

marquee

A boolean value that slides an item's full text into view on hover instead of leaving it ellipsis-truncated. It only affects items whose level is already in truncateDepth, so there's no separate per-level control for it.

 <template>
    <NavSidebar
        sidebarId="main-sidebar"
        :menuItems="routeItems"
        :truncateDepth="[SidebarMenuDepth.LEVEL_1]"
        marquee
    />
</template>
 
  • Type: boolean
  • Default: false

moreActionsItems

Set moreActionsItems on a menuItems entry to render a "more actions" trigger button on that item, opening a DropdownMenu with the given items. It's visible on row hover/focus and is automatically suppressed on parent items that already show a dropdown arrow for their children.

 <script setup lang="ts">
const routeItems: SidebarMenuItem[] = [
    {
        text: 'Inbox',
        icon: 'mdi:inbox-outline',
        to: '/inbox',
        moreActionsItems: [
            { text: 'Mark all as read', icon: 'mdi:email-check-outline' },
            { text: 'Archive', icon: 'mdi:archive-outline' },
        ],
    },
]
</script>
 
  • Type: DropdownMenuItem[]
  • Default: undefined

Use moreActionsPosition and moreActionsPositionYOffset below to control where this dropdown opens relative to its trigger. The menu is always right-aligned with the trigger; only the vertical side is configurable.

moreActionsPosition

Sets the preferred vertical side of the built-in "more actions" dropdown menu (rendered when an item defines moreActionsItems) relative to its trigger button. Uses the Position enum. Each row measures the space above and below it on hover/focus and automatically flips to the opposite side when the preferred side doesn't have enough room, so the menu never overflows the viewport.

 <template>
    <NavSidebar
        sidebarId="main-sidebar"
        :menuItems="routeItems"
        :moreActionsPosition="Position.TOP"
    />
</template>
 
  • Type: Position
  • Default: Position.BOTTOM

Options

Value Description
TOP

Places the menu above the trigger, right-aligned; flips below it if there isn't enough room above.

BOTTOM

Places the menu below the trigger, right-aligned; flips above it if there isn't enough room below.

moreActionsPositionYOffset

Sets the vertical offset of the "more actions" dropdown menu relative to its trigger. Positive values move the menu down, negative values move it up.

 <template>
    <NavSidebar
        sidebarId="main-sidebar"
        :menuItems="routeItems"
        :moreActionsPositionYOffset="4"
    />
</template>
 
  • Type: number | string
  • Default: 4

closeSidebarAriaLabel

The closeSidebarAriaLabel prop sets the accessible label for the mobile close sidebar button. Override it for i18n.

 <template>
    <NavSidebar
        closeSidebarAriaLabel="Cerrar barra lateral"
    />
</template>
 
  • Type: string
  • Default: 'Close sidebar'

collapseSidebarAriaLabel

The collapseSidebarAriaLabel prop sets the accessible label for the collapse sidebar toggle button. Override it for i18n.

 <template>
    <NavSidebar
        collapseSidebarAriaLabel="Contraer barra lateral"
    />
</template>
 
  • Type: string
  • Default: 'Collapse sidebar'

expandSidebarAriaLabel

The expandSidebarAriaLabel prop sets the accessible label for the expand sidebar toggle button. Override it for i18n.

 <template>
    <NavSidebar
        expandSidebarAriaLabel="Expandir barra lateral"
    />
</template>
 
  • Type: string
  • Default: 'Expand sidebar'

You can also pass an object strategy:

 {
    visibility: true,
    interaction: true,
}