Shell
BlockCSS + JavaScript shell.jsRequires _defaults.js
The shell is the top-level dashboard layout: a full-viewport frame with an icon
base rail, an expandable retractable panel of sub-navigation, and a scrollable
content area. Layout is driven entirely by data-* attributes; shell.js handles
the retractable toggle, header measurement, and persistence.
<section class="shell" data-shell> <div class="shell-body" data-shell-body> <!-- ============ sidebar ============ --> <aside class="shell-sidebar" data-shell-sidebar> <!-- base rail (always visible) --> <div class="shell-sidebar-base" data-shell-sidebar-base> <a href="#" class="grid size-10 place-items-center rounded-lg bg-action-primary font-bold text-action-on-primary"> S </a>
<button type="button" class="shell-sidebar-base-action" data-shell-sidebar-base-action> <span data-shell-sidebar-base-action-badge ><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" > <path d="M3 10a7 7 0 1 0 14 0a7 7 0 1 0 -14 0" /> <path d="M21 21l-6 -6" /></svg ></span> </button>
<hr class="border-muted w-full max-w-13" />
<div class="shell-sidebar-base-scrollable" data-shell-sidebar-base-scrollable> <a href="#" class="shell-sidebar-base-action" data-shell-sidebar-base-action data-shell-sidebar-base-action-id="dashboard" > <span data-shell-sidebar-base-action-badge ><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" > <path d="M4 6a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v1a2 2 0 0 1 -2 2h-2a2 2 0 0 1 -2 -2l0 -1" /> <path d="M4 15a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v3a2 2 0 0 1 -2 2h-2a2 2 0 0 1 -2 -2l0 -3" /> <path d="M14 6a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v3a2 2 0 0 1 -2 2h-2a2 2 0 0 1 -2 -2l0 -3" /> <path d="M14 17a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v1a2 2 0 0 1 -2 2h-2a2 2 0 0 1 -2 -2l0 -1" /></svg ></span> <span data-shell-sidebar-base-action-title>Dashboard</span> </a>
<a href="#" class="shell-sidebar-base-action" data-shell-sidebar-base-action data-shell-sidebar-base-action-id="accounts" data-active > <span data-shell-sidebar-base-action-badge ><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" > <path d="M10 13a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" /> <path d="M8 21v-1a2 2 0 0 1 2 -2h4a2 2 0 0 1 2 2v1" /> <path d="M15 5a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" /> <path d="M17 10h2a2 2 0 0 1 2 2v1" /> <path d="M5 5a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" /> <path d="M3 13v-1a2 2 0 0 1 2 -2h2" /></svg ></span> <span data-shell-sidebar-base-action-title>Accounts</span> </a>
<a href="#" class="shell-sidebar-base-action" data-shell-sidebar-base-action data-shell-sidebar-base-action-id="exchange" > <span data-shell-sidebar-base-action-badge ><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" > <path d="M20 10h-16l5.5 -6" /> <path d="M4 14h16l-5.5 6" /></svg ></span> <span data-shell-sidebar-base-action-title>Exchange</span> </a>
<a href="#" class="shell-sidebar-base-action" data-shell-sidebar-base-action data-shell-sidebar-base-action-id="transactions" > <span data-shell-sidebar-base-action-badge ><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" > <path d="M7 15h-3a1 1 0 0 1 -1 -1v-8a1 1 0 0 1 1 -1h12a1 1 0 0 1 1 1v3" /> <path d="M7 10a1 1 0 0 1 1 -1h12a1 1 0 0 1 1 1v8a1 1 0 0 1 -1 1h-12a1 1 0 0 1 -1 -1l0 -8" /> <path d="M12 14a2 2 0 1 0 4 0a2 2 0 0 0 -4 0" /></svg ></span> <span data-shell-sidebar-base-action-title>Transactions</span> </a>
<a href="#" class="shell-sidebar-base-action" data-shell-sidebar-base-action data-shell-sidebar-base-action-id="reports" > <span data-shell-sidebar-base-action-badge ><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" > <path d="M14 3v4a1 1 0 0 0 1 1h4" /> <path d="M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2" /> <path d="M9 17l0 -5" /> <path d="M12 17l0 -1" /> <path d="M15 17l0 -3" /></svg ></span> <span data-shell-sidebar-base-action-title>Reports</span> </a> </div>
<hr class="border-muted w-full max-w-13" />
<!-- opens / closes the retractable panel; state is persisted --> <button type="button" class="shell-sidebar-base-action" data-shell-sidebar-base-action data-shell-sidebar-retractable-toggler > <span data-shell-sidebar-base-action-badge ><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" > <path d="M4 6h16" /> <path d="M7 12h13" /> <path d="M10 18h10" /></svg ></span> </button>
<a href="#" class="shell-sidebar-base-action" data-shell-sidebar-base-action> <span data-shell-sidebar-base-action-badge ><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" > <path d="M10.325 4.317c.426 -1.756 2.924 -1.756 3.35 0a1.724 1.724 0 0 0 2.573 1.066c1.543 -.94 3.31 .826 2.37 2.37a1.724 1.724 0 0 0 1.065 2.572c1.756 .426 1.756 2.924 0 3.35a1.724 1.724 0 0 0 -1.066 2.573c.94 1.543 -.826 3.31 -2.37 2.37a1.724 1.724 0 0 0 -2.572 1.065c-.426 1.756 -2.924 1.756 -3.35 0a1.724 1.724 0 0 0 -2.573 -1.066c-1.543 .94 -3.31 -.826 -2.37 -2.37a1.724 1.724 0 0 0 -1.065 -2.572c-1.756 -.426 -1.756 -2.924 0 -3.35a1.724 1.724 0 0 0 1.066 -2.573c-.94 -1.543 .826 -3.31 2.37 -2.37c1 .608 2.296 .07 2.572 -1.065" /> <path d="M9 12a3 3 0 1 0 6 0a3 3 0 0 0 -6 0" /></svg ></span> </a>
<button type="button" class="shell-sidebar-base-action" data-shell-sidebar-base-action> <span data-shell-sidebar-base-action-photo>RA</span> </button> </div>
<!-- retractable panel (0-width until [data-shell-sidebar-open]) --> <div class="shell-sidebar-retractable" data-shell-sidebar-retractable> <p class="text-xl font-semibold text-foreground xl:text-2xl">Accounts</p>
<a href="#" class="shell-sidebar-retractable-action">Add account</a> <a href="#" class="shell-sidebar-retractable-action" data-active>Accounts</a> <a href="#" class="shell-sidebar-retractable-action">Archived accounts</a> <a href="#" class="shell-sidebar-retractable-action">Receivers & payers</a> </div> </aside>
<!-- ============ content ============ --> <main class="shell-content pb-8" data-shell-content> <div class="mx-auto w-full max-w-6xl px-6"> <!-- content header: breadcrumb + actions --> <div class="shell-content-header" data-shell-content-header> <nav class="shell-breadcrumb" data-shell-breadcrumb> <a href="#" class="shell-breadcrumb-action" data-shell-breadcrumb-action>Home</a> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" > <path d="M9 6l6 6l-6 6" /> </svg> <span class="shell-breadcrumb-current" data-shell-breadcrumb-current>Accounts</span> </nav>
<div class="shell-content-actions" data-shell-content-actions> <button type="button" class="button-secondary">Export</button> <button type="button" class="button-fill-primary"><span>Add account</span></button> </div> </div>
<!-- stat cards --> <div class="mt-2 grid gap-4 sm:grid-cols-2 lg:grid-cols-3"> <div class="rounded-2xl border border-border bg-background-muted p-5"> <p class="text-foreground-subtle">Total balance</p> <p class="mt-2 text-2xl font-semibold">$128,400</p> </div>
<div class="rounded-2xl border border-border bg-background-muted p-5"> <p class="text-foreground-subtle">Open accounts</p> <p class="mt-2 text-2xl font-semibold">312</p> </div>
<div class="rounded-2xl border border-border bg-background-muted p-5"> <p class="text-foreground-subtle">This month</p> <p class="mt-2 text-2xl font-semibold text-foreground-positive">+4.6%</p> </div> </div>
<!-- a simple list --> <div class="mt-6 overflow-hidden rounded-2xl border border-border bg-background-muted"> <div class="flex items-center justify-between border-b border-border-muted px-5 py-4"> <p class="font-medium text-foreground">Recent activity</p> <a href="#" class="text-sm text-foreground-primary">View all</a> </div>
<ul> <li class="flex items-center justify-between border-b border-border-muted px-5 py-4 last:border-0"> <span class="text-foreground">Karwan Hassan · deposit</span> <span class="font-medium text-foreground-positive">+$1,200</span> </li> <li class="flex items-center justify-between border-b border-border-muted px-5 py-4 last:border-0"> <span class="text-foreground">Ari Faruq · withdrawal</span> <span class="font-medium text-foreground-negative">−$540</span> </li> <li class="flex items-center justify-between px-5 py-4"> <span class="text-foreground">Zana Rashid · transfer</span> <span class="font-medium text-foreground">$3,000</span> </li> </ul> </div> </div> </main> </div></section>Structure
Section titled “Structure”The shell is three nested regions — a body that lays out a sidebar beside the content. Note the blank lines: each region is a distinct block you can read top-down.
<section class="shell" data-shell> <div class="shell-body" data-shell-body> <!-- ① sidebar: an always-visible icon rail + an expandable panel --> <aside class="shell-sidebar" data-shell-sidebar> <div class="shell-sidebar-base" data-shell-sidebar-base> <div class="shell-sidebar-base-scrollable" data-shell-sidebar-base-scrollable> <a class="shell-sidebar-base-action" data-shell-sidebar-base-action data-active> <span data-shell-sidebar-base-action-badge><!-- icon --></span> <span data-shell-sidebar-base-action-title>Accounts</span> </a> </div>
<button data-shell-sidebar-base-action data-shell-sidebar-retractable-toggler> <!-- menu icon --> </button> </div>
<div class="shell-sidebar-retractable" data-shell-sidebar-retractable> <a class="shell-sidebar-retractable-action" data-active>Accounts</a> </div> </aside>
<!-- ② content: your scrollable page --> <main class="shell-content" data-shell-content> <div class="shell-content-header" data-shell-content-header> <nav class="shell-breadcrumb" data-shell-breadcrumb>…</nav> <div class="shell-content-actions" data-shell-content-actions>…</div> </div>
<!-- page content… --> </main> </div></section>Attributes
Section titled “Attributes”Layout containers
Section titled “Layout containers”| Attribute | On | Meaning |
|---|---|---|
data-shell |
root | The shell. Gets data-shell="loaded" [auto-set] once JS is ready (enables transitions). |
data-shell-sidebar-open |
root | [auto-set] — present while the retractable panel is open. |
data-shell-header |
element | Mobile top bar. Its height is measured into --shell-header-height. |
data-shell-body |
element | Row wrapper for sidebar + content. |
data-shell-content |
element | Scrollable content column. |
Sidebar
Section titled “Sidebar”| Attribute | On | Meaning |
|---|---|---|
data-shell-sidebar |
<aside> |
The whole sidebar (base + retractable). |
data-shell-sidebar-base |
element | The always-visible icon rail. |
data-shell-sidebar-base-scrollable |
element | Scrollable region of the rail. |
data-shell-sidebar-base-action |
link/button | A rail item. Add data-active for the current one. |
data-shell-sidebar-base-action-id |
rail item | Identifier for the item (matches a retractable/drawer section). |
data-shell-sidebar-base-action-badge |
child | Wrapper for the item’s icon. |
data-shell-sidebar-base-action-photo |
child | Wrapper for an avatar (image or initials). |
data-shell-sidebar-base-action-title |
child | The item’s label. |
data-shell-sidebar-retractable |
element | The expandable sub-nav panel. |
data-shell-sidebar-retractable-action |
link | An item in the retractable panel. Add data-active for the current one. |
data-shell-sidebar-retractable-toggler |
button | Click target that opens/closes the retractable panel. |
Behaviour (shell.js)
Section titled “Behaviour (shell.js)”- Retractable toggle — clicking any
data-shell-sidebar-retractable-togglertogglesdata-shell-sidebar-openon the root and saves it underwindow._storage.shellSidebar(shell:sidebar). - Restore on load — the saved open/closed state is applied on first render.
- Header height — a
ResizeObserverwrites the header’s height to the--shell-header-heightcustom property so content can offset correctly. - Transition guard — animations are suppressed until
data-shell="loaded"is set, so the initial layout doesn’t animate in.
Dependencies
Section titled “Dependencies”_defaults.js— forwindow._storage.shellSidebar. Required.- Preline — the profile dropdown, tooltips, and the (optional) search modal in a full
shell use Preline attributes (
data-hs-overlay,hs-tooltip, …). The layout itself works without them.