docs: rework design guide per mara's review
Addresses all 7 line comments from her REQUEST_CHANGES review: - drop the issue-#3444 history pointer and any issue-number tracking refs throughout (a design guide states expectations, it isn't a change log or a status report) - stop naming specific rejected technical solutions (SSE/WS) for a design constraint — state the chosen shape only - flip the component-first heuristic: build the primitive first/ alongside its first real caller, not after — the point is giving the next thing built ready-made blocks, not lagging behind usage - drop the 'Open questions' section entirely — that's what the issue thread is for, not a doc - stop leading Visual language with 'basis: Material Design' and then immediately carving out big exceptions — lead with what we actually want, mention Material as a minor closing influence instead - drop 'future work'/timeline framing everywhere (motion override, PWA-as-future-slice, 'not shipped yet' theming caveats) — state the target design as the expectation, not its current build status - reworded the stylix-wins theming bullet to drop 'build time', which reads wrong from a frontend dev's perspective (stylix supplies the palette separately, it isn't decided by the frontend's own build)
This commit is contained in:
parent
a5864c0fde
commit
61b7bb4b4d
1 changed files with 41 additions and 78 deletions
|
|
@ -11,16 +11,8 @@ of truth for appearance and this doc as the source of truth for intent.
|
|||
Colour variables specifically are `docs/web-ui/css-vars.md`'s job, not
|
||||
repeated here.
|
||||
|
||||
Distilled from the design-language discussion in issue #3444 — read that
|
||||
thread for the full reasoning behind any rule below that needs more
|
||||
context than fits here.
|
||||
|
||||
## Visual language
|
||||
|
||||
- **Basis: Material Design, the Material You generation** (Android's
|
||||
current design language) — but swarm-ui strays fairly far from its
|
||||
theming approach; base16/stylix (below) is the actual colour contract,
|
||||
not Material's dynamic-colour system.
|
||||
- **Frosted / tinted glass** where it fits — translucency over flat
|
||||
panels, not a hard rule for every surface.
|
||||
- **Playful use of the multiple accent colours**, without tipping into
|
||||
|
|
@ -39,6 +31,10 @@ context than fits here.
|
|||
swarm-ui, but the standard to avoid): the per-hive agent terminal's
|
||||
model selector living in a three-dot overflow menu instead of next to
|
||||
the thing that shows the current model.
|
||||
- Loosely influenced by Material Design's current (Material You)
|
||||
generation, mainly for shape/elevation ideas — colour theming is
|
||||
governed entirely by the base16/stylix contract below, not Material's
|
||||
dynamic-colour system.
|
||||
|
||||
## Motion
|
||||
|
||||
|
|
@ -51,11 +47,6 @@ though it lives in the dashboard package rather than swarm-ui; every
|
|||
future swarm-ui animation follows the same pattern, not just whimsy
|
||||
pieces.
|
||||
|
||||
An in-app override (independent of the OS-level media query, for
|
||||
someone who wants motion on despite a system-wide reduced-motion
|
||||
setting, or vice versa) is tracked separately — see #3456, which needs
|
||||
the client-settings surface from #3453 first.
|
||||
|
||||
Prefer CSS-driven animation over JS-driven where possible, and avoid
|
||||
jarring content swaps (layout shift, hard cuts) where a transition can
|
||||
smooth them instead.
|
||||
|
|
@ -68,24 +59,20 @@ read that for the how. This section is the *policy* layered on top:
|
|||
|
||||
- **User-theming compatible by construction.** The whole point of the
|
||||
base16/`colors.css` swap contract is that a user's own theme (stylix
|
||||
today) takes over with zero swarm-ui code changes — a generator
|
||||
replaces exactly one file. Don't build anything that assumes a
|
||||
specific palette's exact colours (contrast ratios, "this accent is
|
||||
always purple") beyond what the semantic var names promise.
|
||||
- **stylix wins outright when it's active, no in-between state.**
|
||||
`nix/host-modules/hive-c0re/theme.nix` decides at *build time* whether
|
||||
a hive is stylix-themed; when it is, that palette is authoritative —
|
||||
swarm-ui's own light/dark logic (below) doesn't run at all rather than
|
||||
trying to negotiate with it. This is a deliberate simplification, not
|
||||
a limitation to fix: a stylix-using operator has already made their
|
||||
choice.
|
||||
- **Light theme is accessibility, not a cosmetic extra** — confirmed
|
||||
position on #3444/#3452: some people need light for contrast/low-vision
|
||||
reasons, others need dark for photosensitivity, so "OS preference by
|
||||
default + explicit override" is the right shape, same as motion above.
|
||||
**Not shipped yet** — tracked as #3452 (light palette itself), #3453
|
||||
(the client-settings surface an override setting needs), #3454 (the
|
||||
override setting). Until #3452 lands, swarm-ui is dark-only.
|
||||
today) takes over with zero swarm-ui code changes. Don't build
|
||||
anything that assumes a specific palette's exact colours (contrast
|
||||
ratios, "this accent is always purple") beyond what the semantic var
|
||||
names promise.
|
||||
- **stylix wins outright when it's active, no in-between state.** When
|
||||
an operator has stylix supplying swarm-ui's palette, that palette is
|
||||
authoritative — swarm-ui's own light/dark preference (below) doesn't
|
||||
override it. This is a deliberate simplification, not a limitation to
|
||||
fix: a stylix-using operator has already made their choice.
|
||||
- **Light theme is accessibility, not a cosmetic extra.** Some people
|
||||
need light for contrast/low-vision reasons, others need dark for
|
||||
photosensitivity — there's no universally-correct default. The OS
|
||||
preference (`prefers-color-scheme`) drives the default, with an
|
||||
explicit user override available, same shape as motion above.
|
||||
|
||||
## Data freshness & refresh
|
||||
|
||||
|
|
@ -94,22 +81,18 @@ The governing question for anything that shows time-sensitive data:
|
|||
needs a refresh story; a value that's silently gone stale with no way to
|
||||
tell is worse than one that's visibly stale.
|
||||
|
||||
- **Relative-time labels must actually tick.** A `StatusChip`-style
|
||||
"fresh (5s ago)" computed once at fetch and never updated again reads
|
||||
as current when it isn't. Tracked as #3445 (`RelativeTime` component:
|
||||
takes a UTC datetime, not a precomputed age, and re-renders itself on
|
||||
an internal interval; pauses while its tab is hidden).
|
||||
- **Relative-time labels must actually tick.** A label like "fresh (5s
|
||||
ago)" is computed from a stored timestamp and re-renders itself on an
|
||||
interval — never a value frozen at fetch time that quietly goes stale
|
||||
while still reading as current. Pauses while its tab is hidden.
|
||||
- **Pages that poll get a refresh-interval control, not silent
|
||||
staleness and not push.** SSE/WebSocket push was considered and
|
||||
rejected for now — "overkill, leads to the same mess we have in
|
||||
core." Instead: a small, Grafana-like "refresh every: off / 10s / 30s
|
||||
/ 1m / …" control the operator sets per page, paused while the tab is
|
||||
backgrounded and resumed on foreground. Tracked as #3446
|
||||
(`OverviewPage`'s hive-status roster is the first real caller).
|
||||
staleness.** A small, Grafana-like "refresh every: off / 10s / 30s /
|
||||
1m / …" control the operator sets per page, paused while the tab is
|
||||
backgrounded and resumed on foreground.
|
||||
- **A refresh must never clobber input the operator is mid-edit on.**
|
||||
Any future polling component's contract needs to make this the
|
||||
caller's problem to opt out of correctly, not something the next
|
||||
adopter discovers by shipping a bug.
|
||||
Any polling component's contract needs to make this the caller's
|
||||
problem to opt out of correctly, not something the next adopter
|
||||
discovers by shipping a bug.
|
||||
|
||||
## Errors
|
||||
|
||||
|
|
@ -140,13 +123,11 @@ just bare column headers floating over nothing.
|
|||
not a desktop-only app. Concrete floor: every interactive control from
|
||||
the shared `ui/` kit (buttons, inputs, selects) carries a minimum
|
||||
touch target (`2.75em` ≈ 44px, WCAG 2.5.5) by default, so this isn't
|
||||
something each page has to remember. Tracked follow-through:
|
||||
#3447 (page-level layout — nav wrap, no fixed-width assumptions).
|
||||
- **Phone is a second-class citizen for now, not an unsupported one.**
|
||||
Things must not *break* at phone width, but don't over-invest in phone
|
||||
optimization beyond that yet. A PWA manifest (installable, basic
|
||||
status-check/interaction use case) is wanted eventually but is its own
|
||||
future slice, not implied by "supports touch" today.
|
||||
something each page has to remember.
|
||||
- **Phone is a second-class citizen, not an unsupported one.** Things
|
||||
must not *break* at phone width, but don't over-invest in phone
|
||||
optimization beyond that. swarm-ui is installable as a PWA, so a
|
||||
phone can check status or do basic interactions.
|
||||
- **A narrow viewport isn't only a phone** — a tiling-window-manager
|
||||
user with swarm-ui in a narrow tile hits the same layout constraints a
|
||||
phone does. Design for the constraint (narrow viewport), not the
|
||||
|
|
@ -154,27 +135,21 @@ just bare column headers floating over nothing.
|
|||
|
||||
## Component-first design
|
||||
|
||||
When something needs a table, a form field, a button — build (or adopt)
|
||||
a `src/ui/` primitive that enforces consistent theming and behaviour,
|
||||
rather than styling it inline on the page that happens to need it first.
|
||||
Build the `src/ui/` primitive before or alongside the first real page
|
||||
that needs it, not after it's been styled inline and left for later —
|
||||
a page reaching for a component that's already there has ready-made
|
||||
blocks to build with, instead of the next contributor duplicating
|
||||
ad-hoc styling that someone then has to hunt down and consolidate.
|
||||
`Panel`/`StatusChip`/`Table`/`TextField`/`SelectField`/`Button` are the
|
||||
primitives that exist as of this writing, each with its own
|
||||
`/components` demo; `/components` always has the current, complete list
|
||||
— this doc won't try to keep a duplicate inventory in sync.
|
||||
|
||||
Default heuristic for *when* to promote page-scoped styling into a
|
||||
shared primitive: the day a second real page needs the same thing, not
|
||||
speculatively ahead of one. (Exception: when a peer explicitly asks for
|
||||
a primitive ahead of a second caller, as happened with the form kit —
|
||||
that's a judgement call each time, not a rule change.)
|
||||
primitives that exist; `/components` always has the current, complete
|
||||
list — this doc won't try to keep a duplicate inventory in sync.
|
||||
|
||||
**Every new `ui/` component gets a demo section on `/components` the
|
||||
same day it lands** — no primitive without a place to see it. One
|
||||
deliberate exception exists today: `FormField`, the internal label+
|
||||
control wrapper `TextField`/`SelectField` share, isn't itself a
|
||||
primitive a page reaches for directly, so it has no demo of its own —
|
||||
that's a real, considered exception (see its own doc comment), not an
|
||||
oversight this rule missed.
|
||||
a considered exception, not an oversight this rule missed.
|
||||
|
||||
## Attention
|
||||
|
||||
|
|
@ -182,15 +157,3 @@ oversight this rule missed.
|
|||
attention to where it actually matters (an error, a state change worth
|
||||
noticing) — not attention-optimized in the engagement/growth sense of
|
||||
maximizing time-on-page.
|
||||
|
||||
## Open questions
|
||||
|
||||
Tracked separately rather than asserted here as settled:
|
||||
|
||||
| Question | Tracked in |
|
||||
| --- | --- |
|
||||
| Light theme (palette + `prefers-color-scheme` default) | #3452 |
|
||||
| Client-local settings surface (page + storage) | #3453 |
|
||||
| Theme override setting | #3454 |
|
||||
| Reduced-motion override setting | #3456 |
|
||||
| PWA manifest / installable phone experience | not yet filed — mentioned in #3444, no concrete scope agreed |
|
||||
|
|
|
|||
Loading…
Reference in a new issue