Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

App shell

Linear: AUT-122

Top-level layout with slots for rail / main / inspector / titlebar / footer. Each product screen (library, editor, cursor studio, prefs) mounts one AppShell with the panes it needs — chrome stays consistent across surfaces.

Open as live demo →

Slots

SlotRequiredUse
railyesLeft-edge NavigationRail
mainyesThe product surface
titlebaroptionalTop window-chrome strip
inspectoroptionalRight-edge property / inspector panel
footeroptionalBottom status / recording-controls footer

Why slots, not a router

The shell is structural. It places its panes; it does not decide which content goes where. App-ui chooses the children for each slot based on the currently-selected AppSection; the shell just arranges them.

Composition

flowchart TD
    Shell[AppShell] --> Title[titlebar]
    Shell --> Body[body]
    Body --> Rail[rail<br/>NavigationRail]
    Body --> Main[main<br/>per-section content]
    Body --> Inspector[inspector?]
    Shell --> Foot[footer?]

API

#![allow(unused)]
fn main() {
use ui_storybook::components::{AppShell, NavigationRail, /* … */};

view! {
    <AppShell
        rail=ToChildren::to_children(move || view! { <NavigationRail … /> })
        main=ToChildren::to_children(move || view! { /* editor canvas / library grid / … */ })
        inspector=ToChildren::to_children(move || view! { /* property rows */ })
        titlebar=ToChildren::to_children(move || view! { <span>"Recording 02"</span> })
        footer=ToChildren::to_children(move || view! { /* status bar */ })
    />
}
}

Each slot accepts Children (a Box<dyn FnOnce() -> AnyView>). Optional slots accept Option<Children>; pass ToChildren::to_children(...) to populate them and omit the prop to skip.

What this unlocks

Every UI-14..21 ticket plugs into this shell. The library is AppShell { rail: …, main: LibraryGrid, inspector: None }. The editor is AppShell { rail: …, main: EditorCanvas, inspector: InspectorPanel, footer: TimelineSkeleton }. Cursor Studio is AppShell { rail: …, main: CursorPreviewCanvas, inspector: CursorStyleControls }. None of those slots care about the others.