Layouts
A responsive CSS Grid layout system with sidebar, header, themes, and collapsible navigation.
Interactive Demo
Select a variant, theme, and accent color. The preview and code update in real-time.
<neura::layout
variant="with-sidebar-header"
:collapsable="true"
>
<neura::layout.header>
<x-slot:brand>
<neura::brand href="/" name="My App" />
</x-slot:brand>
<x-slot:actions>
<neura::theme-switcher />
</x-slot:actions>
</neura::layout.header>
<neura::sidebar>
<neura::navlist>
<neura::navlist.item href="/dashboard" icon="squares-2x2" label="Dashboard" size="sm" />
<neura::navlist.item href="/users" icon="users" label="Users" size="sm" />
<neura::navlist.item href="/docs" icon="document-text" label="Documents" size="sm" />
<neura::navlist.item href="/settings" icon="cog-6-tooth" label="Settings" size="sm" />
</neura::navlist>
</neura::sidebar>
<neura::layout.main>
Page content
</neura::layout.main>
</neura::layout>
Quick Start
Every layout needs at least two children: a
neura::sidebar and a neura::layout.main. The simplest layout uses the default variant (with-sidebar-only):
<neura::layout>
<neura::sidebar>
<x-slot name="brand">
<neura::brand href="/" name="My App" />
</x-slot>
<neura::navlist>
<neura::navlist.item href="/dashboard" icon="home">Dashboard</neura::navlist.item>
<neura::navlist.item href="/users" icon="users">Users</neura::navlist.item>
</neura::navlist>
</neura::sidebar>
<neura::layout.main>
Your page content
</neura::layout.main>
</neura::layout>
Props Reference
neura::layout
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | string | with-sidebar-only | Layout structure. See Variants. |
| theme | string | default | Visual style for sidebar/main. See Themes. |
| accentColor | string|null | null | Accent hue for accent theme: blue, indigo, purple, rose, red, orange, green, teal, cyan. |
| collapsable | bool | false | Enable sidebar collapse. State is persisted in localStorage. |
neura::layout.header
Available with
with-sidebar-header and without-sidebar variants. Supports brand and actions named slots.
| Prop | Type | Default | Description |
|---|---|---|---|
| sticky | bool | true | Stick the header to the top on scroll. |
| size | string | full | Inner container max-width: xs, sm, md, lg, xl, 2xl … 9xl, full. |
| centered | bool | true | Center the inner container horizontally. |
| withSidebarToggle | bool | true | Show mobile sidebar toggle. Set to false with without-sidebar. |
| direction | string | horizontal | Content direction: horizontal or vertical. |
Variants
The
variant prop controls the structural layout — which regions (header, sidebar, main) are present and how they are arranged.
| Variant | Header | Sidebar | Use case | Legacy alias |
|---|---|---|---|---|
| with-sidebar-only | — | Yes | Dashboard, admin panel | sidebar |
| with-sidebar-header | Yes | Yes | Full app shell with top bar | full |
| without-sidebar | Yes | — | Landing page, simple app | — |
with-sidebar-only
Sidebar + main only. Brand goes inside the sidebar's
brand slot. This is the default variant.
<neura::layout variant="with-sidebar-only">
<neura::sidebar>...</neura::sidebar>
<neura::layout.main>...</neura::layout.main>
</neura::layout>
with-sidebar-header
Header spans full width. Sidebar sits below the header. Use the header's
brand and actions slots for branding, search, and action buttons.
<neura::layout variant="with-sidebar-header" :collapsable="true">
<neura::layout.header>
<x-slot:brand><neura::brand href="/" name="App" /></x-slot:brand>
<x-slot:actions><neura::theme-switcher /></x-slot:actions>
</neura::layout.header>
<neura::sidebar>...</neura::sidebar>
<neura::layout.main>...</neura::layout.main>
</neura::layout>
without-sidebar
Header + main only. Set
:withSidebarToggle="false" on the header to hide the mobile menu button.
<neura::layout variant="without-sidebar">
<neura::layout.header :withSidebarToggle="false">
<x-slot:brand><neura::brand href="/" name="App" /></x-slot:brand>
</neura::layout.header>
<neura::layout.main>...</neura::layout.main>
</neura::layout>
Themes
Themes control the visual appearance (colors, contrast) of the sidebar and main area by overriding CSS design tokens. They work independently of variants.
| Theme | Sidebar | Main | Inspiration |
|---|---|---|---|
| default | Same as global tokens | Same as global tokens | — |
| contrast | Dark background, light text | Light background | GitHub, Notion |
| muted | Tinted grey, dark text | Slightly off-white | Figma, Slack |
| accent | Dark with color tint | Default | Linear, Twenty CRM |
Accent with custom color
When using the
accent theme, pass accentColor to tint the sidebar. Defaults to blue. Available colors: blue, indigo, purple, rose, red, orange, green, teal, cyan.
<!-- Blue accent (default) -->
<neura::layout theme="accent">...</neura::layout>
<!-- Purple accent -->
<neura::layout theme="accent" accentColor="purple">...</neura::layout>
<!-- Teal accent -->
<neura::layout theme="accent" accentColor="teal">...</neura::layout>
Sub-components
neura::sidebar
The navigation sidebar. Use with
with-sidebar-only or with-sidebar-header. Supports a brand slot, scrollable content, and collapsible behavior.
<neura::sidebar>
<x-slot name="brand">
<neura::brand href="/" name="App" />
</x-slot>
<neura::navlist>
<neura::navlist.group label="Navigation">
<neura::navlist.item href="/dashboard" icon="home">Dashboard</neura::navlist.item>
<neura::navlist.item href="/users" icon="users">Users</neura::navlist.item>
<neura::navlist.item href="/settings" icon="cog">Settings</neura::navlist.item>
</neura::navlist.group>
</neura::navlist>
</neura::sidebar>
neura::layout.header
Top header bar. Three zones:
brand (left), default slot (center), actions (right).
<neura::layout.header size="xl">
<x-slot:brand>
<neura::brand href="/" name="My App" />
</x-slot:brand>
<!-- Center: search, breadcrumb, etc. -->
<x-slot:actions>
<neura::theme-switcher />
<neura::button variant="outline" size="sm">Upgrade</neura::button>
</x-slot:actions>
</neura::layout.header>
neura::layout.main
The main content area. Scrolls independently. You can pass classes to customize its background.
<neura::layout.main>
Your page content
</neura::layout.main>
<!-- With a different background -->
<neura::layout.main class="bg-surface-inset">
Content on a recessed background
</neura::layout.main>
Collapsible Sidebar
Set
:collapsable="true" to enable collapse. The state is persisted in localStorage across page reloads.
| Breakpoint | Behavior |
|---|---|
| < 768px | Sidebar hidden; opens as an overlay with backdrop. Toggle via neura::sidebar.toggle. |
| 768px – 1023px | Sidebar visible; can be collapsed to icon-only width (4rem). |
| ≥ 1024px | Full sidebar. Collapse state persisted in localStorage. |
<neura::layout :collapsable="true">
<neura::sidebar>
<!-- Sidebar auto-collapses to icons on toggle -->
</neura::sidebar>
<neura::layout.main>...</neura::layout.main>
</neura::layout>
CSS Variables
Override these on the layout root to customize dimensions or the accent hue.
| Variable | Default | Description |
|---|---|---|
| --sidebar-width | 16rem | Sidebar width (4rem when collapsed) |
| --header-height | 4rem | Header height |
| --nk-accent-hue | 260 | Oklch hue for accent theme sidebar (0–360) |
Complete Example
A full app shell with accent theme, collapsible sidebar, header with brand and actions:
<neura::layout
variant="with-sidebar-header"
theme="accent"
accentColor="indigo"
:collapsable="true"
>
<neura::layout.header>
<x-slot:brand>
<neura::brand href="/" name="My Application" />
</x-slot:brand>
<x-slot:actions>
<neura::theme-switcher />
<neura::button variant="outline" size="sm">Feedback</neura::button>
</x-slot:actions>
</neura::layout.header>
<neura::sidebar>
<neura::navlist>
<neura::navlist.group label="Navigation">
<neura::navlist.item href="/dashboard" icon="home">Dashboard</neura::navlist.item>
<neura::navlist.item href="/projects" icon="folder">Projects</neura::navlist.item>
<neura::navlist.item href="/users" icon="users">Users</neura::navlist.item>
</neura::navlist.group>
<neura::navlist.group label="Settings">
<neura::navlist.item href="/settings" icon="cog">General</neura::navlist.item>
<neura::navlist.item href="/billing" icon="credit-card">Billing</neura::navlist.item>
</neura::navlist.group>
</neura::navlist>
</neura::sidebar>
<neura::layout.main>
<div class="p-6 space-y-6">
<neura::heading level="h2">Dashboard</neura::heading>
<neura::text>Welcome back!</neura::text>
</div>
</neura::layout.main>
</neura::layout>