P3-0: Design system and screen designs — BLOCKS all UI work #51
Labels
No labels
data-integrity
engine
platform
procurement
remote
scaffold
ui
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: Cordy/cairn-desktop#51
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Do this first in phase 3. It blocks #32, #33, #34 and #49.
Why this exists
Four separate issues produce UI. In a subagent-driven run those are four fresh sessions with no
shared visual reference, and the result is four dialects: mismatched padding, different button
hierarchies, inconsistent empty-state voice. The product looks assembled rather than designed,
and fixing it afterwards means touching every screen.
The fix is a single stylesheet plus a living style guide page, built once here and consumed
by every later UI task. Later issues then style nothing from scratch — they use the classes.
Deliverables
frontend/design-system.css— every token and component, light and dark.frontend/design-system.html— a living style guide rendering every component in everystate. Open it, see the whole vocabulary. This is the artifact later tasks read.
frontend/icons/— the mark and tray icons as SVG (see "The signature" below).settings.
Tokens
Cairn's existing palette. Do not invent a new one — the client and the web UI must read as one
product.
Follow the OS theme by default; allow an override in settings.
Typography — the one deliberate idea
Two faces, and the split carries meaning.
brand face. A desktop utility should feel native on each OS; a custom webfont here reads as a
website pretending to be an app.
licence keys, percentages.
That second rule is the typographic personality of this product. Cairn's entire argument is
that your files are real objects on a real disk, not rows in someone's database. Setting every
path and size in monospace makes the interface say that on every screen, at no cost. It is
already the convention in Cairn's web UI and CLI — this makes it deliberate.
Scale (13px base — desktop density, not web):
11 · 12 · 13 · 15 · 20 · 26.Weights: 400 and 600 only. Never 700; it reads heavy against native UI chrome.
Spacing, shape, elevation
4 · 8 · 12 · 16 · 24 · 32 · 48. Nothing between.6pxcontrols,10pxcards,2pxmark bars.--lichen. This is the primary separator.The signature: the mark is the status indicator
The Cairn mark is three stacked rounded bars of increasing width — a cairn, stones marking a
path. It is currently used at 20px in one header and nowhere else. Make it the sync status
indicator, and it becomes both the brand and the most-looked-at element in the product.
--slate-900--glacier--danger, lower two--slate-400--slate-400, hairline outlineOne idea, five places: the tray icon, the window header glyph, the app icon, the installer
artwork, the favicon. Almost no other product's logo is also its spinner — it is genuinely
ownable, and it costs nothing because the shape is three rectangles.
Motion: only the mark animates. Nothing else in this application moves. Under
prefers-reduced-motion, the syncing state becomes a static--glaciertint instead of a loop.This resolves the icon-asset problem
The mark is pure geometry — rounded rectangles — so every icon can be generated as SVG in this
repo, with no external design tool:
--slate-900with the mark in--snow, as SVG..ico(Windows),.icns(macOS), PNG set (Linux).That last step unblocks packaging (#37, #38, #39), which otherwise stalls waiting for artwork.
Component inventory
Build each, in every state, into the style guide:
Buttons — primary (glacier fill), secondary (border), ghost (text), danger. States: rest,
hover, active, focus-visible, disabled, loading.
Form — text input, password, select, checkbox, toggle, folder picker. Plus a managed
variant: read-only with a "Managed by your organisation" note, for policy-set values (#30).
Data display — list row (icon + primary + mono secondary + action), card, badge, progress
bar (determinate and indeterminate), storage meter.
Feedback — inline alert (info/warning/danger/ok), modal dialog, toast, skeleton row.
Navigation — settings sub-nav (vertical list, left side), tab row.
Every list gets three extra states: empty, loading, error. They are the ones that get
forgotten and the ones users hit on their worst day.
Screens to design
choice, confirmation.
status line, activity list, "needs attention" section, storage footer.
make the user scroll to find a setting.
Voice
Sentence case everywhere. No exclamation marks. Plain verbs. An action keeps its name through
the whole flow — "Free up space" produces "Space freed", not "Operation complete". Errors say
what happened and what to do. Empty states are an invitation, never a shrug.
Steps
design-system.csswith tokens, type scale and every component.design-system.htmlshowing all of it, both themes, all states.git commit -s -m "feat(frontend): design system, mark states and screen designs"Acceptance criteria
Visual target committed
docs/mockup-main-window.html— open it in a browser. It is an approved mockup of the mainwindow plus the five mark states, in both themes.
It is a target, not the deliverable. What it settles, so you do not have to re-decide:
turns out to be data rather than prose — that split is the product's visual argument.
syncing and the
prefers-reduced-motionfallback.requires the user is never below the thing that does not.
the moment a user fears they have lost work; answer that first.
Extract the CSS in that file into
frontend/design-system.cssand grow it into the fullcomponent inventory. The mockup uses placeholder glyphs (HTML entities) where the real build
needs proper icons — replace those, keep everything else.
The other three screens — setup wizard, conflict view, settings — still need designing against
this vocabulary.
Amendment — 2026-09-14: phase-3 pre-flight rulings for #51
These rulings come from the phase-3 pre-flight survey. The owner approved posting them and may veto any of them. They bind this issue.
.ico/.icnsstep is a pure-Go program underbuild/icons/(package main,CGO_ENABLED=0). The mark is plain geometry, so the program draws the rectangles directly, with no SVG rasteriser, and writes the PNG set,.icoand.icns. It runs on the Pi runner and on macOS. It never lives underinternal/sync.Posted by Claude on behalf of @Cordy: phase-3 pre-flight, owner-approved process; the owner may veto any point.