The LSidebar component provides a full-featured sidebar navigation with collapsible and resizable functionality, logo display, hierarchical navigation links, and customizable footer.
Props
logoDefaultSrc
string
default:"/media/img/ui-logo-placeholder.svg"
Logo image source URL when the sidebar is expanded
Logo image source URL when the sidebar is collapsed. If not provided, uses logoDefaultSrc.
Navigation path when clicking on the logo
linksBody
NavigationMenuItem[][]
default:"[]"
Navigation links displayed in the main body of the sidebar. Grouped in arrays.
linksBodyBottom
NavigationMenuItem[][]
default:"[]"
Navigation links displayed at the bottom of the body section (before footer)
Navigation links displayed in the footer section
Default width of the sidebar in the specified unit
Minimum width the sidebar can be resized to
Maximum width the sidebar can be resized to
Model
Controls whether the sidebar is open (on mobile) or collapsed state
Slots
Custom header content. Receives { collapsed } as slot props. Replaces default logo.
Custom body content. Receives { collapsed } as slot props. Replaces default navigation.
Custom footer content. Receives { collapsed } as slot props. Replaces default footer links.
Usage
<template>
<LSidebar :links-body="navigationLinks" />
</template>
<script setup>
const navigationLinks = [
[
{ label: 'Dashboard', icon: 'i-lucide-layout-dashboard', to: '/dashboard' },
{ label: 'Projects', icon: 'i-lucide-folder', to: '/projects' },
{ label: 'Tasks', icon: 'i-lucide-check-square', to: '/tasks' }
]
]
</script>
<template>
<LSidebar
logo-default-src="/logo-full.svg"
logo-mini-src="/logo-icon.svg"
logo-link="/home"
:links-body="mainLinks"
:links-body-bottom="utilityLinks"
:links-footer="footerLinks"
v-model:is-open="sidebarOpen"
/>
</template>
<script setup>
const sidebarOpen = ref(true)
const mainLinks = [
[
{ label: 'Dashboard', icon: 'i-lucide-home', to: '/' },
{ label: 'Analytics', icon: 'i-lucide-bar-chart', to: '/analytics' }
],
[
{ label: 'Projects', icon: 'i-lucide-folder', to: '/projects' },
{ label: 'Team', icon: 'i-lucide-users', to: '/team' }
]
]
const utilityLinks = [
[
{ label: 'Settings', icon: 'i-lucide-settings', to: '/settings' }
]
]
const footerLinks = [
[
{ label: 'Help Center', icon: 'i-lucide-help-circle', to: '/help' },
{ label: 'Feedback', icon: 'i-lucide-message-square', to: '/feedback' }
]
]
</script>
Nested Navigation
<template>
<LSidebar :links-body="nestedLinks" />
</template>
<script setup>
const nestedLinks = [
[
{
label: 'Products',
icon: 'i-lucide-package',
children: [
{ label: 'All Products', to: '/products' },
{ label: 'Categories', to: '/products/categories' },
{ label: 'Inventory', to: '/products/inventory' }
]
},
{
label: 'Orders',
icon: 'i-lucide-shopping-cart',
children: [
{ label: 'All Orders', to: '/orders' },
{ label: 'Pending', to: '/orders/pending' },
{ label: 'Completed', to: '/orders/completed' }
]
}
]
]
</script>
<template>
<LSidebar :links-body="links">
<template #header="{ collapsed }">
<div class="flex flex-col items-center p-4">
<img :src="collapsed ? '/icon.svg' : '/logo.svg'" />
<span v-if="!collapsed" class="text-sm mt-2">v2.0.0</span>
</div>
</template>
</LSidebar>
</template>
Custom Body with Dynamic Content
<template>
<LSidebar>
<template #body="{ collapsed }">
<div class="space-y-4 p-4">
<div v-if="!collapsed" class="text-sm text-muted mb-2">
Recent Projects
</div>
<UNavigationMenu
:collapsed="collapsed"
:items="recentProjects"
orientation="vertical"
/>
</div>
</template>
</LSidebar>
</template>
<script setup>
const recentProjects = computed(() => [
[
{ label: 'Project Alpha', to: '/projects/alpha', icon: 'i-lucide-folder' },
{ label: 'Project Beta', to: '/projects/beta', icon: 'i-lucide-folder' }
]
])
</script>
<template>
<LSidebar :links-body="links">
<template #footer="{ collapsed }">
<div class="p-4 border-t">
<div v-if="!collapsed" class="flex items-center gap-3">
<UAvatar src="/user.jpg" size="sm" />
<div>
<p class="font-medium">John Doe</p>
<p class="text-xs text-muted">Premium User</p>
</div>
</div>
<UAvatar v-else src="/user.jpg" size="sm" />
</div>
</template>
</LSidebar>
</template>
Controlled Collapsed State
<template>
<div>
<LSidebar
v-model:is-open="sidebarOpen"
:links-body="links"
/>
<button @click="sidebarOpen = !sidebarOpen">
Toggle Sidebar
</button>
</div>
</template>
<script setup>
const sidebarOpen = ref(true)
</script>
Custom Size Configuration
<template>
<LSidebar
:links-body="links"
:default-size="18"
:min-size="12"
:max-size="25"
/>
</template>
Multi-section Navigation
<template>
<LSidebar
:links-body="primaryLinks"
:links-body-bottom="secondaryLinks"
:links-footer="footerLinks"
/>
</template>
<script setup>
const primaryLinks = [
[
{ label: 'Overview', icon: 'i-lucide-layout-dashboard', to: '/' }
],
[
{ label: 'Content', icon: 'i-lucide-file-text', to: '/content' },
{ label: 'Media', icon: 'i-lucide-image', to: '/media' },
{ label: 'Users', icon: 'i-lucide-users', to: '/users' }
]
]
const secondaryLinks = [
[
{ label: 'Settings', icon: 'i-lucide-settings', to: '/settings' },
{ label: 'Integrations', icon: 'i-lucide-plug', to: '/integrations' }
]
]
const footerLinks = [
[
{ label: 'Support', icon: 'i-lucide-life-buoy', to: '/support' },
{ label: 'Documentation', icon: 'i-lucide-book', to: '/docs' }
]
]
</script>
Features
Collapsible
- Click the collapse button to toggle between expanded and collapsed states
- Collapsed state shows only icons with tooltips
- Logo switches between full and mini versions
Resizable
- Drag the sidebar edge to resize
- Constrained by
minSize and maxSize props
- Size persists across sessions
Tooltips
- Automatically shows tooltips for navigation items when collapsed
- Helps users identify menu items by icon alone
Popover Navigation
- Nested menu items open in popovers when sidebar is collapsed
- Maintains full navigation capabilities in compact mode
Layout Structure
UDashboardSidebar
├── Header (height: 120px)
│ └── Logo (clickable, centered)
├── Body (scrollable)
│ ├── Collapse Button (positioned absolute)
│ ├── Primary Navigation (linksBody)
│ └── Bottom Navigation (linksBodyBottom)
└── Footer (with border-t)
└── Footer Links (linksFooter)
Styling
Default UI configuration:
:ui="{
header: 'h-[120px]',
footer: 'lg:border-t lg:border-default'
}"
- Background:
bg-elevated/25 with transition
- Collapse Button: Positioned at top-right with primary solid color
- Navigation: Vertical orientation with
space-y-2 gap
UNavigationMenu(
:collapsed="collapsed"
:items="linksBody"
orientation="vertical"
tooltip
popover
:ui="{
list: 'space-y-2',
childList: 'space-y-2'
}"
)
Source: /home/daytona/workspace/source/app/components/l/l-sidebar.vue:78