UIPackage
Menu

Framework

Change language

Boilerplate repo

Sidebar

sidebarui

Full-height app sidebar — collapsible to icons, with grouping, sub-grouping, and integrated search. The navigation surface for product apps with many sections.

Also available for React ->

Installation

$npx shadcn-vue@latest add https://uipkge.dev/r/vue/sidebar.json
Named registry:npx shadcn-vue@latest add @uipkge/sidebarInstalls to:app/components/ui/sidebar/

Examples

Loading interactive previews…

Props

NameType / ValuesDefaultRequired
variant
'default''outline'
defaultoptional
size
'default''sm''lg'
defaultoptional

Used by

Files installed (27)

  • app/components/ui/sidebar/Sidebar.vue3.9 kB
    <script setup lang="ts">
    import type { SidebarProps } from '.'
    import { cn } from '@/lib/utils'
    import { Sheet, SheetContent } from '@/components/ui/sheet'
    import SheetDescription from '@/components/ui/sheet/SheetDescription.vue'
    import SheetHeader from '@/components/ui/sheet/SheetHeader.vue'
    import SheetTitle from '@/components/ui/sheet/SheetTitle.vue'
    import { SIDEBAR_WIDTH_MOBILE, useSidebar } from './utils'
    
    defineOptions({
      inheritAttrs: false,
    })
    
    const props = withDefaults(defineProps<SidebarProps>(), {
      side: 'left',
      variant: 'sidebar',
      collapsible: 'offcanvas',
    })
    
    const { isMobile, state, openMobile, setOpenMobile } = useSidebar()
    </script>
    
    <template>
      <div
        v-if="collapsible === 'none'"
        data-uipkge
        data-slot="sidebar"
        :class="cn('bg-sidebar text-sidebar-foreground flex h-full w-(--sidebar-width) flex-col', props.class)"
        v-bind="$attrs"
      >
        <slot />
      </div>
    
      <Sheet v-else-if="isMobile" :open="openMobile" v-bind="$attrs" @update:open="setOpenMobile">
        <SheetContent
          data-sidebar="sidebar"
          data-uipkge
          data-slot="sidebar"
          data-mobile="true"
          :side="side"
          class="bg-sidebar text-sidebar-foreground w-(--sidebar-width) p-0 [&>button]:hidden"
          :style="{
            '--sidebar-width': SIDEBAR_WIDTH_MOBILE,
          }"
        >
          <SheetHeader class="sr-only">
            <SheetTitle>Sidebar</SheetTitle>
            <SheetDescription>Displays the mobile sidebar.</SheetDescription>
          </SheetHeader>
          <div class="flex h-full w-full flex-col">
            <slot />
          </div>
        </SheetContent>
      </Sheet>
    
      <div
        v-else
        class="group peer text-sidebar-foreground hidden md:block"
        data-uipkge
        data-slot="sidebar"
        :data-state="state"
        :data-collapsible="state === 'collapsed' ? collapsible : ''"
        :data-variant="variant"
        :data-side="side"
      >
        <!-- This is what handles the sidebar gap on desktop  -->
        <div
          :class="
            cn(
              'relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear',
              'group-data-[collapsible=offcanvas]:w-0',
              'group-data-[side=right]:rotate-180',
              variant === 'floating' || variant === 'inset'
                ? 'group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]'
                : 'group-data-[collapsible=icon]:w-(--sidebar-width-icon)',
            )
          "
        />
        <div
          :class="
            cn(
              'fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex',
              side === 'left'
                ? 'left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]'
                : 'right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]',
              // Adjust the padding for floating and inset variants (token-aligned with React/shadcn).
              variant === 'floating' || variant === 'inset'
                ? 'p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]'
                : 'group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l',
              props.class,
            )
          "
          v-bind="$attrs"
        >
          <div
            data-sidebar="sidebar"
            class="bg-sidebar group-data-[variant=floating]:border-sidebar-border flex h-full w-full flex-col group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:shadow-sm"
          >
            <slot />
          </div>
        </div>
      </div>
    </template>
    
    <style>
    /* Push any OverlayScroll thumb inside a sidebar 2.5rem in from the right
       edge so it clears SidebarRail's inside-zone. The CSS variable
       cascades to every descendant, so consumers wrapping their nav in
       OverlayScroll (a common pattern when nav items overflow viewport
       height) get this for free -- no per-call thumb-offset config. */
    [data-slot='sidebar'] {
      --ovs-thumb-right: 2.5rem;
    }
    </style>
    
  • app/components/ui/sidebar/SidebarContent.vue0.4 kB
  • app/components/ui/sidebar/SidebarFooter.vue0.3 kB
  • app/components/ui/sidebar/SidebarGroup.vue0.4 kB
  • app/components/ui/sidebar/SidebarGroupAction.vue0.9 kB
  • app/components/ui/sidebar/SidebarGroupContent.vue0.4 kB
  • app/components/ui/sidebar/SidebarGroupLabel.vue0.9 kB
  • app/components/ui/sidebar/SidebarHeader.vue0.3 kB
  • app/components/ui/sidebar/SidebarInput.vue0.7 kB
  • app/components/ui/sidebar/SidebarInset.vue0.9 kB
  • app/components/ui/sidebar/SidebarMenu.vue0.4 kB
  • app/components/ui/sidebar/SidebarMenuAction.vue1.4 kB
  • app/components/ui/sidebar/SidebarMenuBadge.vue0.9 kB
  • app/components/ui/sidebar/SidebarMenuButton.vue1.3 kB
  • app/components/ui/sidebar/SidebarMenuButtonChild.vue1.3 kB
  • app/components/ui/sidebar/SidebarMenuItem.vue0.4 kB
  • app/components/ui/sidebar/SidebarMenuSkeleton.vue0.8 kB
  • app/components/ui/sidebar/SidebarMenuSub.vue0.5 kB
  • app/components/ui/sidebar/SidebarMenuSubButton.vue1.4 kB
  • app/components/ui/sidebar/SidebarMenuSubItem.vue0.4 kB
  • app/components/ui/sidebar/SidebarProvider.vue3.2 kB
  • app/components/ui/sidebar/SidebarRail.vue1.4 kB
  • app/components/ui/sidebar/SidebarSeparator.vue0.4 kB
  • app/components/ui/sidebar/SidebarTrigger.vue0.7 kB
  • app/components/ui/sidebar/sidebar.variants.ts1.9 kB
  • app/components/ui/sidebar/index.ts2 kB
  • app/components/ui/sidebar/utils.ts0.7 kB

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