App Shell
The three-row application scaffold: toolbar over a left/main/right body over a status bar.
Live demo
AppShell is the outermost layout frame for a full-screen application. It establishes a three-row grid (a top toolbar, a flexible body, and a bottom status bar) where the body is itself a three-column grid of a left rail, a scrollable main column, and a right rail.
Every region is an optional named slot, so the same scaffold collapses cleanly from a full IDE-style layout down to a bare main column. The main region is a real <main> landmark that owns the only scroll, keeping the chrome pinned. An optional skip link, hidden until focused, lets keyboard users jump straight past the chrome to the content. It carries no chrome of its own: the Astro and HTML bindings emit the same light-DOM structure, and the custom element is a transparent display: contents host that contributes nothing to the layout.
When to use
How this component composes with the rest of the set.
Props
10 props, straight from the manifest.
| Prop | Type | Default | Bindings | Description |
|---|---|---|---|---|
true uses the default label; a string overrides it. The Astro binding also accepts a skip-link slot for richer content. | ||||
id given to the <main> region, and the anchor the skip link jumps to (main-id). Rename it when a page holds more than one shell, or when something else on the page already owns main. | ||||
18rem, 20%). Omit to size the rail to its content. | ||||
leftSize. When rightResizable is set this is the rail's starting width and its double-click reset target. | ||||
Shift for a larger step, Home/End to jump to the bounds), and a double-click reset to leftSize. The main column reflows live as the rail changes. The element emits resize / resize-end events with the side and size. | ||||
leftResizable with a double-click reset to rightSize. | ||||
left-min). | ||||
left-max). | ||||
right-min). | ||||
right-max). |
Events
What the component emits, and what rides along on event.detail. The name in the
first column is the one addEventListener takes.
| Event | Detail | Bindings | Description |
|---|---|---|---|
Home/End, or a double-click reset committed. The keyboard routes emit only this one, never resize. |
Appearance
States
main-focus
The main region after the skip link moves focus to it; an inset ring marks the landing.
skip-link-focus
The skip link revealed on keyboard focus, sliding into view with the standard ring.
Anatomy
The named parts that make up the component. A ::part() handle is reachable from your own stylesheet; the class beside it is the component's internal selector, which a shadow boundary keeps to itself.
app
The outer three-row grid filling the viewport, carrying the body background and base typography.
body
The middle row split into the left rail, the main column, and the right rail.
main
The scrollable <main> landmark and skip-link target; takes the remaining space.
rail-handle
The drag handle on a resizable rail's inner edge (when leftResizable / rightResizable is set); a hairline that thickens to the accent on hover, keyboard focus, and drag.
skip-link
The keyboard-only jump link, off-screen until focused, sliding into the top-left when it is.
Tokens & coverage
What the component consumes, checked live against what the algorithm produces.
Live coverage check against the xtyle-default register
(derive(xtyleDefault, { anchors }) →
coverComponent(manifest, register)). Every token this component
consumes must be a key the algorithm produces.
--accent--accent-fg--body-bg--border-normal--border-thick--border-thin--duration-fast--ease-standard--fg-0--font-sans--layer-chrome--layer-skip--leading-normal--leading-tight--line--radius-md--ring--space-2--space-3--space-4--space-5--text-body--text-sm--weight-mediumSlots
The main content, rendered inside the scrollable <main> landmark.
The top row; typically a Toolbar with the app title and global actions.
The left rail; typically navigation.
The right rail; typically contextual detail.
The bottom row; typically a Statusbar.
Custom content for the skip link (Astro only); falls back to a default label otherwise.
Accessibility
Code
Full application scaffold
Toolbar, left and right rails, scrollable main, a status bar, and a skip link.
<xtyle-app-shell skip-link>
<header slot="toolbar" class="xtyle-toolbar">App title and global actions</header>
<nav slot="left" class="xtyle-panel">Primary navigation</nav>
<h1>Page content</h1>
<p>Everything in the default slot lands in the scrollable main column.</p>
<aside slot="right" class="xtyle-panel">Contextual details</aside>
<footer slot="statusbar" class="xtyle-statusbar">Ready</footer>
</xtyle-app-shell><script lang="ts">
import { AppShell } from "@xtyle/svelte";
</script>
<AppShell skipLink>
{#snippet toolbar()}
<header class="xtyle-toolbar">App title and global actions</header>
{/snippet}
{#snippet left()}
<nav class="xtyle-panel">Primary navigation</nav>
{/snippet}
<h1>Page content</h1>
<p>Everything in the default slot lands in the scrollable main column.</p>
{#snippet right()}
<aside class="xtyle-panel">Contextual details</aside>
{/snippet}
{#snippet statusbar()}
<footer class="xtyle-statusbar">Ready</footer>
{/snippet}
</AppShell>---
import { AppShell } from "@xtyle/astro";
---
<AppShell skipLink>
<header slot="toolbar" class="xtyle-toolbar">App title and global actions</header>
<nav slot="left" class="xtyle-panel">Primary navigation</nav>
<h1>Page content</h1>
<p>Everything in the default slot lands in the scrollable main column.</p>
<aside slot="right" class="xtyle-panel">Contextual details</aside>
<footer slot="statusbar" class="xtyle-statusbar">Ready</footer>
</AppShell>Resizable right rail
An editor with a user-resizable inspector: drag the rail's inner edge (or arrow-key the handle) and the main column reflows; double-click to reset. leftResizable mirrors it.
<xtyle-app-shell right-size="344" right-resizable right-min="288" right-max="560">
<header slot="toolbar" class="xtyle-toolbar">Editor</header>
<h1>Canvas</h1>
<!-- Drag the rail's inner edge to resize; double-click it to reset to 344. -->
<aside slot="right" class="xtyle-panel">Inspector</aside>
</xtyle-app-shell><script lang="ts">
import { AppShell } from "@xtyle/svelte";
</script>
<AppShell rightSize={344} rightResizable rightMin={288} rightMax={560}>
{#snippet toolbar()}
<header class="xtyle-toolbar">Editor</header>
{/snippet}
<h1>Canvas</h1>
{#snippet right()}
<aside class="xtyle-panel">Inspector</aside>
{/snippet}
</AppShell>---
import { AppShell } from "@xtyle/astro";
---
<AppShell rightSize={344} rightResizable rightMin={288} rightMax={560}>
<header slot="toolbar" class="xtyle-toolbar">Editor</header>
<h1>Canvas</h1>
<aside slot="right" class="xtyle-panel">Inspector</aside>
</AppShell>