Skip to content

fix(ui): use runtime :root color vars in shimmer gradient - #434

Open
Zerlight wants to merge 1 commit into
ruocheng/code-525from
ruocheng/code-575
Open

fix(ui): use runtime :root color vars in shimmer gradient#434
Zerlight wants to merge 1 commit into
ruocheng/code-525from
ruocheng/code-575

Conversation

@Zerlight

@Zerlight Zerlight commented Aug 8, 2026

Copy link
Copy Markdown
Member

Summary

The chat Shimmer gradient referenced var(--color-background) / var(--color-muted-foreground) — Tailwind v4 @theme inline names that never exist as runtime custom properties, so the whole background-image was invalid at computed-value time and the shimmer silently rendered with no colors in both themes. Switch to the :root/.dark vars coss-ui actually defines (--background, --muted-foreground), matching the existing color-mix(in oklab, var(--foreground) …) pattern in packages/presentation/ui/src/styles.css.

Swept packages/presentation/ui, packages/client/workbench, and both app renderers for other var(--color-*) usages — this was the only one.

Closes CODE-575

Verification

  • dev:mock webview, on a live Shimmer ("Running a command" during the showcase's streaming playback): computed background-image resolves to a white sweep over a muted-gray fill in light, and a near-black sweep over a lighter muted fill with the dark class toggled. Before the fix the computed value was none.
  • pnpm format:check, pnpm lint, pnpm typecheck clean; vitest run 2722 passed. The single git-mutations.test.ts failure is the signing-machine environment (production git commit path hits headless gpg pinentry) — the file passes 5/5 with GIT_CONFIG_GLOBAL=/dev/null.

Checklist

  • pnpm check:ci and pnpm test both pass (plus cargo fmt / clippy / test for Rust changes)
  • I ran the affected surface and observed the change working
  • If a wire message changed: WIRE_PROTOCOL_VERSION is bumped
  • New code and assets are my own work, or their origin and license compatibility are noted above
  • Docs and comments are updated where behavior changed

Copilot AI lite review requested due to automatic review settings August 8, 2026 14:20
@linear-code

linear-code Bot commented Aug 8, 2026

Copy link
Copy Markdown

CODE-575

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes the chat Shimmer text gradient by replacing references to Tailwind v4 @theme inline variables (--color-*, not available as runtime custom properties) with coss-ui’s runtime :root/.dark CSS variables (--background, --muted-foreground), ensuring the background-image computes correctly in both themes.

Changes:

  • Update Shimmer’s backgroundImage to use var(--background) and var(--muted-foreground) so the gradient no longer resolves to none at computed-value time.
  • Add an inline comment documenting why --color-* variables are not safe to use at runtime.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ The fix is correct and I verified the premise independently. One comment-accuracy nit inline, plus a stacking question below.

Reviewed changes — the single commit 8f7e4fb0, one file.

  • Shimmer gradient reads the :root varspackages/presentation/ui/src/chat/shimmer.tsx swaps var(--color-background) / var(--color-muted-foreground) for var(--background) / var(--muted-foreground) in the inline style.backgroundImage, and adds a one-line trap comment.

I confirmed the premise rather than taking it on faith, by compiling Tailwind 4.3.3 through its compile() API against a minimal repro of coss-ui's @theme inline block. The A/B was decisive: with no candidates the alias is not emitted; with a bg-muted utility candidate it is still not emitted (the value is inlined); only an arbitrary-value candidate like [background:var(--color-muted)] forces it into :root. A var(--color-*) written inside a JS inline style string is never a scanned candidate, so nothing forced --color-background to be emitted — the declaration was invalid at computed-value time and background-image fell back to none.

Worth recording that the blast radius was larger than "rendered with no colors": because the component itself sets bg-clip-text text-transparent, a background-image of none leaves nothing to clip, so every in-progress label was fully invisibletool.tsx:85, reasoning.tsx:92, activity-run.tsx:131,138, compaction-marker.tsx:42, terminal.tsx:46 all sit behind an isStreaming ? <Shimmer>x</Shimmer> : x ternary, so the text vanished while running and popped in on completion. Only the reduceMotion early-return branch was spared.

I also reproduced the sweep: var(--color- has no remaining non-vendor hits. The packages/vendor/coss-ui hits are correctly out of scope — --color-white / --color-zinc-* come from Tailwind's non-inline default @theme and are emitted normally, and skeleton.tsx:14's arbitrary value does force emission.

ℹ️ A standalone user-visible fix is gated behind an unmerged branch

The base is ruocheng/code-525, not master, and master still carries the broken string. Every streaming label in chat is invisible until this lands, so stacking it behind an unrelated agent-adapter branch delays a fix that has no dependency on that work.

Technical details
# Shimmer fix is stacked behind `ruocheng/code-525`

## Affected sites
- PR base ref — `ruocheng/code-525` (`a730f54f`), whose recent commits are opencode/MCP
  agent-adapter work unrelated to the shimmer gradient.
- `packages/presentation/ui/src/chat/shimmer.tsx` on `origin/master` — still has
  `var(--color-background)` / `var(--color-muted-foreground)`.

## Required outcome
- A conscious decision about whether this one-line fix should reach `master` on its own
  schedule rather than inheriting the parent branch's merge timeline.

## Open questions for the human
- Does this change actually depend on anything in `ruocheng/code-525`? If not, retargeting
  the base to `master` makes it mergeable immediately.
- If the stack is intentional (e.g. CODE-575 is scoped as a follow-up to CODE-525), no
  action needed — this is purely a sequencing observation.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using Claude Opus𝕏

{
backgroundImage:
'linear-gradient(90deg, transparent 35%, var(--color-background), transparent 65%), linear-gradient(var(--color-muted-foreground), var(--color-muted-foreground))',
// --color-* are @theme-inline-only (no runtime custom properties); use the :root vars.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only guard against someone reintroducing the bug, so it's worth making it exact — as written it over-generalizes twice. Tailwind's default palette --color-* (--color-white, --color-zinc-500) comes from a non-inline @theme and does exist at runtime, which is precisely what globals.css:68 relies on; and the @theme inline aliases are emitted when a Tailwind-scanned candidate references them (coss-ui's skeleton.tsx:14 uses [background:…var(--color-muted)…] and gets a real custom property). The actual invariant is that a JS inline style string is never scanned, so nothing forces the alias to be emitted.

Technical details
# Trap comment states the wrong invariant

## Affected sites
- `packages/presentation/ui/src/chat/shimmer.tsx:30` — "`--color-*` are @theme-inline-only
  (no runtime custom properties)" is false for Tailwind's default palette and false for
  `@theme inline` aliases that a scanned candidate references.

## Required outcome
- The comment should name the real rule: Tailwind emits a theme variable only when
  something **it scans** references it via `var()`; a JS inline `style` string is not a
  scanned candidate, so coss-ui's semantic `--color-*` aliases never materialize on
  `:root` for this call site. Keep it to the repo's 1–2 line comment budget.

## Suggested approach
- Apply the inline suggestion, or any wording that distinguishes "not emitted here" from
  "never exists".

## Verification performed
- Compiled `tailwindcss@4.3.3` via its `compile()` API against a minimal repro of
  `packages/vendor/coss-ui/src/styles/globals.css`:
  - no candidates → `--color-muted:` absent from output
  - candidate `bg-muted` → still absent (value inlined into the utility)
  - candidate `[background:var(--color-muted)]`**present** in `:root`
  - `--color-white:` / `--color-zinc-100:` → present (non-inline default `@theme`)
Suggested change
// --color-* are @theme-inline-only (no runtime custom properties); use the :root vars.
// coss-ui's semantic --color-* aliases are @theme inline and Tailwind never scans a JS
// style string, so they are not emitted to :root — read the underlying vars directly.

@lucas77778 lucas77778 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blocking findings. Independently verified the Tailwind 4.3.3 behavior: @theme inline utilities inline var(--background) / var(--muted-foreground) and do not emit the corresponding --color-* runtime declarations for this JS inline-style usage. Also confirmed coss-ui defines both replacement variables in :root and .dark, and both renderer entries import the shared stylesheet.

Checked the complete one-commit diff, all Shimmer call sites, reduced-motion behavior, applicable repository/frontend guidance, and current CI results. git diff --check is clean and all required GitHub checks are green. The non-master base affects sequencing only; it does not introduce a correctness dependency in this change.

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.

3 participants