Skip to content

feat: dark mode and a theme toggle in the generated viewer - #14

Open
DanielMontilla wants to merge 2 commits into
leji-org:mainfrom
DanielMontilla:feat/darkmode
Open

feat: dark mode and a theme toggle in the generated viewer#14
DanielMontilla wants to merge 2 commits into
leji-org:mainfrom
DanielMontilla:feat/darkmode

Conversation

@DanielMontilla

@DanielMontilla DanielMontilla commented Aug 31, 2026

Copy link
Copy Markdown

Summary

Adds dark mode to the generated Docsify viewer (leji view / leji viewer build), with a theme toggle that defaults to the OS scheme and persists the reader's choice.

  • The effective theme is resolved to <html data-theme> before first paint by a new vendored theme-init.js (head script, CSP-safe), so there's no wrong-theme flash; the dark palette lives in a single :root[data-theme='dark'] block.
  • vue.css re-values the --leji-* tokens for dark and overrides the stock theme's Prism tokens, tables, tip box, search-plugin borders, and the zoom overlay. The layer's own accent (viewer.theme.primary) is left as authored in both modes.
  • viewer-boot.js resolves system → light → dark (in-memory when localStorage is blocked), re-themes mermaid on toggle, and falls back to matchMedia.addListener for older engines.
  • viewer-contrast.test.ts gains an arithmetic guard for the dark palette. All three SDKs ship byte-identical copies (npm run assets); golden export manifests regenerated.

Screenshots

Light (system):

Light overview

Dark (system):

Dark overview

Dark — code + blockquote:

Dark invariants

Dark — table:

Dark glossary

Manual toggle → dark (pill shows 🌙 Dark):

Toggle dark

Verification

  • Node SDK suite: 976 pass (one pre-existing flaky timing test in preflight.test.ts, fails without these changes too)
  • Go conformancetest + commands/export: pass
  • Python test_units + test_export: 97 pass
  • viewer-tones / viewer-contrast (now incl. dark palette): pass
  • npm run assets:check: in sync

Daniel Montilla added 2 commits August 31, 2026 19:41
The Docsify viewer (leji view / leji viewer build) follows the OS scheme
by default and offers a fixed pill that cycles system -> light -> dark and
persists the choice in localStorage.

- A new vendored theme-init.js runs in <head> before first paint, writing
  the effective theme to <html data-theme> so there is no wrong-theme
  flash; the dark palette lives in one :root[data-theme='dark'] block.
- vue.css re-values the --leji-* tokens for dark and overrides the stock
  theme's Prism tokens, tables, tip box, search plugin borders and the
  zoom overlay; the layer's own accent is left as authored in both modes.
- viewer-boot.js resolves system|light|dark (in-memory when localStorage
  is blocked), re-themes mermaid on toggle, and falls back to
  matchMedia.addListener for older engines.
- viewer-contrast.test.ts gains an arithmetic guard for the dark palette.
  All three SDKs ship byte-identical copies (npm run assets) and the
  golden export manifests were regenerated.

Signed-off-by: Daniel Montilla <daniel@montilla.dev>
Signed-off-by: Daniel Montilla <daniel@montilla.dev>
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