Skip to content

feat(canvas-kit): make the canvas follow the user's light/dark theme#20

Merged
jongio merged 1 commit into
mainfrom
jongio-canvas-theme-awareness
Jul 6, 2026
Merged

feat(canvas-kit): make the canvas follow the user's light/dark theme#20
jongio merged 1 commit into
mainfrom
jongio-canvas-theme-awareness

Conversation

@jongio

@jongio jongio commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Problem

Canvas extensions rendered dark even when the user's GitHub/app theme is light.

The host (github-app) already injects theme-aware Primer tokens onto the canvas document, but:

  1. Dark flash. It injects them in on_page_load (after first paint), and canvas-kit theme.css had dark-only fallbacks, so a light-theme user saw a dark flash on every open (and any non-app context stayed dark).
  2. Wrong inset token. --ck-bg-inset aliased --background-color-emphasis, which is a dark chip color in Primer light (#25292e). Every inset surface (chips, filter pills, tab-count badges, slider track, code viewer, Q&A, prompts) rendered as a dark box on white.
  3. Dark-tuned accents. code-tutor's --lvl-*/--q-*/category hexes and two rgba(0,0,0,.4) shadows were tuned for dark only.

Fix (kit-first, theme-aware)

canvas-kit/theme.css (all 6 vendored copies, synced from the create-canvas-app kit; bumped to 2026-07-05.1):

  • Derive --ck-bg-inset from the theme-aware --ck-bg-muted + --ck-fg instead of the wrong emphasis token. Verified: dark stays ~#363c43 (no regression), light becomes ~#d6d8db (a real recessed surface on white).
  • Add a prefers-color-scheme: light fallback + color-scheme, both gated on :root:not([data-color-mode]). The host sets data-color-mode alongside its tokens and explicit color-scheme, so these back off the instant it themes the canvas and the host stays fully in control. This kills the dark flash for light users and makes non-app contexts follow the OS scheme.
  • Theme-neutral skeleton shimmer (was a white-on-dark gradient invisible on light).

code-tutor: map --lvl-*/--q-* to semantic tokens and CATEGORY_META to Primer data tokens so hues track the theme; soften two dark-only shadows. The other canvases inherit the shared kit fix with no per-extension edits.

Validation

Booted the canvases over loopback and rendered them in Chromium with real injected token sets across every path:

  • Un-injected + OS light -> light (flash fixed)
  • Un-injected + OS dark -> dark (matches the original, no regression)
  • Injected light over OS-dark -> light (host wins when app theme differs from OS)
  • Injected dark inset resolves to ~#363c43 (unchanged)

node scripts/lint.mjs, node scripts/validate-extensions.mjs, and node scripts/run-tests.mjs all green (the suites include the "theme.css ships the reduced-motion guard" and "no em dashes" checks).

Companion change

canvas-kit is vendored from the create-canvas-app skill (jongio/skills). The same theme.css + version change lands there in a companion PR so the copies do not drift on the next kit sync.

The host injects its theme-aware Primer tokens only after first paint, and the
kit fallbacks were dark-only, so a light-theme user saw a dark flash. Worse,
--ck-bg-inset aliased --background-color-emphasis (a dark chip color in light
mode), which painted chips, filter pills, tab counts and the slider track as
dark boxes on a light canvas.

canvas-kit/theme.css (all 6 vendored copies, synced from the create-canvas-app
kit; bumped to 2026-07-05.1):
- Derive --ck-bg-inset from --ck-bg-muted + --ck-fg instead of the wrong
  emphasis token (dark stays ~#363c43, light becomes ~#d6d8db).
- Add a prefers-color-scheme:light fallback plus color-scheme, both gated on
  :root:not([data-color-mode]) so the host stays fully in control the moment
  it injects its tokens.
- Theme-neutral skeleton shimmer.

code-tutor: map --lvl-*/--q-* and category colors to semantic and data Primer
tokens so the hues track the theme; soften two dark-only shadows.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@jongio jongio merged commit 95a1dd6 into main Jul 6, 2026
3 checks passed
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