App Shell

The dashboard skeleton — LB.Shell. The 2026 "inverted L": full-height sidebar + content column whose header lives inside the column. Variant axes: collapse (data-lb-shell-collapse="icon | offcanvas | none") × side (--right) × style (standard · --floating · --inset) × right rail (slot). Opt-in drag-resize (data-lb-shell-resizable) — drag the sidebar edge, arrow keys when focused, drag-to-edge collapses. State persists in localStorage. Toggle: button or Ctrl/Cmd+B. Consumed here: Icon Button · Breadcrumb · Avatar · Badge · Card · Stat · Resizable. Composed in the AI Chat template.

a11y (built in, verified): sidebar nav is a <nav aria-label> landmark (never aside); the content column is <main tabindex="-1"> so the skip link can move real focus; the topbar is not a banner landmark (nested headers lose the role by spec — intentional); toggle is a button[aria-expanded][aria-controls]; rail mode keeps labels in the DOM (clip-hidden) so accessible names survive; frame is 100dvh; reduced-motion disables the collapse animation. Mobile ≤768px: sidebar becomes a modal drawer (focus trap + scroll-lock + Esc), or opt into the bottom-bar pattern with --mobile-bar.

Usage: Load js/lb.js first, then js/components/lb-shell.js; every data-lb-shell element auto-inits, and lb.js console-warns if the markup is present without the module. Structure contract: .lb-shell__sidebar (head · <nav> · foot) + .lb-shell__main (topbar · .lb-shell__content), optional <aside class="lb-shell__panel">; any button inside carrying data-lb-shell-toggle becomes a collapse control with aria-expanded/aria-controls wired for free. React to lb-shell-collapse ({collapsed}) and lb-shell-drawer-open / lb-shell-drawer-close, or drive it from el._lbShell. Routing stays yours — items are plain links, you set lb-shell__item--active + aria-current per route, and each distinct shell needs its own data-lb-shell-key so persisted widths don't collide (the default key is shared).


A · Default — icon-rail collapse + drag-resize

Click the panel-left toggle (or Ctrl/Cmd+B) to collapse to the 3rem rail — labels clip-hide, icons keep their accessible names. Drag the sidebar's right edge to resize (14–22rem); drag it near the edge to collapse. Three sidebar zones: brand · nav groups (one nested level) · user foot.

Skip to content
letbe
Platform
Dashboard Inbox
Website Mobile app Design system
Workspace
Members Settings
  1. Workspace/
  2. Dashboard

Dashboard

Active projects128
Components2,410
Token coverage97%

B · Offcanvas collapse

data-lb-shell-collapse="offcanvas" — the sidebar hides entirely — no icon rail remains. Toggle brings it back.

letbe
Overview Documents Settings
Overview

Collapse fully hides the sidebar — every tab gets the full width.

C · Styles — --floating · --inset

Floating detaches the sidebar as a card; inset makes the content column the card instead. Both collapse like the default.

letbe
Home Inbox
Floating

Sidebar floats as a detached card.

letbe
Home Team
Inset

Content column is the elevated card.

D · Inspector rail

The optional right rail (.lb-shell__panel) — an inspector for the selected item. It's an <aside> (complementary is correct here: supporting detail, not navigation).

letbe
Issues Projects
LB-204 · Fix focus ring on rail items

Issue body. The rail on the right holds metadata.

Status
In progress
Assignee
Vatroslav K
Priority
High

E · Mobile — bottom bar variant

--mobile-bar + a .lb-shell__bottombar nav: below 768px the sidebar disappears and this bar takes over, keeping the primary destinations in thumb reach. Without the modifier the sidebar becomes a modal drawer instead — shrink the window below 768px to compare (demo A = drawer, this one = bar).

letbe
Home Search Activity Settings
Home

Below 768px the bottom bar replaces the sidebar.

Home Search Activity Settings

F · Hover-peek rail — --peek

This shell starts on the icon rail — hover the rail (or Tab into it) and it expands as a temporary overlay; the content never shifts. Leave and it snaps back. Pure CSS (:hover / :focus-within), so keyboard users get the same peek. Toggle still pins it open permanently.

letbe
Studio
Home Projects Inbox Members Settings
Hover-peek

Hover the rail on the left — it peeks open over this text without pushing it. This paragraph stays exactly where it is.

API

Add data-lb-shell. Auto-inits. Options: data-lb-shell-collapse="icon|offcanvas|none", data-lb-shell-resizable, data-lb-shell-key (persistence key); class modifiers --right / --floating / --inset / --peek (hover/focus overlay expand of the icon rail, standard style only) / --mobile-bar; add --collapsed in markup to start on the rail. Instance at el._lbShell: toggle() / setCollapsed(bool) / isCollapsed(), openDrawer() / closeDrawer(). Events: lb-shell-collapse {collapsed}, lb-shell-drawer-open/-close. On a real page the shell is the body's only child at 100dvh; demos override height inline.