Sidebar

A composable, themeable and customizable sidebar component.

Credits

I just want to start by thanking the shadcn-vue & shadcn-ui team for doing the heavy lifting for this component. I basically just copied their code and have it here for this thing.

The Setup

  1. To get started, you should add the component to your project.
npx ui-thing@latest add sidebar
  1. Next you will need to update your tailwind.css file to include the following:
@layer base {
  :root {
    --sidebar-background: 0 0% 98%;
    --sidebar-foreground: 240 5.3% 26.1%;
    --sidebar-primary: 240 5.9% 10%;
    --sidebar-primary-foreground: 0 0% 98%;
    --sidebar-accent: 240 4.8% 95.9%;
    --sidebar-accent-foreground: 240 5.9% 10%;
    --sidebar-border: 220 13% 91%;
    --sidebar-ring: 217.2 91.2% 59.8%;
    --sidebar-input: 240 5.9% 90%;
  }

  .dark {
    --sidebar-background: 240 5.9% 10%;
    --sidebar-foreground: 240 4.8% 95.9%;
    --sidebar-primary: 224.3 76.3% 48%;
    --sidebar-primary-foreground: 0 0% 100%;
    --sidebar-accent: 240 3.7% 15.9%;
    --sidebar-accent-foreground: 240 4.8% 95.9%;
    --sidebar-border: 240 3.7% 15.9%;
    --sidebar-ring: 217.2 91.2% 59.8%;
    --sidebar-input: 240 3.7% 15.9%;
  }
}
  1. Now update the tailwind.config.js file to include the following:
// ...
sidebar: {
  DEFAULT: "hsl(var(--sidebar-background))",
  foreground: "hsl(var(--sidebar-foreground))",
  primary: "hsl(var(--sidebar-primary))",
  "primary-foreground": "hsl(var(--sidebar-primary-foreground))",
  accent: "hsl(var(--sidebar-accent))",
  "accent-foreground": "hsl(var(--sidebar-accent-foreground))",
  border: "hsl(var(--sidebar-border))",
  ring: "hsl(var(--sidebar-ring))",
  input: "hsl(var(--sidebar-input))",
},
// ...

Source code

Click here to see the source code for this component on GitHub. Feel free to copy it and adjust it for your own use.

Usage

You should always ensure that you have all parts of the Sidebar components wrapped in a UiSidebarProvider component. This is to ensure that the sidebar can be toggled on and off.

<template>
  <UiSidebarProvider>
    <!-- Other Sidebar stuff -->
  </UiSidebarProvider>
</template>

First Sidebar

Let's start with the most basic sidebar. A collapsible sidebar with a menu.

The code. Take note of the UiSidebarTrigger component. This is what toggles the sidebar.

Also, the UiSidebarInset component! When I just started using this component, I was confused as to where the page content should go.

<template>
  <UiSidebarProvider>
    <UiSidebar>
      <UiSidebarContent>
        <UiSidebarGroup>
          <UiSidebarGroupLabel label="Application" />
          <UiSidebarGroupContent>
            <UiSidebarMenu>
              <UiSidebarMenuItem v-for="item in items" :key="item.title">
                <UiSidebarMenuButton as-child>
                  <a :href="item.url">
                    <Icon :name="item.icon" />
                    <span>{{ item.title }}</span>
                  </a>
                </UiSidebarMenuButton>
              </UiSidebarMenuItem>
            </UiSidebarMenu>
          </UiSidebarGroupContent>
        </UiSidebarGroup>
      </UiSidebarContent>
    </UiSidebar>
    <UiSidebarInset>
      <UiNavbar sticky>
        <UiContainer class="flex h-12 items-center">
          <UiSidebarTrigger />
        </UiContainer>
      </UiNavbar>
    </UiSidebarInset>
  </UiSidebarProvider>
</template>

<script lang="ts" setup>
  // Menu items.
  const items = [
    { title: "Home", url: "#", icon: "lucide:home" },
    { title: "Inbox", url: "#", icon: "lucide:inbox" },
    { title: "Calendar", url: "#", icon: "lucide:calendar" },
    { title: "Search", url: "#", icon: "lucide:search" },
    { title: "Settings", url: "#", icon: "lucide:settings" },
  ];
</script>

SidebarHeader

Use the UiSidebarHeader component to add a sticky header to the sidebar.

The following example adds a <UiDropdownMenu> to the UiSidebarHeader.

SidebarFooter

Use the UiSidebarFooter component to add a sticky footer to the sidebar.

The following example adds a <UiDropdownMenu> to the UiSidebarFooter.

Collapsible SidebarGroup

To make a UiSidebarGroup collapsible, wrap it in a UiCollapsible.

We wrap the UiCollapsibleTrigger in a UiSidebarGroupLabel to render a button.

SidebarGroupAction

Use the UiSidebarGroupAction component to add an action button to the UiSidebarGroup.

SidebarMenuAction

The UiSidebarMenuAction component is used to render a menu action within a UiSidebarMenuItem.

This button works independently of the UiSidebarMenuButton i.e you can have the <UiSidebarMenuButton /> as a clickable link and the <UiSidebarMenuAction /> as a button.

SidebarMenuSub

The UiSidebarMenuSub component is used to render a submenu within a UiSidebarMenu.

Use <UiSidebarMenuSubItem /> and <UiSidebarMenuSubButton /> to render a submenu item.

Collapsible SidebarMenu

To make a UiSidebarMenu component collapsible, wrap it and the UiSidebarMenuSub components in a UiCollapsible.

SidebarMenuBadge

The UiSidebarMenuBadge component is used to render a badge within a UiSidebarMenuItem.

SidebarRail

The UiSidebarRail component is used to render a rail within a UiSidebar. This rail can be used to toggle the sidebar.

Controlled Sidebar

Use the v-model:open directive to control the visibility of the sidebar.

This should be added to the UiSidebarProvider component.

You can even model this to local storage with the help of useStorage from VueUse.

You can even use Pinia to store the state of the sidebar & make it global.