Skip to content

fix(web): colors and appearance classes come from theme tokens - #942

Merged
rynfar merged 3 commits into
pylonfrom
upstream/2026-09-30-web-theme-tokens
Sep 30, 2026
Merged

rynfar merged 3 commits into
pylonfrom
upstream/2026-09-30-web-theme-tokens

Conversation

@rynfar

@rynfar rynfar commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

Web components styled status tones with raw palette classes (text-amber-600 dark:text-amber-300, bg-sky-500, ...) and appearance values with arbitrary literals (text-[11px], text-[10px], ease-[cubic-bezier(...)], shadow-[...]). Raw colours ignore custom themes, and the literals bypass the type, motion and elevation scales. Upstream moved both onto theme tokens; Pylon had only taken the thread-status subset (#908).

Fix

Three commits, one per upstream source, for #865.

Source Upstream PR Disposition
315fcca10a826d8aa1cbdffc3ef5b5eb5a1e2f9d #13371 Partially adopted → now complete except the lint rule. Remaining chat, settings, pull request, Usage, device and preview hunks ported; thread-status hunks were already in #908.
f26ee083fe41720207fb10616359500dcecc19d3 #13397 Adapted. Token definitions ported verbatim; class substitutions applied hunk by hunk to Pylon's files; lint rule not ported.
ed809f7ad274ebccdfbf029ccfd7ff2582fd486a #13700 Adapted. Adds --text-4xs (8px) and --text-5xs (7px), line-height 1, registered with tailwind-merge; provider instance badges return to their pre-migration size.

Token definitions (apps/web/src/index.css, apps/web/src/lib/utils.ts)

  • --text-2xs (11px / 16px line) and --text-3xs (10px / 14px line), registered with tailwind-merge so cn() treats them as font sizes.
  • --ease-drawer, --shadow-composer, --shadow-composer-dark, --background-image-composer-seam-below/above.
  • --font-size-prompt-touch, --workspace-gutter, --workspace-gutter-start/end.
  • The prompt-stash-count-enter, snap-shot-contents-enter and provider-update-pill-countdown keyframes are removed; their three users now use starting: transitions (no remaining references).

Neither source touches mobile or any generated theme file, so nothing was regenerated.

How the class changes were applied

No file was taken from upstream. Each upstream hunk was applied only where Pylon's context matched exactly; every other hunk was re-targeted by hand or script onto the Pylon line carrying the same class, or skipped.

315fcca10a f26ee083fe
Upstream hunks 59 306
Applied with exact context 40 221
Re-targeted onto Pylon's line 8 73 (2 partial)
Already in Pylon (#908) 9 0
Skipped, code absent in Pylon 1 10
Lint config, not ported 1 2

Skipped as absent: the "Changed" stale label in PullRequestCodeTab and its two text-[11px] header lines; ComposerPromptEditorTiptap.tsx and ContextChip.tsx (files Pylon does not have, 5 hunks); the reasoning-trace stroke-[1.8] chevrons and one agent-spawn label in MessagesTimeline; the glass-surface badge in ProviderModelPicker. Partial: ComposerControl is structured differently in Pylon (it wraps Button), so only the rounded-(--control-radius) syntax change applies; the --control-icon-color removal does not.

Pylon-only code

The same substitutions were applied to Pylon-only components where the token is an exact equivalent: text-[10px] → text-3xs, text-[11px] → text-2xs, text-[12px] → text-xs, px-[calc(--spacing(2)-1px)] → px-1.75, leading-[1.125rem] → leading-4.5 (18 further files, e.g. SessionGoalControl, SessionInputQueueControl, providerUsage/*, PairingRouteSurface). Left alone: components/ui/* (upstream leaves these too), composerInlineChip.ts (text-[12px] on an inline chip, where a token line-height would change the line box), and non-exact literals (text-[9px], text-[13px], text-[.65rem], leading-[1.45]) that upstream did not touch on lines Pylon has.

Intentional visual changes (all from upstream)

  • Status colours now come from the theme: amber → warning, sky/blue → info, emerald → success, red → destructive; favourite star yellow-500 → warning; attachment badge fuchsia-500 → primary; quit-hold overlay neutral-700/white → foreground/background; provider radio hover zinc-50 → accent.
  • text-2xs/text-3xs carry a line-height (16px / 14px). Text that used a bare text-[11px]/text-[10px] without an explicit leading-* previously inherited its line-height.
  • Sizes snapped to the scale: text-[9px], text-[.6rem], text-[.65rem] → text-3xs (10px), matching upstream's final head for each of those lines. Former text-[7px] badges use text-5xs and former text-[8px] use text-4xs, so they do not change size. This includes the pull request author-initial avatar (pullRequestPresentation.tsx), which upstream's head renders at text-3xs; Pylon keeps its 8px there. text-[.7rem] → text-2xs (11px); text-[13px]/text-[0.8125rem] → text-sm or text-xs; text-[1.4rem] → text-2xl.
  • tracking-[0.08em] → tracking-widest (0.1em); tracking-[-0.005em] dropped; leading-[1.45] → leading-normal.
  • blur-[2px] → blur-xs (4px) on redacted text; rounded-[20px] → rounded-3xl; rounded-[5px] → rounded-sm; stroke-[1.8] → stroke-2; several one-off shadow-[...] → scale shadows.
  • Custom scrollbar colours use scrollbar-thumb-*/scrollbar-track-* on theme colours; citation chip focus outline and hover tint use theme colours.
  • Stash count, expanded capture swap and the provider-update countdown animate with starting: transitions instead of keyframes (one-shot, motion-reduce still disables them).
  • The macOS permission marks and the Computer Use mark moved into Icons.tsx (no visual change).

Exclusions

  • Upstream's shadcn/no-raw-colors and shadcn/no-arbitrary-values lint rules (vite.config.ts) are not ported: Pylon does not carry the @shadcn/lint plugin those rules come from, and adopting it is a separate dependency decision. Without the rule, Pylon-only code still holds some raw colours and arbitrary values.
  • No test enforcing token usage exists upstream in these sources.

Verification

Run on the rebased head:

  • vp run -F @t3tools/web typecheck: passed (exit 0).
  • Full web suite, cd apps/web && vp test run: 474 files, 6079 tests passed. Two assertions updated to follow their class (ProviderInstanceCard.test.ts, blur-[2px] → blur-xs, as upstream did; ProviderModelPicker.test.tsx, text-[7px] → text-5xs).
  • vp lint on the 131 changed files: 0 errors (warnings only, none from these class-name edits). vp fmt --check: clean.
  • 131 files changed across both commits.

Limits: no rendered-client pass was done. Surfaces worth a human look, in light, dark and one custom theme: chat composer (elevation, attached banners and the context strip seam, stash count, approval/user-input panels); messages timeline work log and changed-files tree; sidebar thread rows and the provider-update pill countdown; Settings → Diagnostics and resource telemetry tables; Settings → Providers (instance card, redacted text blur, add-provider dialog); Settings → Keybindings and Theme; pull request detail, summary, timeline and code tabs; Usage page and pooled limits legend; Agents panel; context-window meter popover; onboarding wizard.

Model: Claude Opus 5.5. Harness: Claude Code in Pylon. Workflow: review-t3-upstream skill.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL labels Sep 30, 2026
@rynfar
rynfar force-pushed the upstream/2026-09-30-web-theme-tokens branch from 7720f5e to ff211f1 Compare September 30, 2026 15:47
Ports the remaining chat, settings, pull request and Usage hunks of upstream
315fcca10a826d8aa1cbdffc3ef5b5eb5a1e2f9d (#13371). The thread-status subset
landed earlier in #908. Raw palette classes become semantic theme tokens so
status tones follow custom themes; the macOS permission and Computer Use marks
move into Icons.tsx. The upstream shadcn/no-raw-colors lint rule is not ported
because Pylon does not carry the @shadcn/lint plugin.
Ports upstream f26ee083fe41720207fb10616359500dcecc19d3 (#13397). Adds the
text-2xs/text-3xs sizes, the drawer easing, the composer shadow and seam tokens
and the workspace gutter variables, registers the new sizes with tailwind-merge,
and replaces arbitrary appearance values with those tokens and Tailwind's
scales. Upstream hunks were applied to Pylon's own versions of each file; the
same exact-equivalent substitutions were applied to Pylon-only components.
Three keyframes give way to starting-style transitions. The upstream
shadcn/no-arbitrary-values lint rule is not ported because Pylon does not carry
the @shadcn/lint plugin.
Ports upstream ed809f7ad274ebccdfbf029ccfd7ff2582fd486a (#13700). Adds the
text-4xs (8px) and text-5xs (7px) sizes and registers them with tailwind-merge,
so provider instance badges keep the size they had before the scale migration
snapped them to 10px. The pull request author-initial avatar, 8px in Pylon,
also uses text-4xs.
@rynfar
rynfar force-pushed the upstream/2026-09-30-web-theme-tokens branch from ff211f1 to 21ae282 Compare September 30, 2026 15:50
@rynfar
rynfar merged commit fb960a7 into pylon Sep 30, 2026
7 checks passed
@rynfar
rynfar deleted the upstream/2026-09-30-web-theme-tokens branch September 30, 2026 15:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant