Skip to content

fix(assistant): audit the surface against the ranui design standard - #284

Merged
chaxus merged 9 commits into
mainfrom
design/assistant-audit
Oct 18, 2026
Merged

chaxus merged 9 commits into
mainfrom
design/assistant-audit

Conversation

@chaxus

@chaxus chaxus commented Oct 18, 2026

Copy link
Copy Markdown
Member

Audits every first-party stylesheet against ran's packages/ranui/docs/DESIGN.md (§1–§12) and INTERACTION.md, weighted to the AI assistant. Nine commits, one per concern.

The assistant's behaviour layer already held up — transcript following, focus restoration, accessible names, failure copy. The defects were in the stylesheet, and in the checker that was supposed to be watching it.

The checker was not watching. semanticLiterals() matched padding-inline-start as padding-inline, so the : it required never arrived and the declaration was skipped. Logical properties are the form this repo writes, so the rule was blind where it mattered; three literal insets hid behind it. DESIGN §5 ("never animate a theme switch") had no mechanical owner at all, and twelve declarations were violating it — four of them bare durations, which mean all.

Assistant surface. The current conversation was painted with the hover fill while hover took the deeper active fill, so "you are here" read as "the pointer is here". Header icon targets were 30/28/32px in one row (34×40 below 480px against a 44px neighbour). Nineteen focus rings used three colours. Eight selectors were declared twice, with the dead copy still reading as intent. Plus an invented 3px radius, four light-only colour fallbacks, and a 20px inset fabricated as calc(space-4 + space-1) in three rules that must agree.

Both rules are now mechanical, and the audit log records the rendered measurements rather than a claim that it looks right.

Validation:

  • site-token-consistency 12/12 and design-contract 193/193; full unit suite green (6797) on a quiet machine.
  • ranui's verify:design: dark-unsafe-fallback and bare-colour clean. The remaining clamp() and pill-height reports are documented exceptions in docs/design-system.md.
  • agent-workspace-consistency E2E 4/4 against a production build.
  • Chromium at 1280×900: header controls all 32×32; current row #e6e6e6 vs hover #ebebeb; focus ring rgb(23,23,23) 2px; .cui-send transition none; theme flip #171717 → #ededed.

Evidence and the list of deliberate exceptions: docs/explorations/2026-10-18-assistant-design-audit.md.

The property pattern stopped at the first hyphen: `padding-inline-start` matched
as `padding-inline`, the `:` it required next never arrived, and the whole
declaration was skipped. Logical properties are the form this codebase actually
writes, so the rule was blind wherever it mattered.

Accept every hyphen in the class, assert the form in the unit contract, and
correct the three literal insets it surfaced: 12px and 8px in the assistant,
22px in the landing list.

Validation: site-token-consistency 12/12.
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Deploying document with  Cloudflare Pages  Cloudflare Pages

Latest commit: 3cc0460
Status: ✅  Deploy successful!
Preview URL: https://b7685271.document-7hm.pages.dev
Branch Preview URL: https://design-assistant-audit.document-7hm.pages.dev

View logs

CSS cannot tell why a colour changed, so a palette property in a transition also
fades when the theme flips its token: each surface lands at its own duration
while the page around it snaps. DESIGN §5 bans the default and nothing was
checking it.

`paletteTransitions()` judges each comma-separated transition by its first
token — a timing value there means the property was omitted, i.e. `all` — and
the unit contract runs it over every authored stylesheet and every freshly
generated page. A lone `var(--…-transition)` stays the opt-in hook.

It found twelve declarations in five files. Four were bare durations
(`transition: 0.15s ease`, which is `all`) on the home and landing navigation;
eight named palette properties only. Every hover and focus now snaps, which is
also what §5 asks of frequent feedback.
The row marked `aria-current` was painted with the hover fill, and `:hover`
painted the deeper active fill on top of it. The persistent state therefore
shared the transient one's colour and lost to it on hover: "you are here" read
as "the pointer is here".

Hover now takes `--ran-color-bg-hover` and the current row takes
`--ran-color-bg-active`, declared after the hover rule at equal specificity so
hovering the current conversation keeps the stronger fill.
The header is one row, so unequal boxes read as misalignment rather than as
hierarchy. The gear, quote and close controls were 30px, the quote 28px and the
clear button 32px; below 480px the buttons became 34x40 while clear and quote
stayed 44px.

All icon-only header controls now take `--ran-size-7` and grow together to
`--app-control-touch` on coarse pointers; the per-width geometry is gone.

Two declarations that the shared header rule already outranked are removed with
it: `.agent-panel-close` claimed `color: text-disabled` — a disabled-looking
close button — and the gear declared `margin-left/right` and then `margin: 0`.
Nineteen `:focus-visible` rules used three different colours: primary twelve
times, `--ran-color-link` five, `--ran-blue-700` twice. Two of the link rules
also carried a light-only `#0070f3` fallback.

DESIGN §7 allows either the `--ran-focus-ring` shadow or an outline in the
primary colour. The outline form was already the majority, so every ring is now
`2px solid var(--ran-color-primary)` with the same 2px offset.
`var(--ran-color-border, #ddd)` and `var(--ran-color-primary, #2563eb)` keep
their light value when the token is missing, so a missing token would paint a
light border and a blue ring in dark mode. Both now fall back to a foundation
role that flips with the theme.

The `#2563eb` case was worse than a light-only literal: it also named a blue
that the monochrome primary never takes, so the fallback misrepresented the
token it stood in for.
… inset

Eight selectors were declared twice in this file. The later block silently won,
so the earlier `font-size: 20px` on the empty state, the flex row on its
actions, the `flex-basis` on the welcome hint, the 96px fixed language lane and
two scroll caps were dead code that still read as intent — the next person to
change one of them would have edited the copy that does nothing.

Each is now a single block, verified by comparing the effective declaration map
per selector before and after: only the three intended value changes moved.

The 20px inset shared by the model status, readiness and write-destination
lines was `calc(space-4 + space-1)` in three places that must agree. It is
named once on `.agent-panel` as `--agent-composer-inset`, because it is the
footer padding plus the composer's own padding — the status text aligns to the
composer's text, not its edge.
`calc(var(--ran-radius-sm) / 2)` produced a 3px corner that exists nowhere else
in the product, and `min-height: 40px` sat between the compact and page action
sizes without belonging to either. Both now come from the existing scales.

`margin: 0.5rem 0` was a spacing decision hiding as a rem; the citation
marker's `0.15em` is genuinely optical — it has to scale with the glyph — so it
became one named local token instead of an anonymous inset.
The audit log states what was found, what was fixed and what was deliberately
left alone, with the rendered measurements rather than a claim that it looks
right. `docs/design-system.md` gains the two rules that are now mechanical —
logical properties count as spacing, and a palette property never appears in a
transition — because both fail silently in review.
@chaxus
chaxus force-pushed the design/assistant-audit branch from 0d2d5c3 to 3cc0460 Compare October 18, 2026 12:28
@chaxus
chaxus merged commit d8ce247 into main Oct 18, 2026
19 checks passed
@chaxus
chaxus deleted the design/assistant-audit branch October 18, 2026 14:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant