Blocks

Layout

Dashboard shell with optional nav, left, and right rails, toolbar, main column, and footer.

Usage

Use MeLayout as the root layout: fill only the slots you need (header, nav, left and optional right rails, toolbar, analytics, main content, footer). Below lg, rails open as slideovers unless you pass inlineSidebarsOnMobile.

Loading preview...
<template>
  <div class="flex h-[28rem] w-full max-w-full flex-col gap-2 text-sm">
    <fieldset class="shrink-0 rounded-md border border-default bg-muted/30 p-3">
      <legend class="px-1 text-xs font-medium text-muted">Show slots</legend>
      <div class="mt-1 flex flex-wrap gap-x-4 gap-y-2">
        <label class="inline-flex cursor-pointer items-center gap-2">
          <input v-model="showHeader" type="checkbox" class="rounded border-default">
          Header
        </label>
        <label class="inline-flex cursor-pointer items-center gap-2">
          <input v-model="showNav" type="checkbox" class="rounded border-default">
          Nav
        </label>
        <label class="inline-flex cursor-pointer items-center gap-2">
          <input v-model="showLeft" type="checkbox" class="rounded border-default">
          Left
        </label>
        <label class="inline-flex cursor-pointer items-center gap-2">
          <input v-model="showRight" type="checkbox" class="rounded border-default">
          Right
        </label>
        <label class="inline-flex cursor-pointer items-center gap-2">
          <input v-model="showToolbar" type="checkbox" class="rounded border-default">
          Toolbar
        </label>
        <label class="inline-flex cursor-pointer items-center gap-2">
          <input v-model="showAnalytics" type="checkbox" class="rounded border-default">
          Analytics
        </label>
        <label class="inline-flex cursor-pointer items-center gap-2">
          <input v-model="showFooter" type="checkbox" class="rounded border-default">
          Footer
        </label>
      </div>
    </fieldset>

    <div class="min-h-0 flex-1 overflow-hidden rounded-md border border-default">
      <MeLayout class="!h-full min-h-0 w-full">
        <template v-if="showHeader" #header>
          <div class="flex h-12 w-full shrink-0 items-center border-b border-default bg-default px-4 font-medium">
            My App
          </div>
        </template>

        <template v-if="showNav" #nav-area>
          <div class="flex h-full flex-col items-center justify-center gap-2 p-2 text-xs text-muted">
            Nav
          </div>
        </template>

        <template v-if="showLeft" #left-area>
          <aside class="p-3">Left</aside>
        </template>

        <template v-if="showToolbar" #toolbar>
          <div class="px-2 py-1.5 text-muted">Toolbar</div>
        </template>

        <template v-if="showAnalytics" #analytics>
          <div class="p-4">Analytics</div>
        </template>

        <template #default>
          <div class="p-4">Main content</div>
        </template>

        <template v-if="showRight" #right-area>
          <aside class="p-3">Right</aside>
        </template>

        <template v-if="showFooter" #footer>
          <div class="px-4 py-2 text-xs text-muted">Footer</div>
        </template>
      </MeLayout>
    </div>
  </div>
</template>

<script setup>
const showHeader = ref(true)
const showNav = ref(false)
const showLeft = ref(true)
const showRight = ref(false)
const showAnalytics = ref(false)
const showToolbar = ref(true)
const showFooter = ref(false)
</script>

Rail sizing

Nav rail width is fixed at 5.5rem. Set unit and optional leftArea / rightArea for the resizable sidebars. The default unit is px; use unit="%" when your numbers are percentages (as in the example).

App
Content
<template>
  <MeLayout
    unit="%"
    :left-area="{
      minSize: 10,
      defaultSize: 18,
      maxSize: 28,
      resizable: true,
      collapsible: true
    }"
    :right-area="{
      minSize: 8,
      defaultSize: 12,
      maxSize: 20,
      resizable: false,
      collapsible: false
    }"
  >
    <template #header><div class="flex h-12 w-full items-center border-b border-default px-4 text-sm font-medium">App</div></template>
    <template #nav-area><div class="flex h-full items-center justify-center p-2 text-xs text-muted">Nav</div></template>
    <template #left-area><div class="p-3 text-sm">Left</div></template>
    <template #default><div class="p-4 text-sm">Content</div></template>
    <template #right-area><div class="p-3 text-sm">Right</div></template>
  </MeLayout>
</template>

API

Props

PropDefaultType
unit'px''%' | 'px' | 'rem'
Unit for left and right sidebar sizes.
inlineSidebarsOnMobile[]LayoutInlineSidebarKey[]
Rails that stay in the row under lg instead of slideover.
storage'cookie''cookie' | 'local'
Where sizes are stored.
storageKey'layout'string
Storage key for this layout group.
leftArea{ resizable: true, collapsible: true }LayoutLeftAreaConfig
minSize, defaultSize, maxSize, resizable, collapsible. Defaults: px 200/240/400, % 10/15/25, rem 12/15/25.
rightArea{ resizable: true, collapsible: true }LayoutRightAreaConfig
Same as leftArea. Defaults: px 260/358/640, % 8/12/20, rem 16/22.5/40.

Slots

SlotType
headervoid
nav-areaLayoutMobileSidebarSlotProps
nav-area-headerLayoutSidebarRailHeaderSlotProps
left-areaLayoutMobileSidebarSlotProps
left-area-headerLayoutSidebarRailHeaderSlotProps
toolbarLayoutMobileToolbarSlotProps
analyticsvoid
defaultvoid
right-areaLayoutMobileSidebarSlotProps
right-area-headerLayoutSidebarRailHeaderSlotProps
footervoid

Rail slot bodies use horizontal clipping; wrap wide content in overflow-x-auto min-w-0.