Skip to content

fix(ui): align chrome, scrims and modal text to RBX tokens - #276

Open
tyreseluo wants to merge 6 commits into
mainfrom
fix/timeline-chrome-tokens
Open

fix(ui): align chrome, scrims and modal text to RBX tokens#276
tyreseluo wants to merge 6 commits into
mainfrom
fix/timeline-chrome-tokens

Conversation

@tyreseluo

@tyreseluo tyreseluo commented Jul 29, 2026

Copy link
Copy Markdown

Colour-only work: six commits, each reviewable on its own. No behaviour changes.

Why

The surfaces the user looks at most were drawn from one-off literals that matched nothing else in the app, so the same concept — selected, hovered, dimmed, muted text, "this is a bot" — rendered differently depending on which file it lived in.

What changed

Timeline chrome. Reaction chips hovered #fef65b highlighter yellow with pure-black text and a bespoke green/grey pair; they now use the accent pair the app already uses for selection. Mention pills drop the black pill (and the #d91b38 red for self-mentions) for two tiers of the same accent — quiet chip for others, filled for you or @room. Links were browser-default blue and turned green on hover (shared by message links, settings and previews), so RBX_LINK_HOVER is added once rather than patched three times. Unread badges keep the conventional red but take RBX_DANGER_FG instead of pure #FF0000, and "marked unread" moves off the logo cyan.

Scrims, selection, modal text. Overlays dimmed at three different values (RBX_SCRIM, #000000BB, #000000b2) — all five backdrops now share one. The autocomplete highlighted its selected row in dodger blue while floating over the teal composer. room_settings_modal.rs wrapped tokenised chrome around 19 literals including five levels of text grey; it now has zero hardcoded colours.

Sticker picker and media players. Three files drew from a Tailwind palette with no RBX reference at all — 56 literals → tokens, including the players' #ff4444 error red. The sticker picker's primary button also leaves the deprecated legacy blue.

Bot badge. One concept had four definitions and three appearances: solid legacy-blue block in the rooms list and room title, soft accent chip in the message header, capitalised "Bot" in the member list. All now match the timeline chip. (The rooms-list pill's comment claimed it "reproduces the timeline's bot badge look" while drawing solid blue.)

Bot card and code paths. The agent card used seven hand-picked blue-greys, each within ~2% of a real token — the near-miss that made it read as faintly "off" against the approval card nested inside it. Separately, a bot's inline code changed shade between messages depending on whether the body contained a fenced block (markdown widget, blue-tinted) or not (HTML widget, neutral grey); both now use RBX_BG_SUNKEN. Expanding a small-state group also shifted its summary 7px left, now aligned.

One regression, caught and fixed in-branch

Pointing four styles.rs colours at RBX_* looked correct and compiled clean, but shared/mod.rs registers styles before design_tokens, so the names did not exist yet:

[E] src/shared/styles.rs:216 - property RBX_BG_SURFACE not found in prototype chain

They fell back to a grey default, turning day dividers, small state events and the "new message" marker into grey blocks. cargo check passes either way — it only surfaces in the running app's log. Reverted to literals mirroring the token values, with a comment recording why they must stay literal. Every other file in this branch registers after design_tokens, so their token references are fine; styles.rs is the only module with this hazard.

Testing

cargo test --lib --features agent_chat — 579 pass. Ran the app against a live agent-chat room and stepped through reaction hover/selected, self vs other mentions, link hover, unread badges, all five overlays, the autocomplete popup, the settings and sticker modals, audio/video messages, bot badges on all four surfaces, and the small-state group toggle. Confirmed from the app log that no RBX_* property fails to resolve.

Deliberately not included

  • Legacy blue migration. COLOR_ACTIVE_PRIMARY has ~43 call sites, but design_tokens.rs states blue is "migrated per surface as §5 refactors land". Only the bot-badge surface is migrated here; a global flip is the maintainer's call.
  • Three genuine defects, better as their own PR than mixed into colour work: folding can trigger mid-stream and swallow the typewriter cursor (regression from feat(timeline): make long agent replies scannable #274); link_preview.rs slices description by byte offset and panics on mixed CJK/ASCII; populate_message_view resets bot-card visibility on the Text/Notice path only, so a recycled slot can show a previous bot reply's body under a redacted or image message.

🤖 Generated with Claude Code

tyreseluo and others added 6 commits July 29, 2026 13:07
The most-seen chrome in the timeline was drawn from one-off literals that
matched nothing else in the app.

- Reaction chips: hover was `#fef65b` highlighter yellow, text pure black, and
  the reacted/unreacted pairs were a bespoke green/grey. They now use the accent
  pair the rest of the app already uses for selection, and hover tints 20%
  toward the accent instead of flashing yellow.
- Mention pills: replace the black pill (and the `#d91b38` red used when it
  mentions you) with two tiers of the same accent — a mention of someone else is
  a quiet soft chip, a mention of you or @room is filled. Both branches write
  fill *and* label colour so a pill reused after an edit cannot keep the
  previous emphasis.
- Links: `#x0000EE` was the browser default blue, and hovering any link turned
  it green (`#21B070`) — shared by message links, settings and previews. Add
  `RBX_LINK_HOVER` (same hue, darkened like ACCENT → ACCENT_HOVER) and point all
  three at the tokens.
- Unread badges: mentions keep the conventional red but take the system's
  `RBX_DANGER_FG` rather than pure `#FF0000`, the most saturated pixel in the
  app; "marked unread" moves off the logo cyan to the functional accent, since
  the brand ramp is reserved for brand entry points.

`styles.rs` declares these colours twice (DSL + Rust); both sides now reference
the tokens so they cannot drift apart.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Modal scrims came in three values: `RBX_SCRIM` (navy 50%) in two menus, but
  `#000000BB` in search / room info / user profile and `#000000b2` in the
  loading pane, so dimming visibly changed depth depending on which overlay you
  opened. All five are `bg_view := SolidView` backdrops; they now share
  `RBX_SCRIM`.
- The @/slash autocomplete highlighted its selected row in dodger blue
  (`#x1E90FF30`) while every other selected row in the app uses
  `RBX_BG_SELECTED` — and the popup floats directly over the teal composer.
- `room_settings_modal.rs` wrapped RBX-tokenised chrome around 19 hardcoded
  literals, including five levels of text grey (`#000/project-robius#333/project-robius#444/project-robius#666/project-robius#888`)
  sitting next to tokenised titles. Those collapse onto the three RBX text
  levels, and the panel/button fills onto the surface tokens; the file no longer
  contains a hardcoded colour.
- `COLOR_PRIMARY_DARKER` was a stray `#fefefe` belonging to no ramp, which made
  a room's Chat tab a different white from its Info tab. It is now an alias for
  `RBX_BG_SURFACE`; all ten uses are near-white panels or borders, so the 0.4%
  shift is invisible in place while removing the last off-ramp white.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Three files drew from a Tailwind-style palette with no RBX reference at all, so
they read as panels bolted on from another app: the sticker picker sat on
gray-100 with gray-900 text and gray-200 rules, and the audio/video players
paired near-black controls with a cool grey chrome next to the warm navy of
everything around them.

- `sticker_modal.rs`: 28 literals → tokens. Text collapses onto the three RBX
  levels, panel/rule fills onto the surface and stroke tokens, and the error
  line onto `RBX_DANGER_FG`. Its primary button also moves off the deprecated
  legacy blue to `RBX_ACCENT`, per the note in design_tokens.rs that new UI must
  use the accent. Two hover washes reuse the existing `RBX_HIT_HOVER`.
- `audio_message_player.rs` / `video_message_player.rs`: 28 literals → tokens,
  including the players' `#ff4444` error red onto `RBX_DANGER_FG`.

None of the three now contains a hardcoded colour.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The same "this is a bot" concept had four definitions and three appearances, so
one agent looked like a different thing depending on where you saw it: a solid
legacy-blue block in the rooms list and the room title, a soft accent chip in
the message header, and a capitalised "Bot" in the member list.

Both blue pills move to the soft accent chip the timeline already uses, and the
member-list label is lowercased to match. The rooms-list pill's comment claimed
it "reproduces the timeline's bot badge look" while drawing solid blue — it now
actually does, and the comment says why it must.

Leaves the wider legacy-blue deprecation alone: design_tokens.rs states that
blue is "migrated per surface as §5 refactors land", and the bot badge is one
such surface. The other ~40 call sites are not touched here.

The source-assertion test in rooms_list_entry.rs guards the pill's `new_batch`
DrawList structure, which is unchanged; the full suite (579 tests) passes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
An earlier commit in this branch pointed four `styles.rs` colours at `RBX_*`
tokens. `shared/mod.rs` registers `styles::script_mod` *before*
`design_tokens::script_mod`, so those names did not exist yet and every one of
them failed to resolve at runtime:

    [E] src/shared/styles.rs:216 - property RBX_BG_SURFACE not found in prototype chain
    [E] src/shared/styles.rs:238 - property RBX_DANGER_FG not found in prototype chain

The properties fell back to a grey default, which is what turned the day
dividers, small state events and the "new message" marker into grey blocks.
`cargo check` passes either way — this only shows up in the running app's log,
which is why it was missed.

Restore literals mirroring the token values (`#ffffff`, `#C5392F`, `#119FB3`,
`#8A98AE`) and record *why* they must stay literal, so the next reader does not
"fix" them back. The Rust consts in the same file have no ordering constraint
and keep referencing the tokens directly, which ties the two sides together.

Every other file touched in this branch registers after design_tokens
(shared/mod.rs ≥48, home/, settings/, profile/), so their token references are
fine; styles.rs is the only module with this hazard.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- The agent card was drawn from seven hand-picked blue-greys (`COLOR_BOT_*`),
  each within ~2% of a real token. That near-miss is exactly what made the card
  read as faintly "off" against the approval card and every other surface nested
  inside it. They are now aliases onto the token layer.
- A bot's inline `code` and quotes changed shade between messages: a body
  containing a fenced block renders through the markdown widget (blue-tinted
  `#EFF5FB`), everything else through the HTML widget (neutral `#EDEDED`). Both
  now use `RBX_BG_SUNKEN`, so the same author's code looks the same either way.
- Expanding a small-state group shifted its summary text 7px left: the collapsed
  `SmallStateEventsSummary` pads 50, while the expanded `group_header` sits
  inside a `body` that already pads 7, totalling 57. The header now pads 43 so
  both land on 50.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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