AppShell
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
1 prop, straight from the manifest.
| Prop | Type | Default | Bindings | Description |
|---|---|---|---|---|
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, with their selectors.
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.
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 xoji-default register
(derive(xojiDefault, { 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
--leading-normal
--leading-tight
--radius-md
--ring
--space-2
--space-3
--space-4
--space-5
--text-body
--text-sm
--weight-medium
Slots
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.
<xoji-app-shell skip-link>
<header slot="toolbar" class="xoji-toolbar">App title and global actions</header>
<nav slot="left" class="xoji-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="xoji-panel">Contextual details</aside>
<footer slot="statusbar" class="xoji-statusbar">Ready</footer>
</xoji-app-shell>
<script lang="ts">
import { AppShell } from "@xoji/svelte";
</script>
<AppShell skipLink>
{#snippet toolbar()}
<header class="xoji-toolbar">App title and global actions</header>
{/snippet}
{#snippet left()}
<nav class="xoji-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="xoji-panel">Contextual details</aside>
{/snippet}
{#snippet statusbar()}
<footer class="xoji-statusbar">Ready</footer>
{/snippet}
</AppShell>
---
import { AppShell } from "@xoji/astro";
---
<AppShell skipLink>
<header slot="toolbar" class="xoji-toolbar">App title and global actions</header>
<nav slot="left" class="xoji-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="xoji-panel">Contextual details</aside>
<footer slot="statusbar" class="xoji-statusbar">Ready</footer>
</AppShell>