Skip to main content
The LDashboardContainer component provides the foundational layout structure for dashboard pages. It wraps Nuxt UI’s UDashboardGroup and UDashboardPanel with sensible defaults and slot organization.

Props

Inherits all props from Nuxt UI’s DashboardGroupProps with the following additions and defaults:
id
string
default:"home"
Unique identifier for the dashboard panel
as
string
default:"div"
HTML element to render the container as
unit
string
default:"rem"
Unit for layout measurements
storage
string
default:"cookie"
Storage method for layout preferences
storageKey
string
default:"dashboard"
Key for storing layout state
persistent
boolean
default:"true"
Whether layout state should persist across sessions

Slots

sidebar
Content for the sidebar area, typically used for navigation (e.g., LSidebar component)
header
Content for the header section of the main dashboard panel (e.g., LNavbar component)
body
Main content area of the dashboard panel

Usage

Basic Layout

<template>
  <LDashboardContainer>
    <template #sidebar>
      <LSidebar :links-body="navigationLinks" />
    </template>
    
    <template #header>
      <LNavbar :menu-items="menuItems" />
    </template>
    
    <template #body>
      <div class="p-6">
        <h1>Dashboard Content</h1>
      </div>
    </template>
  </LDashboardContainer>
</template>

Complete Dashboard Example

<template>
  <LDashboardContainer id="main-dashboard">
    <template #sidebar>
      <LSidebar
        logo-default-src="/logo.svg"
        logo-mini-src="/logo-mini.svg"
        :links-body="sidebarLinks"
        :links-footer="footerLinks"
      />
    </template>
    
    <template #header>
      <LNavbar
        search-placeholder="Search..."
        :links="navLinks"
        menu-user-name="John Doe"
        menu-user-email="[email protected]"
        :menu-items="userMenuItems"
      />
    </template>
    
    <template #body>
      <NuxtPage />
    </template>
  </LDashboardContainer>
</template>

<script setup>
const sidebarLinks = [
  [
    { 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' }
  ]
]

const navLinks = [
  { label: 'Overview', to: '/overview' },
  { label: 'Analytics', to: '/analytics' }
]

const userMenuItems = [
  [
    { label: 'Profile', icon: 'i-lucide-user', onSelect: () => navigateTo('/profile') },
    { label: 'Settings', icon: 'i-lucide-settings', onSelect: () => navigateTo('/settings') }
  ],
  [
    { label: 'Logout', icon: 'i-lucide-log-out', onSelect: handleLogout }
  ]
]

const footerLinks = [
  [
    { label: 'Help', icon: 'i-lucide-help-circle', to: '/help' }
  ]
]
</script>

Custom Panel ID

<template>
  <LDashboardContainer id="settings-panel">
    <template #sidebar>
      <LSidebar :links-body="settingsLinks" />
    </template>
    
    <template #header>
      <DCardHeader title="Settings" />
    </template>
    
    <template #body>
      <div class="p-6">
        <p>Settings content</p>
      </div>
    </template>
  </LDashboardContainer>
</template>

Without Sidebar

<template>
  <LDashboardContainer>
    <template #header>
      <LNavbar has-search />
    </template>
    
    <template #body>
      <div class="max-w-7xl mx-auto p-6">
        <h1>Full Width Content</h1>
      </div>
    </template>
  </LDashboardContainer>
</template>

Multi-Page Dashboard

<!-- layouts/dashboard.vue -->
<template>
  <LDashboardContainer>
    <template #sidebar>
      <LSidebar
        :links-body="sidebarLinks"
        v-model:is-open="sidebarOpen"
      />
    </template>
    
    <template #header>
      <LNavbar
        v-model:search-term="searchTerm"
        :menu-user-name="user.name"
        :menu-items="menuItems"
      />
    </template>
    
    <template #body>
      <slot />
    </template>
  </LDashboardContainer>
</template>

<script setup>
const sidebarOpen = ref(true)
const searchTerm = ref('')
const user = useUser()

const sidebarLinks = [
  [
    { label: 'Home', icon: 'i-lucide-home', to: '/' },
    { label: 'Dashboard', icon: 'i-lucide-layout-dashboard', to: '/dashboard' }
  ]
]

const menuItems = [
  [
    { label: 'Profile', to: '/profile' },
    { label: 'Logout', onSelect: () => logout() }
  ]
]
</script>

Custom Storage Configuration

<template>
  <LDashboardContainer
    storage="localStorage"
    storage-key="my-dashboard-layout"
    :persistent="false"
  >
    <!-- slots -->
  </LDashboardContainer>
</template>

With Custom Wrapper Element

<template>
  <LDashboardContainer as="main">
    <template #sidebar>
      <LSidebar :links-body="links" />
    </template>
    
    <template #header>
      <LNavbar />
    </template>
    
    <template #body>
      <article>
        <h1>Content</h1>
      </article>
    </template>
  </LDashboardContainer>
</template>

Layout Structure

The component creates this structure:
UDashboardGroup (container)
├── Sidebar slot → typically LSidebar
└── UDashboardPanel
    ├── Header slot → typically LNavbar or DCardHeader
    └── Body slot → main page content

State Persistence

With persistent: true (default):
  • Sidebar collapsed/expanded state is saved
  • Layout preferences are restored on page reload
  • Storage method configurable via storage prop
  • Storage key customizable via storageKey prop

Responsive Behavior

Built on Nuxt UI’s responsive dashboard:
  • Sidebar auto-collapses on mobile
  • Touch-friendly interactions
  • Smooth transitions
  • Adjustable panel widths

Type Definitions

export type Props = DashboardGroupProps & {
  id?: string
}
Source: /home/daytona/workspace/source/app/components/l/l-dashboard-container.vue:36

Build docs developers (and LLMs) love