Aros HIG/Vol. III/PatternsPatterns
Volume III

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.

3.1 · Patterns

App shell

Every authenticated screen shares one frame: a persistent left rail, a sticky top bar, and a single content well.

aros.ryanit.com/estate
AROS
Estate
Resources
Observe
Approvals
Audit
Settings
Platform-wide ▾Search or jump to… ⌘KAll systems operational
Hosts
3
Resources
37
Alerts
0
rail240px · collapses to 56px (icon-only, labels become tooltips) · z-rail · off-canvas drawer below lg · brand lockup top, live platform health bottom
topbar56px · z-sticky · blur backdrop · tenant scope left · the palette's front door centre · theme, identity, sign-out right
contentthe well scrolls, the chrome does not · page inset --s6 · max 1080px for prose, full width for instruments (tables, dashboards)
modalityone modal owner: the drawer, the palette and any dialog are mutually exclusive, and everything behind them is inert
MUSTThe rail's active item wears the keyline, the tint and the green icon. The shell is identical on every screen — never relocate the rail or restyle the topbar per page.
SHOULDCustomer-facing surfaces (the public status page, the portal) drop the operator chrome entirely and use the calmer centred frame — the same mark, the same wordmark, the same status grammar, no rail.
3.1a · Patterns

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.

LayerMechanismTaught by
Anywhere⌘K palette · ? help sheet · g-then-x jumpsthe top-bar front door, the palette's own hints
A list/ focuses the filter · j/k move · ↵ opens · ⋯ or right-click for the row menuthe search field's keycap, the row menu's keycaps
A formTab in order · ⌘↵ submits · Esc cancelsthe primary button's tooltip
A dialogfocus trapped · Esc closes · focus returns to the openernothing to teach — it just holds
MUSTA shortcut is never the only way. The pointer path exists, is visible, and shows the shortcut beside itself.
3.1b · Patterns

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.

Verdict first, evidence on demand

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.

Where the second layer lives

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.

SHOULDGroup a form's rare fields under an Advanced disclosure, closed by default, that names how many fields it hides ("Advanced · 4"). A hidden field the operator does not know exists is a bug filed later.
NEVERHide the state itself. Disclosure is for why and more; the verdict — healthy, degraded, down — is always on the first layer.
3.1d · Patterns

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.

ElementDesktopPhone (< 1024)
navigationthe rail, 240pxa bottom tab bar — Home · Estate · Ops · Search · More — 56px + safe-area inset; "More" opens the full section drawer
top bartenant · front door · identity44px: back or menu · page title · one action; the tenant scope is a chip inside More
scrollingthe content well scrolls inside the shellthe DOCUMENT scrolls — the browser chrome collapses, pull-to-refresh works, the tab bar is fixed
page headertitle · description · actions righttitle 22, description folded behind a ⓘ affordance, the primary action pinned in the tab bar's raised slot or at the top right
sub-navthe tab stripone horizontal row, scroll-snapped, the active tab scrolled into view — never wrapped into a stack
stat rowfive tilestwo per row, or a horizontal snap row for five
filter barthe rowsearch 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
tableDataTablea card list — primary line, secondary line, the status pill, one action; the same selection and row menu (long-press)
dialog · side panelmodal · right sheeta bottom sheet with a grab handle; the primary action pinned above the keyboard
controls36px44px, native pickers for date and select, 16px input text so iOS does not zoom
detail pagetabsthe same tabs, scroll-snapped; sections collapse to headers with counts on long pages
MUSTEvery interactive target is 44 × 44 or larger on a phone, the page never scrolls sideways, and nothing important hides under the tab bar or the home indicator.
SHOULDDesign the phone shape of a component once (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.
NEVERShow a phone user a desktop toolbar shrunk to fit. If a control is not worth a sheet, it is not worth the phone.
3.1c · Patterns

Density

The console is an instrument: dense by default (vol1 §1.2.3). The operator chooses the table density once, and the console remembers.

SettingRowsPersistedRule
standard12 × 14 cellsper browser (aros-density)the default
compact8 × 12 cellsper browsertype does not shrink — 13px is still the floor
SHOULDPick one density per surface and hold it. NEVER mix densities within a single view.
3.2 · Patterns

Dashboard

The landing screen answers one question first — "is everything OK?" — then lets the operator drill in.

Cluster health · 1h
Failure domains
Aros PG · Patroni3/3
MinIO · EC2/3 hosts
SHOULDOrder a dashboard by urgency, then rollup, then detail: the overall verdict on top, summary metrics next, drill-in tables last.
3.3 · Patterns · canonical

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.

Operational
3
Hosts up
37
Resources
1
At risk
0
Down
LevelVerdict shownRollup rule
EstateSingle worst-case verdict + countsWorst child wins: one host down → estate "degraded"
HostHost state + resource countsWorst resource wins
ResourceLive state + last-seenLeaf — reported directly
MUSTRoll status up by worst-case. A green estate badge over a failing node is a lie, and lying about state breaks P3 (Transparent) — the cardinal sin.
NEVERAverage or "mostly green" a rollup. Status is worst-case, not a mean.
3.4 · Patterns

Inventory & tree

The estate is a hierarchy: host → VM → container. The tree makes parentage and rollup visible at a glance.

pve12 VMs · 1 container
aros-pg-dev-1VM 231
patronileader
aros-minio-4VM 274 · SPOF
pve3RAM upgrade queued
SHOULDIndent each level by --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.

MUSTOne filter bar per page, and one table. A page that grows a second toolbar or a second table has become two pages — split it, or fold the second into a tab.
3.5 · Patterns

Approval flow

Aros proposes; a human approves; the system applies and records. The stepper makes the gate explicit.

Proposed
Review
3Applied
Sealed
Restart aros-worker-discovery-dev
Proposed by remediation engine · schedule stalled
MUSTEvery applied action lands in the audit log ("Sealed"). The flow is not complete until it's recorded — propose, approve, apply, seal.
3.6 · Patterns

Discovery flow

How found entities surface over time. Discovery is continuous; the timeline shows what changed each sweep.

Sweep complete — 37 entities
18:57:04 · pve1, pve2, pve3
New VM entity materialised — aros-pg-dev-3
18:57:03 · linked to pve3
Container nested under parent VM
18:57:03 · patroni → aros-pg-dev-3
SHOULDShow discovery as deltas over time, not just a current snapshot. An operator's question is usually "what changed?" — answer it without a diff in their head.
3.7 · Patterns

Notification pattern

Raw events are noisy. Aros dedups, correlates, and assigns severity before anything reaches a human or ntfy.

Event
Dedup
Correlate
Dispatch
P1 · Quorum lost
pve3 unreachable · correlated with 4 child alerts (suppressed)
P3 · MinIO read-only risk
dual-VM host · deduped ×3 in 5 min
MUSTSuppress correlated child alerts under their root cause. Paging an operator four times for one failed host trains them to ignore the pager.
3.8 · Patterns

Forms

Single column, labels above fields, related fields grouped, primary action bottom-right.

Enable object lock
SHOULDKeep forms single-column. Multi-column forms scatter the eye and break the top-to-bottom reading order; the only exception is short, obviously-paired fields (city / postcode).
SHOULDA routine create / edit form with three or more fields lives in a side panel (vol2 §2.8.2), not a modal: the list stays visible behind it, the panel scrolls, and the primary action never leaves the screen. A modal is for a decision that must interrupt.
MUSTPlace the primary action bottom-right, secondary to its left, separated from the fields by a divider. Destructive actions sit far from the primary.
3.9 · Patterns

Empty & error pages

Page-level versions of the component states — centred, calm, always with a way forward.

Nothing to observe yet

Connect a host to begin discovery. Aros will populate the estate automatically.

MUSTA page-level empty or error state stays on-brand and calm — obsidian, one glyph, one action. No full-bleed red, no apologetic paragraphs, no dead ends.
End of Volume III

Next: Content & voice

Screens are built. Volume IV — Content & voice → governs the words inside them.

Copied