App Shell
Full application shells — collapsible sidebars, org switchers, command search, breadcrumb headers and an inset content area.
Preview
@props([
'title' => 'Dashboard',
'subtitle' => 'Overview of your workspace',
'nav' => null,
'stats' => null,
])
@php
$nav ??= [
['label' => 'Overview', 'href' => '#', 'current' => true],
['label' => 'Customers', 'href' => '#', 'current' => false],
['label' => 'Billing', 'href' => '#', 'current' => false],
['label' => 'Settings', 'href' => '#', 'current' => false],
];
$stats ??= [
['label' => 'Revenue', 'value' => '$24.8K', 'delta' => '+12.5%', 'tone' => 'success'],
['label' => 'Active users', 'value' => '1,284', 'delta' => '+4.1%', 'tone' => 'default'],
['label' => 'Open tasks', 'value' => '32', 'delta' => '-8.0%', 'tone' => 'warning'],
];
@endphp
<x-ui.section data-surface="admin" space="none" class="min-h-svh" {{ $attributes }}>
<header class="border-b border-border bg-card">
<div class="mx-auto flex max-w-7xl items-center justify-between gap-4 px-4 py-4 sm:px-6 lg:px-8">
<div>
<h1 class="text-xl font-semibold">{{ __($title) }}</h1>
<p class="text-sm text-muted-foreground">{{ __($subtitle) }}</p>
</div>
<x-ui.button type="button" size="sm">{{ __('New project') }}</x-ui.button>
</div>
</header>
<div class="mx-auto grid max-w-7xl gap-6 px-4 py-6 sm:px-6 lg:grid-cols-[16rem_1fr] lg:px-8">
<aside class="rounded-lg border border-border bg-card p-6">
<nav class="grid gap-2 text-sm" aria-label="{{ __('Dashboard') }}">
@foreach ($nav as $item)
<a
href="{{ $item['href'] }}"
@class([
'rounded-md px-4 py-2 transition-colors',
'bg-muted font-medium text-foreground' => $item['current'] ?? false,
'text-muted-foreground hover:bg-muted hover:text-foreground' => ! ($item['current'] ?? false),
])
@if ($item['current'] ?? false) aria-current="page" @endif
>{{ __($item['label']) }}</a>
@endforeach
</nav>
</aside>
<main class="grid gap-6">
<div class="grid gap-4 md:grid-cols-3">
@foreach ($stats as $stat)
<x-ui.card>
<x-ui.card.header class="gap-2">
<x-ui.card.description>{{ __($stat['label']) }}</x-ui.card.description>
<div class="flex items-center justify-between">
<x-ui.card.title class="text-2xl">{{ $stat['value'] }}</x-ui.card.title>
<x-ui.badge :variant="$stat['tone'] ?? 'default'">{{ $stat['delta'] }}</x-ui.badge>
</div>
</x-ui.card.header>
</x-ui.card>
@endforeach
</div>
<x-ui.card>
<x-ui.card.header>
<x-ui.card.title>{{ __('Workspace activity') }}</x-ui.card.title>
<x-ui.card.description>{{ __('Recent operational events and review items.') }}</x-ui.card.description>
</x-ui.card.header>
<x-ui.card.content class="grid gap-4 text-sm">
<div class="flex items-center justify-between rounded-md border border-border p-4">
<span>{{ __('Payment provider synced') }}</span>
<span class="text-muted-foreground">{{ __('2 min ago') }}</span>
</div>
<div class="flex items-center justify-between rounded-md border border-border p-4">
<span>{{ __('New team invite accepted') }}</span>
<span class="text-muted-foreground">{{ __('18 min ago') }}</span>
</div>
</x-ui.card.content>
</x-ui.card>
</main>
</div>
</x-ui.section>
Installation
php artisan ui:add pages/app-shell-classic
Registry contract
Install confidence
php artisan ui:add pages/app-shell-classic
writes only the generated targets below. The CLI validates each file hash before writing and
prompts before replacing local changes unless --force is used.
- Version
- 1.1.4
- License
- open
- Stability
- stable
- Contract
- v1
- Foundation
- ≥ 1.0.0
| Type | Generated target |
|---|---|
| blade | resources/views/pages/app-shell-classic.blade.php |
Registry dependencies
Package dependencies
composer: jml/brok:^0.2
Use with AI
A brief for your coding agent: what the page is, the install command, how to render it, its props and the rules. Copy it, or open a prompt about this page in an assistant.
# Brok UI page: Dashboard Shell (`app-shell-classic`)
An admin dashboard shell with navigation, status cards, and a work area.
Brok UI is a Laravel Blade registry. `ui:add` copies this page into the app as plain Blade the app owns; it composes installed `<brok:*>` primitives and semantic design tokens.
## Install
```bash
php artisan ui:add pages/app-shell-classic
```
## Render it
```blade
<x-pages.app-shell-classic />
```
## Props
- `title` (string, default `Dashboard`) — Section heading.
- `subtitle` (string, default `Overview of your workspace`) — Supporting copy under the heading.
- `nav` (mixed|null, default `null`) — Sidebar navigation links with a current flag; null falls back to sample data.
- `stats` (mixed|null, default `null`) — Status cards ({label, value, delta, tone}); null falls back to sample data.
## Use when
- A simple admin dashboard shell with a top bar, a sidebar nav list, status cards and a work area.
- It composes primitives directly (badge, button, card, section) as a lightweight starting shell rather than a full sidebar app shell.
## Avoid when
- Needing a collapsible sidebar with a breadcrumb bar or command search; use app-shell-full-viewport through app-shell-workspace instead.
## Rules
- Render the installed page with `<x-pages.app-shell-classic />` and pass data through its props; edit the copied file only for structural changes.
- Keep the semantic design tokens (`bg-background`, `text-muted-foreground`); never swap in raw colour utilities.
- Keep the `data-slot` attributes and the logical (start/end) spacing so the markup still mirrors under `dir="rtl"`.
## Links
- Docs: https://brokui.dev/pages/app-shell-classic
- Registry JSON (files, props, contract): https://brokui.dev/r/open/pages/app-shell-classic.json
Working in Claude Code, Cursor or Codex? Give the agent the whole registry through the MCP server or the Brok UI skill.
Guidance
Use when
- A simple admin dashboard shell with a top bar, a sidebar nav list, status cards and a work area.
- It composes primitives directly (badge, button, card, section) as a lightweight starting shell rather than a full sidebar app shell.
Avoid when
- Needing a collapsible sidebar with a breadcrumb bar or command search; use app-shell-full-viewport through app-shell-workspace instead.
Anti-patterns
- Do not replace semantic props with conflicting utility classes.
- Do not remove labels, focus styles, or state attributes.
Usage
Render the page as a component, or wire it to a route. Pass data where useful:
<x-pages.app-shell-classic />
Built from blocks & primitives
This page composes installed <brok:*> primitives and semantic design
tokens only — it does not reimplement any primitive. Re-theme it (light, dark, admin, customer) by
editing CSS variables; flip the preview to RTL to confirm it mirrors.
Source
The exact, editable file ui:add writes
into your app. The preview above renders this same source — there are no preview-only pages.
@props([
'title' => 'Dashboard',
'subtitle' => 'Overview of your workspace',
'nav' => null,
'stats' => null,
])
@php
$nav ??= [
['label' => 'Overview', 'href' => '#', 'current' => true],
['label' => 'Customers', 'href' => '#', 'current' => false],
['label' => 'Billing', 'href' => '#', 'current' => false],
['label' => 'Settings', 'href' => '#', 'current' => false],
];
$stats ??= [
['label' => 'Revenue', 'value' => '$24.8K', 'delta' => '+12.5%', 'tone' => 'success'],
['label' => 'Active users', 'value' => '1,284', 'delta' => '+4.1%', 'tone' => 'default'],
['label' => 'Open tasks', 'value' => '32', 'delta' => '-8.0%', 'tone' => 'warning'],
];
@endphp
<x-ui.section data-surface="admin" space="none" class="min-h-svh" {{ $attributes }}>
<header class="border-b border-border bg-card">
<div class="mx-auto flex max-w-7xl items-center justify-between gap-4 px-4 py-4 sm:px-6 lg:px-8">
<div>
<h1 class="text-xl font-semibold">{{ __($title) }}</h1>
<p class="text-sm text-muted-foreground">{{ __($subtitle) }}</p>
</div>
<x-ui.button type="button" size="sm">{{ __('New project') }}</x-ui.button>
</div>
</header>
<div class="mx-auto grid max-w-7xl gap-6 px-4 py-6 sm:px-6 lg:grid-cols-[16rem_1fr] lg:px-8">
<aside class="rounded-lg border border-border bg-card p-6">
<nav class="grid gap-2 text-sm" aria-label="{{ __('Dashboard') }}">
@foreach ($nav as $item)
<a
href="{{ $item['href'] }}"
@class([
'rounded-md px-4 py-2 transition-colors',
'bg-muted font-medium text-foreground' => $item['current'] ?? false,
'text-muted-foreground hover:bg-muted hover:text-foreground' => ! ($item['current'] ?? false),
])
@if ($item['current'] ?? false) aria-current="page" @endif
>{{ __($item['label']) }}</a>
@endforeach
</nav>
</aside>
<main class="grid gap-6">
<div class="grid gap-4 md:grid-cols-3">
@foreach ($stats as $stat)
<x-ui.card>
<x-ui.card.header class="gap-2">
<x-ui.card.description>{{ __($stat['label']) }}</x-ui.card.description>
<div class="flex items-center justify-between">
<x-ui.card.title class="text-2xl">{{ $stat['value'] }}</x-ui.card.title>
<x-ui.badge :variant="$stat['tone'] ?? 'default'">{{ $stat['delta'] }}</x-ui.badge>
</div>
</x-ui.card.header>
</x-ui.card>
@endforeach
</div>
<x-ui.card>
<x-ui.card.header>
<x-ui.card.title>{{ __('Workspace activity') }}</x-ui.card.title>
<x-ui.card.description>{{ __('Recent operational events and review items.') }}</x-ui.card.description>
</x-ui.card.header>
<x-ui.card.content class="grid gap-4 text-sm">
<div class="flex items-center justify-between rounded-md border border-border p-4">
<span>{{ __('Payment provider synced') }}</span>
<span class="text-muted-foreground">{{ __('2 min ago') }}</span>
</div>
<div class="flex items-center justify-between rounded-md border border-border p-4">
<span>{{ __('New team invite accepted') }}</span>
<span class="text-muted-foreground">{{ __('18 min ago') }}</span>
</div>
</x-ui.card.content>
</x-ui.card>
</main>
</div>
</x-ui.section>
Ownership & lifecycle
Owner, release state, review evidence and adoption for this item.
- Owner
- Platform UI (@JoshJML)
- Current version
-
1.1.4 - Status
- Stable
- License
-
open - Deprecation
- Not deprecated
- Contract
-
v1 - Foundation
-
≥ 1.0.0