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

Install the component

To get started, you should add the component to your project.

npx ui-thing@latest add sidebar

Update the Tailwind CSS file

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%;
  }
}

Update the Tailwind Config file

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.

External View

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.

External View

SidebarFooter

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

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

External View

Collapsible SidebarGroup

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

External View

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

SidebarGroupAction

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

External View

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.

External View

SidebarMenuSub

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

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

External View

Collapsible SidebarMenu

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

External View

SidebarMenuBadge

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

External View

SidebarRail

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

External View

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.

External View