Files
mydot/agents/.agents/skills/nuxt-ui/references/layouts/dashboard.md
T
2026-09-27 11:51:31 +03:00

6.2 KiB

Dashboard Layout

Build admin interfaces with resizable sidebars, multi-panel layouts, and toolbars.

When to use

  • Admin panels, back-office UIs
  • Email clients, project management tools
  • Any app with a persistent sidebar and content panels
  • Combine with chat or editor layouts for specialized dashboards

Component tree

UApp
└── NuxtLayout (dashboard)
    └── UDashboardGroup
        ├── UDashboardSidebar
        │   ├── #header (logo, search button)
        │   ├── #default (navigation) — receives { collapsed } slot prop
        │   └── #footer (user menu)
        └── NuxtPage
            └── UDashboardPanel
                ├── #header → UDashboardNavbar + UDashboardToolbar
                ├── #body (scrollable content)
                └── #footer (optional)

Layout

<script setup lang="ts">
import type { NavigationMenuItem } from '@nuxt/ui'

const items = computed<NavigationMenuItem[]>(() => [{
  label: 'Home',
  icon: 'i-lucide-house',
  to: '/dashboard'
}, {
  label: 'Inbox',
  icon: 'i-lucide-inbox',
  to: '/dashboard/inbox'
}, {
  label: 'Users',
  icon: 'i-lucide-users',
  to: '/dashboard/users'
}, {
  label: 'Settings',
  icon: 'i-lucide-settings',
  to: '/dashboard/settings'
}])
</script>

<template>
  <UDashboardGroup>
    <UDashboardSidebar collapsible resizable>
      <template #header="{ collapsed }">
        <UDashboardSearchButton :collapsed="collapsed" />
      </template>

      <template #default="{ collapsed }">
        <UNavigationMenu
          :collapsed="collapsed"
          :items="items"
          orientation="vertical"
        />
      </template>

      <template #footer="{ collapsed }">
        <UButton
          :icon="collapsed ? 'i-lucide-log-out' : undefined"
          :label="collapsed ? undefined : 'Sign out'"
          color="neutral"
          variant="ghost"
          block
        />
      </template>
    </UDashboardSidebar>

    <slot />
  </UDashboardGroup>
</template>

Page

<script setup lang="ts">
definePageMeta({ layout: 'dashboard' })
</script>

<template>
  <UDashboardPanel>
    <template #header>
      <UDashboardNavbar title="Home">
        <template #leading>
          <UDashboardSidebarCollapse />
        </template>
        <template #right>
          <UButton icon="i-lucide-plus" label="New" />
        </template>
      </UDashboardNavbar>
    </template>

    <template #body>
      <!-- Page content -->
    </template>
  </UDashboardPanel>
</template>

Common mistakes

  • Forgetting definePageMeta({ layout: 'dashboard' }) — the page won't use the dashboard layout without it.
  • Putting content directly in UDashboardPanel without using #body slot — content won't scroll properly.
  • Not handling the collapsed slot prop — sidebar content should adapt when collapsed (hide labels, center icons).

Key components

DashboardGroup

Root wrapper. Manages sidebar state and persistence.

Prop Default Purpose
storage 'cookie' 'cookie', 'localStorage', false
storage-key 'dashboard' Storage key name

DashboardSidebar

Resizable, collapsible sidebar. Must be inside DashboardGroup.

Prop Default Purpose
resizable false Drag to resize
collapsible false Collapse when dragged to edge
side 'left' 'left' or 'right'
mode 'slideover' Mobile: 'modal', 'slideover', 'drawer'

All slots receive { collapsed, collapse } — collapsed is the boolean state, collapse(value) toggles it programmatically. Use v-model:collapsed and v-model:open (mobile) for state control.

DashboardPanel

Content panel with #header, #body (scrollable), #footer, and #default (raw, no scroll) slots.

DashboardNavbar / DashboardToolbar

Navbar: #leading, #left, #default, #right slots + title prop. Use UDashboardSidebarCollapse in #leading to toggle sidebar on mobile. Toolbar: same slots, sits below navbar for filters/actions.

UNavigationMenu in sidebar

Always pass :collapsed="collapsed" to UNavigationMenu inside a collapsible sidebar — it auto-hides labels and centers icons. Use NavigationMenuItem[][] (array of arrays) for separate groups (main nav + footer links).

Multi-panel (list-detail)

<script setup lang="ts">
definePageMeta({ layout: 'dashboard' })
</script>

<template>
  <UDashboardPanel id="inbox-list" resizable>
    <template #header>
      <UDashboardNavbar title="Inbox" />
    </template>
    <template #body>
      <!-- Email list -->
    </template>
  </UDashboardPanel>

  <UDashboardPanel id="inbox-detail" class="hidden lg:flex">
    <template #header>
      <UDashboardNavbar title="Message" />
    </template>
    <template #body>
      <!-- Email content -->
    </template>
  </UDashboardPanel>
</template>

With toolbar

<UDashboardPanel>
  <template #header>
    <UDashboardNavbar title="Users" />
    <UDashboardToolbar>
      <template #left>
        <UInput icon="i-lucide-search" placeholder="Search..." />
      </template>
      <template #right>
        <USelect :items="['All', 'Active', 'Inactive']" />
      </template>
    </UDashboardToolbar>
  </template>
</UDashboardPanel>
<template>
  <UDashboardGroup>
    <UDashboardSidebar>
      <template #header>
        <UDashboardSearchButton />
      </template>
    </UDashboardSidebar>

    <slot />

    <UDashboardSearch :groups="searchGroups" />
  </UDashboardGroup>
</template>

Right sidebar

<UDashboardGroup>
  <UDashboardSidebar collapsible resizable>
    <!-- Left sidebar -->
  </UDashboardSidebar>

  <slot />

  <UDashboardSidebar side="right" resizable>
    <!-- Right sidebar -->
  </UDashboardSidebar>
</UDashboardGroup>