Skip to content

Add off-by-default provider marks to sidebar thread rows - #452

Merged
Tryanks merged 6 commits into
mainfrom
feat/provider-colors
Sep 16, 2026
Merged

Tryanks merged 6 commits into
mainfrom
feat/provider-colors

Conversation

@Tryanks

@Tryanks Tryanks commented Sep 16, 2026

Copy link
Copy Markdown
Owner

Summary

Every provider now has a color, and an opt-in Provider marks switch (Settings → General → Appearance, off by default) draws each thread's provider logo in that color at the right edge of its sidebar row. The mark is decorative only: it fits inside the row (row height − 8px), sits under the row's content, takes no input, and leaves the row's rest / hover / selected / semantic surfaces exactly as they were.

Changes

  • Color ownership in core. crates/core/src/provider_colors.rs holds the four built-in brand colors (Claude #D97757 Anthropic Clay, Codex #8B5CF6, pi #4D9ABF from its logo, OpenCode #22A06B) and a ten-hue palette for everything the user adds. Settings::provider_color(key) resolves a card's accent_color first, then the brand color, then a palette slot chosen by a stable FNV-1a hash of the key with collision bumping across the configured user profiles and ACP agents, so known providers never share a color while the palette has room and no assignment has to be persisted. SessionMeta::provider_color_key derives the key from a non-built-in profile_id, else acp:<agent id>, else the built-in provider key.
  • One owner for the brand color. CLAUDE_BRAND_COLOR in the UI is gone; provider_glyph and the composer's favourite star read builtin_provider_color. ProviderSettings::accent_rgb is the single #rrggbb parser, and the store's provider_profile_accent now calls it.
  • Sidebar mark. provider_mark in sidebar.rs renders the glyph (provider_glyph for native kinds, the ACP box for agents) at PROVIDER_MARK_ALPHA 0.32 in a right-aligned square box, attached to the grouped, flat (parent and child) and compact row shapes.
  • Setting. Settings::sidebar_provider_marks (#[serde(default)], legacy files → off), SettingsPatch::SidebarProviderMarks, store intent, toggle row with reset action, settings.sidebar_provider_marks strings in en.yml and zh-CN.yml. Restore defaults turns it off.
  • Docs. docs/DESIGN.md Sidebar and Settings sections describe the mark contract and the switch.

Test plan

  • cargo fmt --all --check
  • cargo clippy --workspace --all-targets --locked -- -D warnings
  • cargo test -p tcode-core -p tcode-ui -p tcode-runtime --locked (136 / 422 / 174 passed) — new: palette determinism and distinctness, accent-over-brand precedence, color key resolution, default-off + patch, reset clears the switch, locale parity, and a GPUI sidebar test that enables the switch through the store, asserts both marks sit inside their rows and the active row still paints list_active, then disables it and asserts the marks are gone.
  • cargo build --workspace --locked
  • Launched the desktop app against a throwaway TCODE_DATA_DIR copy of a real session index; screenshots of flat and grouped layouts in light and dark confirmed Codex and Claude marks are distinguishable and the row surfaces are unchanged.

Every provider now has a color: built-in profiles carry a hand-picked
brand color and every user-added provider (custom profiles, ACP agents)
takes a slot from a fixed palette. Slots come from an FNV-1a hash of the
thread's provider color key, with known custom providers walked in
sorted order and bumped past collisions, so colors are deterministic
across devices without persisted state and configured providers never
share a color while the palette has room.

With the new default-on "Provider colors" switch (Settings → General →
Appearance, stored inverted as `provider_colors_disabled`), wide thread
rows use the provider hue at three alpha steps (rest 0.08, hover 0.16,
active 0.26) and compact rows take the resting wash under the existing
selected surface and semantic washes. Off restores the neutral rows.

Owners: `Settings::provider_color` / `crates/core/src/provider_colors.rs`
for assignment, `SessionMeta::provider_color_key` for the key, and
`WorkspaceStore::provider_color` for the setting-gated read.
`ProviderSettings::accent_rgb` is now the one parser of the card's
`#rrggbb` accent; `WorkspaceStore::provider_profile_accent` and
`Settings::provider_color` both call it, so a user-set accent wins over
the brand color and the palette for that profile's rows. ACP keys are
not profile ids and keep their palette slot. zh-CN wording follows the
locale's 提供方 term for provider.
Thread rows return to their neutral rest, hover, selected and semantic
surfaces. With Provider colors on, every row shape (grouped, flat parent
and child, compact) instead paints its provider's glyph under the
content: ~1.25x the row height, vertically centred, hanging 6px past the
right edge so the row's clip cuts it, in the provider color at 0.14
alpha. The mark has no handlers; ACP agents use the box glyph the rail
and ACP panel already use.

The Claude brand color now lives only in core: `provider_glyph` and the
favorite star read `builtin_provider_color` instead of a UI constant.
The glyph is now sized to the row height minus an 8px inset, vertically
centred and right-aligned inside the row's own horizontal padding, so
nothing overhangs and rows keep their original (unclipped) overflow.
Alpha rises to 0.18 to compensate for the smaller mark.
Raise the mark's alpha from 0.18 to 0.32 so the fitted glyph reads on
both canvases.
`provider_colors_disabled` becomes `sidebar_provider_marks: bool`
(`SettingsPatch::SidebarProviderMarks`), absent in legacy files → off.
The General row is "Provider marks", non-inverted, with its reset action
shown while on. Color assignment (accent → brand → palette) is untouched.
@Tryanks
Tryanks merged commit 5ba1650 into main Sep 16, 2026
6 checks passed
@Tryanks
Tryanks deleted the feat/provider-colors branch September 16, 2026 13:37
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