Patterns
Components are vocabulary; patterns are grammar. This volume sets how elements compose into the screens operators actually use — and codifies the few canonical patterns that make Aros recognisably Aros, chief among them the status pattern.
App shell
Every authenticated screen shares one frame: a persistent left rail, a sticky top bar, and a single content well.
| rail | 240px · collapses to 56px (icon-only, labels become tooltips) · z-rail · off-canvas drawer below lg · brand lockup top, live platform health bottom |
| topbar | 56px · z-sticky · blur backdrop · tenant scope left · the palette's front door centre · theme, identity, sign-out right |
| content | the well scrolls, the chrome does not · page inset --s6 · max 1080px for prose, full width for instruments (tables, dashboards) |
| modality | one modal owner: the drawer, the palette and any dialog are mutually exclusive, and everything behind them is inert |
Keyboard-first operation
An operator at 3am is not going to hunt for a button. Every view has a fast path, and every fast path is taught where it is used.
| Layer | Mechanism | Taught by |
|---|---|---|
| Anywhere | ⌘K palette · ? help sheet · g-then-x jumps | the top-bar front door, the palette's own hints |
| A list | / focuses the filter · j/k move · ↵ opens · ⋯ or right-click for the row menu | the search field's keycap, the row menu's keycaps |
| A form | Tab in order · ⌘↵ submits · Esc cancels | the primary button's tooltip |
| A dialog | focus trapped · Esc closes · focus returns to the opener | nothing to teach — it just holds |
Progressive disclosure
Density without noise: show the verdict, keep the evidence one gesture away. The estate is too big to show everything, and too important to hide anything.
A status pill says Degraded; the ▾ opens the causes, the threshold and when it was evaluated. A KPI tile shows the number; its link opens the list. The header shows three metrics; the table below has forty columns' worth.
Inline expand for one row's detail (a <details> or a disclosure row). Side panel for one record's full view. Tooltip for a value that was truncated. Never a modal for something you are merely reading.
The phone shell
Below lg the console is a different instrument, not a squeezed one. The rail becomes a bottom tab bar, tables become card lists, dialogs become sheets, and every target is a thumb's width.
| Element | Desktop | Phone (< 1024) |
|---|---|---|
| navigation | the rail, 240px | a bottom tab bar — Home · Estate · Ops · Search · More — 56px + safe-area inset; "More" opens the full section drawer |
| top bar | tenant · front door · identity | 44px: back or menu · page title · one action; the tenant scope is a chip inside More |
| scrolling | the content well scrolls inside the shell | the DOCUMENT scrolls — the browser chrome collapses, pull-to-refresh works, the tab bar is fixed |
| page header | title · description · actions right | title 22, description folded behind a ⓘ affordance, the primary action pinned in the tab bar's raised slot or at the top right |
| sub-nav | the tab strip | one horizontal row, scroll-snapped, the active tab scrolled into view — never wrapped into a stack |
| stat row | five tiles | two per row, or a horizontal snap row for five |
| filter bar | the row | search stays inline with a Filters trigger that carries the active count; the structured filters live in a bottom sheet and apply as you tap — one closing action, Show results, and Clear when anything is on. Never "Apply": nothing is deferred |
| table | DataTable | a card list — primary line, secondary line, the status pill, one action; the same selection and row menu (long-press) |
| dialog · side panel | modal · right sheet | a bottom sheet with a grab handle; the primary action pinned above the keyboard |
| controls | 36px | 44px, native pickers for date and select, 16px input text so iOS does not zoom |
| detail page | tabs | the same tabs, scroll-snapped; sections collapse to headers with counts on long pages |
useIsMobile()) and let every consumer inherit it — a table that becomes a card list on one page and a scrolling table on another is two products.Density
The console is an instrument: dense by default (vol1 §1.2.3). The operator chooses the table density once, and the console remembers.
| Setting | Rows | Persisted | Rule |
|---|---|---|---|
| standard | 12 × 14 cells | per browser (aros-density) | the default |
| compact | 8 × 12 cells | per browser | type does not shrink — 13px is still the floor |
Dashboard
The landing screen answers one question first — "is everything OK?" — then lets the operator drill in.
The status pattern
The defining pattern of Aros. Health is presented at three nested levels — estate, host, resource — and the same grammar (dot + colour + label + rollup) is used at every level so an operator reads it identically whether they're looking at the whole estate or one container.
| Level | Verdict shown | Rollup rule |
|---|---|---|
| Estate | Single worst-case verdict + counts | Worst child wins: one host down → estate "degraded" |
| Host | Host state + resource counts | Worst resource wins |
| Resource | Live state + last-seen | Leaf — reported directly |
Inventory & tree
The estate is a hierarchy: host → VM → container. The tree makes parentage and rollup visible at a glance.
--s6 and lead with the resource's domain icon. A child with no resolvable parent surfaces at root with a "no parent" note — never silently hidden.3.4.1 The list page, in one shape
Every list in the product is the same page: PageHeader → a StatRow (or a metric strip in the header) → ONE filter bar → ONE table or card grid. The filter bar is search first, structured filters next (a segmented control for a small closed set, a select for a long one), presets and export on the right, and one "Clear · n". Filter state is the URL, so a filtered list is a link.
Approval flow
Aros proposes; a human approves; the system applies and records. The stepper makes the gate explicit.
Discovery flow
How found entities surface over time. Discovery is continuous; the timeline shows what changed each sweep.
Notification pattern
Raw events are noisy. Aros dedups, correlates, and assigns severity before anything reaches a human or ntfy.
Forms
Single column, labels above fields, related fields grouped, primary action bottom-right.
Empty & error pages
Page-level versions of the component states — centred, calm, always with a way forward.
Connect a host to begin discovery. Aros will populate the estate automatically.
Next: Content & voice
Screens are built. Volume IV — Content & voice → governs the words inside them.