Skip to content

feat: comprehensive dark theme overhaul#365

Merged
mmcky merged 11 commits intomainfrom
feature/dark-theme-overhaul
Feb 23, 2026
Merged

feat: comprehensive dark theme overhaul#365
mmcky merged 11 commits intomainfrom
feature/dark-theme-overhaul

Conversation

@mmcky
Copy link
Copy Markdown
Contributor

@mmcky mmcky commented Feb 19, 2026

Comprehensive Dark Theme Overhaul

A complete rewrite of the dark theme for a modern, consistent, and readable dark mode experience. The previous dark theme had numerous issues identified through a deep audit — this PR addresses all of them.

Before / After Summary

The old dark theme used an ad-hoc collection of ~35 CSS rules with inconsistent gray values (#222, #333, #444, #fff). This PR replaces it with a cohesive design system.

Color Palette

Role Old New
Body background #222 #1a1a2e (deep navy-charcoal)
Elevated surfaces #333 (everything the same) #252540 / #2d2d4a (visual hierarchy)
Primary text #fff (pure white, harsh) #d4d4e4 (soft white, reduced eye strain)
Links #fff (indistinguishable from text) #6cb6ff (clearly identifiable)
Borders #ccc (light mode leftover) #3a3a5c (subtle, dark-appropriate)

Critical Bugs Fixed

  • Tables: Row text was #333 (dark on dark) — now properly readable
  • Links: Were #fff, identical to body text — now distinct blue #6cb6ff with hover/visited states
  • Images: Aggressive invert(100%) broke photos/charts — now uses subtle opacity reduction
  • SVGs: Forced white fill/stroke broke multi-colored charts — now uses currentColor
  • Inline code: Light #cccccc dotted border on dark background — now #3a3a5c

Syntax Highlighting (NEW)

Previously only 3 of ~40 token types had dark mode colors. This PR adds a complete VS Code Dark+ inspired palette:

  • Keywords: Soft purple (#c586c0)
  • Strings: Warm orange (#ce9178)
  • Numbers: Light green (#b5cea8)
  • Functions: Yellow (#dcdcaa)
  • Builtins/Classes: Teal (#4ec9b0)
  • Comments: Muted blue-gray (#7c8a9e)
  • Variables: Light blue (#9cdcfe)

New Component Coverage

Components that previously had zero dark mode styling:

  • Modals (settings, download PDF) — full background, text, border, input styling
  • Admonitions — type-specific accent colors (warning=amber, danger=red, tip=green, important=blue)
  • Homepage elements — web-version cards, alternative links
  • Collapse/toggle bars — proper dark backgrounds and borders
  • Tippy tooltips — background, text, border, and arrow colors
  • Autodoc/API docs — function signatures, viewcode links
  • Dropdown details — borders and summary backgrounds
  • Footnotes — reference links and definition terms
  • Sidebar search area — was white-on-dark, now properly styled
  • Non-QuantEcon project overrides — link colors, borders adapt to dark mode
  • Toctree captions — dark text on dark background fixed

UX Improvements

  • No more FOUC: Added early dark mode injection script that applies dark-theme class before the page renders, eliminating the white flash
  • Better image handling: Replaced aggressive invert(100%) hue-rotate(-180deg) with subtle opacity reduction that preserves photo/chart colors
  • Toolbar QE logo: Applied brightness inversion filter for dark mode visibility
  • Stderr warnings: Updated to match new palette with semi-transparent backgrounds

Files Changed

Testing

  • npm run build compiles successfully
  • pre-commit run --all-files passes all checks
  • Visual testing recommended with a live Jupyter Book build

@codecov
Copy link
Copy Markdown

codecov bot commented Feb 19, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (main@5c371cf). Learn more about missing BASE report.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #365   +/-   ##
=======================================
  Coverage        ?   45.92%           
=======================================
  Files           ?        2           
  Lines           ?      405           
  Branches        ?        0           
=======================================
  Hits            ?      186           
  Misses          ?      219           
  Partials        ?        0           
Flag Coverage Δ
pytests 45.92% <ø> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 19, 2026

🎭 Visual Regression Test Results

passed  45 passed
skipped  1 skipped

Details

stats  46 tests across 1 suite
duration  1 minute, 2 seconds
commit  53eea76

Skipped tests

mobile-chrome › theme.spec.ts › Theme Features › f-string interpolation styling

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR implements a comprehensive dark theme overhaul for the QuantEcon Book Theme, replacing the previous ad-hoc collection of ~35 inconsistent dark mode CSS rules with a cohesive design system based on a well-defined color palette. The changes address multiple critical bugs (dark-on-dark table text, indistinguishable links, broken images/SVGs, poor inline code styling) and add comprehensive VS Code Dark+ inspired syntax highlighting for ~40 token types. A new FOUC (Flash of Unstyled Content) prevention script ensures the dark theme is applied before the page renders when dark mode is saved in localStorage.

Changes:

  • Complete rewrite of _dark-theme.scss (~550 lines) with organized sections for all UI components using a consistent 8-color palette
  • Added ~224 lines of dark mode syntax highlighting tokens in _code.scss with VS Code Dark+ inspired colors
  • Updated _stderr.scss dark mode colors to match the new palette
  • Added early-executing dark mode script in layout.html to prevent FOUC, plus dark mode overrides for non-QuantEcon projects

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 8 comments.

File Description
src/quantecon_book_theme/theme/quantecon_book_theme/layout.html Adds FOUC prevention script and non-QuantEcon project dark mode overrides for links, borders, and toctree captions
src/quantecon_book_theme/assets/styles/_stderr.scss Updates dark mode stderr warning colors from #ffc107 to #d4a017 with semi-transparent backgrounds matching new palette
src/quantecon_book_theme/assets/styles/_dark-theme.scss Complete rewrite with consistent color palette, organized sections for all components (toolbar, sidebar, tables, admonitions, modals, etc.)
src/quantecon_book_theme/assets/styles/_code.scss Adds comprehensive dark mode syntax highlighting palette for all Pygments token types using :where() for low specificity

Complete rewrite of the dark theme for a modern, consistent, and readable dark mode experience.

Color palette:
- Replace ad-hoc grays (#222/#333/#444) with a cohesive navy-charcoal palette
- Body background: #1a1a2e, Surfaces: #252540/#2d2d4a
- Text: #d4d4e4 (soft white, reduces eye strain vs pure #fff)
- Links: #6cb6ff (distinguishable from body text)
- Borders: #3a3a5c (subtle, consistent)

Syntax highlighting:
- Add complete dark mode token colors for all ~40 syntax classes
- VS Code Dark+ inspired palette
- Previously only 3 of ~40 tokens had dark overrides

Bug fixes:
- Fix table row text color (#333 on dark bg was unreadable)
- Fix links being indistinguishable from body text (all were #fff)
- Fix inline code having light border on dark background
- Fix sidebar search area remaining white in dark mode
- Fix toolbar border remaining light gray
- Fix image inversion being too aggressive (now uses subtle opacity)

New dark mode coverage:
- Modals, admonitions (type-specific accents), homepage elements
- Collapse/toggle bars, tooltips, anchor links, autodoc, footnotes
- Non-QuantEcon project color overrides, toctree caption text

UX improvements:
- Eliminate FOUC with early dark mode injection script
- SVG icons use currentColor instead of forced white
- Images use subtle opacity reduction instead of aggressive inversion
- Stderr warnings updated to match new palette
@mmcky mmcky force-pushed the feature/dark-theme-overhaul branch from 66774f4 to 063328d Compare February 19, 2026 06:43
- Flatten SCSS nesting to plain CSS in layout.html <style> tag (browsers can't parse SCSS)
- Add missing semicolon in .toctree-wrapper .caption-text rule
- Scope svg g selector to UI icon containers only (.qe-toolbar, .qe-sidebar, .topbar-main, nav) to avoid breaking matplotlib/plotly charts
- Remove duplicate .highlight rules (unreachable :where() block)
- Use strict equality (=== '1') in FOUC prevention script
@mmcky
Copy link
Copy Markdown
Contributor Author

mmcky commented Feb 19, 2026

/update-snapshots

@github-actions
Copy link
Copy Markdown
Contributor

✅ All visual snapshots have been regenerated and committed to this PR.

📦 Download snapshot-update-diff artifact to review before/after images.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 19, 2026

@github-actions github-actions bot temporarily deployed to pull request February 19, 2026 07:14 Inactive
@mmcky
Copy link
Copy Markdown
Contributor Author

mmcky commented Feb 19, 2026

This is a big step in the right direction for consistency.

  • FIX double logo issue in dark theme
Screenshot 2026-02-19 at 6 18 33 pm

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 13 changed files in this pull request and generated 2 comments.

Declare 16 CSS custom properties on body.dark-theme so downstream
projects can override palette colors without duplicating selectors:

  --qe-dark-bg, --qe-dark-surface, --qe-dark-surface-alt,
  --qe-dark-border, --qe-dark-text, --qe-dark-text-muted,
  --qe-dark-heading, --qe-dark-heading-top, --qe-dark-text-light,
  --qe-dark-link, --qe-dark-link-hover, --qe-dark-link-visited,
  --qe-dark-code-bg, --qe-dark-inline-code, --qe-dark-accent,
  --qe-dark-accent-dark

All ~120 hardcoded palette hex values replaced with var() references.
Semantic colors (admonition accents, modal button text) remain
hardcoded intentionally.

Docs updated with full reference table of available properties.
The :only-child fallback was matching .logo-img:only-child, but each
<img> is always the sole child of its own <a> wrapper, so it matched
even when a dark logo existed — showing both logos.

Fixed by checking :only-child on the <a> wrapper instead:
  p.logo > a:only-child > .logo-img

When a dark logo IS configured there are two <a> siblings inside
<p class="logo">, so a:only-child won't match and only the dark
logo is shown.

Fixes: double logo issue reported in PR #365
@mmcky
Copy link
Copy Markdown
Contributor Author

mmcky commented Feb 20, 2026

Fixed in ccdc837. The root cause was the :only-child fallback selector.

The bug: .logo-img:only-child was intended to detect "no dark logo configured, so invert the light one." But each <img> is the only child of its own <a> wrapper, so :only-child always matched — even when a dark logo existed. This re-showed the light logo alongside the dark logo.

The fix: Check :only-child on the <a> wrapper instead of the <img>:

// Before (buggy — always matches):
.logo-img:only-child { display: block; filter: invert(100%)... }

// After (correct — only matches when no dark logo <a> sibling exists):
p.logo > a:only-child > .logo-img { display: block; filter: invert(100%)... }

When a dark logo IS configured, the <p class="logo"> contains two <a> siblings, so a:only-child won't match and only the dark logo is shown.

The page header (title link, authors, 'Last changed' button) and the
changelog dropdown used colors.$body (#444) which is invisible on
the dark background. Added dark theme overrides for the full
.qe-page__header section:

- Title link → heading-top color
- Authors → primary text
- 'Last changed' button → muted text with accent border
- Changelog dropdown → dark surface background, proper borders
- Commit hash, author, time, message → appropriate text colors
Add entries for:
- CSS custom properties refactor (16 overridable --qe-dark-* vars)
- Double logo fix (only-child selector bug)
- Page header/changelog readability fix
@mmcky mmcky requested a review from DrDrij February 20, 2026 00:48
@github-actions github-actions bot temporarily deployed to pull request February 20, 2026 00:52 Inactive
The dark theme applied font-weight: 600 to .reference links, making
them visually heavier than in light mode. Color alone provides
sufficient contrast on dark backgrounds.
@github-actions github-actions bot temporarily deployed to pull request February 20, 2026 01:09 Inactive
@DrDrij
Copy link
Copy Markdown
Member

DrDrij commented Feb 23, 2026

Silky reading on iPhone after dark. Lovely theme addition.

@mmcky
Copy link
Copy Markdown
Contributor Author

mmcky commented Feb 23, 2026

thanks @DrDrij -- I did some research on contrast ratio's :-)

@mmcky mmcky merged commit 04d4895 into main Feb 23, 2026
10 checks passed
@mmcky mmcky deleted the feature/dark-theme-overhaul branch February 23, 2026 22:08
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