fix(theme): make all pages dark/light-mode compatible via design tokens#79
Merged
Conversation
Audited every route + component for theme compatibility. Many pages used hardcoded light colors, Tailwind dark: utilities (which track prefers-color-scheme, not the app's data-theme toggle), color-mix(… white), and several UNDEFINED 'phantom' tokens (--bg-surface, --bg-error, --border-error, --text-error, --red) — none of which respond to :root[data-theme='dark']. Converted surfaces/text/borders to var(--bg-*)/var(--text-*)/var(--border) and semantic accents to var(--success|accent|info|warning|error) (or rgba(var(--*-rgb), a)) across 30 files: settings, about, archived, hooks, commands, skills, plugins, tools, conversation, timeline, and shared components (TokenSearchInput, Switch, SegmentedControl, EmptyState, LiveSessions*, etc.). Replaced phantom tokens with real ones; merged a duplicate style= attribute on the skills page. Chart.js data-series colors and SVG brand marks left as literals. Verified at runtime in BOTH themes across 6+ representative pages: no light-surface-in-dark, no dark-surface-in-light, no new low-contrast text. npm run check: 0 errors. Pre-existing (not changed): --text-faint on raised cards is ~2.2:1 in dark mode app-wide (also on /sessions); candidate for a separate token a11y tweak. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
0629683 to
3ec8308
Compare
Review of the dark/light token pass surfaced two regressions: - hooks/scripts/[filename]: the no-highlight fallback <pre> was changed to text-[var(--text-primary)] while its container stays a hardcoded dark #0d1117 (the Shiki block is force-dark in both themes). In light mode --text-primary is near-black -> invisible code. Restored the fixed light literal (#e6edf3) so the always-dark block reads in both themes (verified 16:1 contrast). - skills/[skill_name]: the "Mentioned (not invoked)" bar segment and legend dots used var(--border-hover) (a 12-15% alpha border token) as a content fill, washing them out beside the solid category colors. Switched to var(--text-muted), a solid muted gray matching the original gray-500/50 intent, clearly visible in both themes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
App-wide audit + fix of dark/light theme compatibility across every route and component. Follow-up to #75 (which fixed
/shells+/cron); this extends the same design-token discipline to the rest of the app.The app themes via
:root[data-theme='dark']inapp.css. Several pages bypassed the design tokens and therefore did not respond to the theme toggle:#fff/white/#f5f5f4, near-black text, light borders,rgba(0,0,0,…).dark:utilities (e.g.text-emerald-600 dark:text-emerald-400) — there is nodark:custom-variant configured, so these trackprefers-color-scheme, not the app'sdata-themetoggle. They silently mismatch when the in-app theme disagrees with the OS preference.color-mix(… white)— mixed toward a literalwhiteinstead ofvar(--bg-base), so it didn't flip.--bg-surface,--bg-error,--border-error,--text-error,--redwere referenced but never defined inapp.css(rendered as invalid / light-only fallbacks).What changed (30 files)
Converted surfaces/text/borders to
var(--bg-*)/var(--text-*)/var(--border)and semantic accents tovar(--success|accent|info|warning|error)(orrgba(var(--*-rgb), a)so they flip). Replaced phantom tokens with real ones. Areas touched: settings, about, archived, hooks (+ scripts/event), commands, skills, plugins, tools, conversation, timeline, and shared components (TokenSearchInput,Switch,SegmentedControl,EmptyState,LiveSessions*,PluginCard,Archived*,ToolCallDetail, …).Intentionally left as literals: Chart.js data-series colors (charts can't read CSS vars at render), SVG brand/logo marks, and accent-on-accent button text (
text-whiteonvar(--accent)— valid contrast both themes).Verification
/,/settings,/skills/[name],/archived, plus/shells+/cron: no light-surface-in-dark, no dark-surface-in-light, no new low-contrast text.npm run check: 0 errors (15 pre-existing warnings).style=attribute introduced during the swap (skills invocation bars).Known / out of scope (pre-existing, not introduced here)
--text-fainton raised cards is ~2.2:1 in dark mode app-wide (also on/sessions) — a design-token a11y characteristic; candidate for a separate one-line token tweak.dark:prose-invert(markdown prose) still tracksprefers-color-schemerather than the toggle — would need a Tailwind@custom-variant darkmapped todata-themeto fully resolve.🤖 Generated with Claude Code