Components / Navigation

Sidebar

A responsive app sidebar with collapsible groups and a mobile drawer.

Preview

Overview

Workspace

Select a destination from the sidebar to continue.

Install

Run in your project
Package manager
npx @getweini/cli@latest add sidebar

Use cases

Workspace shell

Keep project-level navigation beside the main page content.

Nested section

Expand a section to reveal related routes, with the active child visible.

Usage example

Vue
<SidebarProvider>
  <Sidebar>
    <SidebarHeader>
      Workspace
      <SidebarTrigger aria-label="Toggle sidebar"><MenuIcon aria-hidden="true" /></SidebarTrigger>
    </SidebarHeader>
    <SidebarContent aria-label="Workspace navigation">
      <SidebarGroup>
        <SidebarGroupLabel>Workspace</SidebarGroupLabel>
        <SidebarMenu>
          <SidebarMenuItem>
            <SidebarMenuButton>
              <template #icon><DashboardIcon aria-hidden="true" /></template>
              Dashboard
            </SidebarMenuButton>
            <SidebarMenuSub>
              <SidebarMenuItem><SidebarMenuButton href="/dashboard/reports">Reports</SidebarMenuButton></SidebarMenuItem>
            </SidebarMenuSub>
          </SidebarMenuItem>
        </SidebarMenu>
      </SidebarGroup>
    </SidebarContent>
  </Sidebar>
  <SidebarInset>Page content</SidebarInset>
</SidebarProvider>

More examples

Workspace navigation

The provider owns state for the sidebar and inset.

Workspace navigation
<script setup lang="ts">
import Sidebar from './components/ui/sidebar/Sidebar.vue'
import SidebarContent from './components/ui/sidebar/SidebarContent.vue'
import SidebarGroup from './components/ui/sidebar/SidebarGroup.vue'
import SidebarGroupLabel from './components/ui/sidebar/SidebarGroupLabel.vue'
import SidebarHeader from './components/ui/sidebar/SidebarHeader.vue'
import SidebarInset from './components/ui/sidebar/SidebarInset.vue'
import SidebarMenu from './components/ui/sidebar/SidebarMenu.vue'
import SidebarMenuButton from './components/ui/sidebar/SidebarMenuButton.vue'
import SidebarMenuItem from './components/ui/sidebar/SidebarMenuItem.vue'
import SidebarProvider from './components/ui/sidebar/SidebarProvider.vue'
import SidebarTrigger from './components/ui/sidebar/SidebarTrigger.vue'
</script>

<template>
  <SidebarProvider><Sidebar>
    <SidebarHeader>Atlas <SidebarTrigger aria-label="Toggle navigation">Menu</SidebarTrigger></SidebarHeader>
    <SidebarContent aria-label="Workspace navigation"><SidebarGroup><SidebarGroupLabel>Workspace</SidebarGroupLabel><SidebarMenu>
      <SidebarMenuItem><SidebarMenuButton href="/dashboard" active>Dashboard</SidebarMenuButton></SidebarMenuItem>
      <SidebarMenuItem><SidebarMenuButton href="/projects">Projects</SidebarMenuButton></SidebarMenuItem>
    </SidebarMenu></SidebarGroup></SidebarContent>
  </Sidebar><SidebarInset><main><h1>Dashboard</h1></main></SidebarInset></SidebarProvider>
</template>

Expandable settings

A parent without href opens its child links from the whole row.

Expandable settings
<script setup lang="ts">
import Sidebar from './components/ui/sidebar/Sidebar.vue'
import SidebarContent from './components/ui/sidebar/SidebarContent.vue'
import SidebarGroup from './components/ui/sidebar/SidebarGroup.vue'
import SidebarGroupLabel from './components/ui/sidebar/SidebarGroupLabel.vue'
import SidebarInset from './components/ui/sidebar/SidebarInset.vue'
import SidebarMenu from './components/ui/sidebar/SidebarMenu.vue'
import SidebarMenuButton from './components/ui/sidebar/SidebarMenuButton.vue'
import SidebarMenuItem from './components/ui/sidebar/SidebarMenuItem.vue'
import SidebarMenuSub from './components/ui/sidebar/SidebarMenuSub.vue'
import SidebarProvider from './components/ui/sidebar/SidebarProvider.vue'
</script>

<template>
  <SidebarProvider><Sidebar><SidebarContent aria-label="Settings navigation">
    <SidebarGroup><SidebarGroupLabel>Settings</SidebarGroupLabel><SidebarMenu>
      <SidebarMenuItem default-open><SidebarMenuButton>Account</SidebarMenuButton><SidebarMenuSub>
        <SidebarMenuItem><SidebarMenuButton href="/settings/profile" active>Profile</SidebarMenuButton></SidebarMenuItem>
        <SidebarMenuItem><SidebarMenuButton href="/settings/security">Security</SidebarMenuButton></SidebarMenuItem>
      </SidebarMenuSub></SidebarMenuItem>
    </SidebarMenu></SidebarGroup>
  </SidebarContent></Sidebar><SidebarInset><main><h1>Profile</h1></main></SidebarInset></SidebarProvider>
</template>

Key API

The most useful props, models, slots, events, and methods for this component.

Key API for Sidebar
NameTypeDefault or requirement
v-model:collapsed / defaultCollapsedbooleanfalse
v-model:mobileOpen / defaultMobileOpenbooleanfalse
mobilebooleanfalse
side / collapsibleleft | right / icon | noneleft / icon
SidebarMenuItem v-model:open / defaultOpenbooleanfalse
SidebarMenuButton #iconslotnone

A parent without href opens its child links when you click anywhere on the row. If the parent navigates, add SidebarMenuSubTrigger for a separate expand button. Mark the current child page to open its group automatically. Set the mobile breakpoint and save collapsed state in your application.

Implementation notes

  • Persist collapsed state in the application when it should survive navigation or reloads.
  • When a parent row also navigates, use SidebarMenuSubTrigger as its separate disclosure control.

Accessibility and localization

  • Name the sidebar content and provide a usable label for icon-only triggers; mark the current route active.
Weini UIDesign system · Vue component library · Free and public