UIPackage

Sidebar 01

block sidebar
Edit on GitHub

Collapsible icon-rail app sidebar with brand block, two grouped nav sections, and a user dropdown footer. Pure template, no props -- edit Sidebar01.vue to change routes and NavUser.vue to wire your auth session. Pair with SidebarProvider + SidebarInset for the full admin shell.

Also available for React ->

Installation

$ npx shadcn-vue@latest add https://uipkge.dev/r/vue/sidebar-01.json

Or with the named registry: npx shadcn-vue@latest add @uipkge/sidebar-01

Examples

Files (2)

  • app/components/blocks/sidebar-01/Sidebar01.vue 4.1 kB
    <script setup lang="ts">
    // Edit this file to change brand, navigation, and the user dropdown.
    // Every menu item is spelled out below -- copy, remove, or rename rows directly.
    
    import { BarChart3, BookOpen, FileText, Files, History, LayoutDashboard, Table as TableIcon } from 'lucide-vue-next'
    import {
      Sidebar,
      SidebarContent,
      SidebarFooter,
      SidebarGroup,
      SidebarGroupContent,
      SidebarGroupLabel,
      SidebarHeader,
      SidebarMenu,
      SidebarMenuButton,
      SidebarMenuItem,
      SidebarRail,
    } from '@/components/ui/sidebar'
    import NavUser from './NavUser.vue'
    </script>
    
    <template>
      <Sidebar collapsible="icon">
        <SidebarHeader>
          <SidebarMenu>
            <SidebarMenuItem>
              <SidebarMenuButton size="lg" tooltip="uipkge" class="group-data-[collapsible=icon]:!justify-center">
                <div
                  class="bg-sidebar-primary text-sidebar-primary-foreground flex aspect-square size-8 shrink-0 items-center justify-center rounded-lg group-data-[collapsible=icon]:size-6"
                >
                  <svg
                    viewBox="0 0 24 24"
                    class="size-4 group-data-[collapsible=icon]:size-3.5"
                    fill="currentColor"
                    aria-hidden="true"
                  >
                    <rect x="2" y="2" width="9" height="9" rx="1.5" />
                    <rect x="13" y="2" width="9" height="9" rx="1.5" opacity="0.55" />
                    <rect x="2" y="13" width="9" height="9" rx="1.5" opacity="0.55" />
                    <rect x="13" y="13" width="9" height="9" rx="1.5" />
                  </svg>
                </div>
                <div class="grid flex-1 text-left text-sm leading-tight group-data-[collapsible=icon]:hidden">
                  <span class="font-display truncate font-bold">uipkge</span>
                  <span class="text-muted-foreground truncate text-xs">uipkge.dev</span>
                </div>
              </SidebarMenuButton>
            </SidebarMenuItem>
          </SidebarMenu>
        </SidebarHeader>
    
        <SidebarContent>
          <SidebarGroup>
            <SidebarGroupLabel>Workspace</SidebarGroupLabel>
            <SidebarGroupContent>
              <SidebarMenu>
                <SidebarMenuItem>
                  <!-- TODO: wrap in NuxtLink / RouterLink and bind :is-active to your route -->
                  <SidebarMenuButton is-active tooltip="Dashboard">
                    <LayoutDashboard class="size-4" />
                    <span>Dashboard</span>
                  </SidebarMenuButton>
                </SidebarMenuItem>
                <SidebarMenuItem>
                  <SidebarMenuButton tooltip="Data tables">
                    <TableIcon class="size-4" />
                    <span>Data tables</span>
                  </SidebarMenuButton>
                </SidebarMenuItem>
                <SidebarMenuItem>
                  <SidebarMenuButton tooltip="Forms">
                    <FileText class="size-4" />
                    <span>Forms</span>
                  </SidebarMenuButton>
                </SidebarMenuItem>
                <SidebarMenuItem>
                  <SidebarMenuButton tooltip="Charts">
                    <BarChart3 class="size-4" />
                    <span>Charts</span>
                  </SidebarMenuButton>
                </SidebarMenuItem>
                <SidebarMenuItem>
                  <SidebarMenuButton tooltip="Pages">
                    <Files class="size-4" />
                    <span>Pages</span>
                  </SidebarMenuButton>
                </SidebarMenuItem>
              </SidebarMenu>
            </SidebarGroupContent>
          </SidebarGroup>
    
          <SidebarGroup>
            <SidebarGroupLabel>Resources</SidebarGroupLabel>
            <SidebarGroupContent>
              <SidebarMenu>
                <SidebarMenuItem>
                  <SidebarMenuButton tooltip="Docs">
                    <BookOpen class="size-4" />
                    <span>Docs</span>
                  </SidebarMenuButton>
                </SidebarMenuItem>
                <SidebarMenuItem>
                  <SidebarMenuButton tooltip="Changelog">
                    <History class="size-4" />
                    <span>Changelog</span>
                  </SidebarMenuButton>
                </SidebarMenuItem>
              </SidebarMenu>
            </SidebarGroupContent>
          </SidebarGroup>
        </SidebarContent>
    
        <SidebarFooter>
          <NavUser />
        </SidebarFooter>
    
        <SidebarRail />
      </Sidebar>
    </template>
  • app/components/blocks/sidebar-01/NavUser.vue 4.4 kB
    <script setup lang="ts">
    // Edit this file to change the user dropdown content, avatar, and logout handler.
    // The user details are inlined below -- wire them to your auth session in place.
    
    import { BadgeCheck, ChevronsUpDown, LogOut, Monitor, Moon, Palette, Settings, Sun } from 'lucide-vue-next'
    import { useTheme } from '~/composables/useTheme'
    import { Avatar, AvatarFallback } from '@/components/ui/avatar'
    import {
      DropdownMenu,
      DropdownMenuContent,
      DropdownMenuGroup,
      DropdownMenuItem,
      DropdownMenuLabel,
      DropdownMenuRadioGroup,
      DropdownMenuRadioItem,
      DropdownMenuSeparator,
      DropdownMenuSub,
      DropdownMenuSubContent,
      DropdownMenuSubTrigger,
      DropdownMenuTrigger,
    } from '@/components/ui/dropdown-menu'
    import { SidebarMenu, SidebarMenuButton, SidebarMenuItem, useSidebar } from '@/components/ui/sidebar'
    
    const { isMobile } = useSidebar()
    const { theme, setTheme } = useTheme()
    
    // Replace these with your auth session.
    const user = {
      name: 'Test User',
      email: '[email protected]',
      initials: 'TU',
    }
    
    function handleLogout() {
      // TODO: call your /api/auth/logout endpoint, then redirect.
      console.warn('NavUser: wire handleLogout() to your auth backend')
    }
    </script>
    
    <template>
      <SidebarMenu>
        <SidebarMenuItem>
          <DropdownMenu>
            <DropdownMenuTrigger as-child>
              <SidebarMenuButton
                size="lg"
                class="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground group-data-[collapsible=icon]:!justify-center"
              >
                <Avatar class="h-8 w-8 shrink-0 rounded-lg group-data-[collapsible=icon]:size-6">
                  <AvatarFallback class="rounded-lg text-xs group-data-[collapsible=icon]:text-[10px]">{{
                    user.initials
                  }}</AvatarFallback>
                </Avatar>
                <div class="grid flex-1 text-left text-sm leading-tight group-data-[collapsible=icon]:hidden">
                  <span class="truncate font-medium">{{ user.name }}</span>
                  <span class="truncate text-xs">{{ user.email }}</span>
                </div>
                <ChevronsUpDown class="ml-auto size-4 group-data-[collapsible=icon]:hidden" />
              </SidebarMenuButton>
            </DropdownMenuTrigger>
            <DropdownMenuContent
              class="w-(--reka-dropdown-menu-trigger-width) min-w-56 rounded-lg"
              :side="isMobile ? 'bottom' : 'right'"
              align="end"
              :side-offset="4"
            >
              <DropdownMenuLabel class="p-0 font-normal">
                <div class="flex items-center gap-2 px-1 py-1.5 text-left text-sm">
                  <Avatar class="h-8 w-8 rounded-lg">
                    <AvatarFallback class="rounded-lg">{{ user.initials }}</AvatarFallback>
                  </Avatar>
                  <div class="grid flex-1 text-left text-sm leading-tight">
                    <span class="truncate font-semibold">{{ user.name }}</span>
                    <span class="truncate text-xs">{{ user.email }}</span>
                  </div>
                </div>
              </DropdownMenuLabel>
              <DropdownMenuSeparator />
              <DropdownMenuGroup>
                <DropdownMenuItem> <BadgeCheck class="size-4" /> Profile </DropdownMenuItem>
                <DropdownMenuItem> <Settings class="size-4" /> Settings </DropdownMenuItem>
              </DropdownMenuGroup>
              <DropdownMenuSeparator />
              <DropdownMenuSub>
                <DropdownMenuSubTrigger>
                  <Palette class="size-4" />
                  Theme
                  <span class="text-muted-foreground ml-auto text-xs capitalize">{{ theme }}</span>
                </DropdownMenuSubTrigger>
                <DropdownMenuSubContent class="min-w-36">
                  <DropdownMenuRadioGroup
                    :model-value="theme"
                    @update:model-value="(v) => setTheme(v as 'light' | 'dark' | 'system')"
                  >
                    <DropdownMenuRadioItem value="light"> <Sun class="size-4" /> Light </DropdownMenuRadioItem>
                    <DropdownMenuRadioItem value="dark"> <Moon class="size-4" /> Dark </DropdownMenuRadioItem>
                    <DropdownMenuRadioItem value="system"> <Monitor class="size-4" /> System </DropdownMenuRadioItem>
                  </DropdownMenuRadioGroup>
                </DropdownMenuSubContent>
              </DropdownMenuSub>
              <DropdownMenuSeparator />
              <DropdownMenuItem @click="handleLogout">
                <LogOut class="size-4" />
                Log out
              </DropdownMenuItem>
            </DropdownMenuContent>
          </DropdownMenu>
        </SidebarMenuItem>
      </SidebarMenu>
    </template>

Raw manifest: https://uipkge.dev/r/vue/sidebar-01.json