Skip to content

feat: system-aware color mode with browser-mode tests#2

Merged
rqbazan merged 7 commits into
mainfrom
feat/system-color-mode
Jun 28, 2026
Merged

feat: system-aware color mode with browser-mode tests#2
rqbazan merged 7 commits into
mainfrom
feat/system-color-mode

Conversation

@rqbazan

@rqbazan rqbazan commented Jun 27, 2026

Copy link
Copy Markdown
Member

Summary

  • Bug fix — system mode now follows the OS. Both useColorMode (src/index.ts) and the inline pre-paint script (src/initial.ts) resolve system against matchMedia("(prefers-color-scheme: dark)"). The hook also tracks OS changes live while in system mode. Previously system always rendered light, because the apply step only checked for an explicit dark value and fell through to removing the class otherwise.
  • Integration tests in a real browser. New suite under test/functional runs via Vitest Browser Mode + Playwright (headless Chromium), covering both entry points: the npm hook and the inline IIFE script.
  • Tooling & docs. Biome, tsdown (lib + IIFE build), tsconfig, Vitest browser config, CI workflows, and a rewritten README documenting usage, styling, and the window.__COLOR_MODE__ runtime contract.

The bug

if (mode === COLOR_MODE.DARK) {
  document.documentElement.classList.add("dark");
} else {
  document.documentElement.classList.remove("dark"); // ← system always landed here
}

A user on system with an OS dark preference saw the light theme. The same gap existed in initial.ts for a persisted system value (the matchMedia branch only ran on first visit). Both sites now resolve system via prefers-color-scheme.

Note: the inline script's first-visit default is now system (resolved against the OS) instead of baking a concrete dark/light into storage — so system keeps following the OS over time.

Tests

  • 18 tests / 2 files, all passing in headless Chromium.
  • Hook: init from localStorage, invalid-value fallback + console.error, setMode side effects (class / localStorage / CustomEvent), and system following the OS both statically and on a live change.
  • Inline script: explicit light/dark, persisted system + OS dark→dark / light, first-visit defaults, unavailable media query, and the window.__COLOR_MODE__ contract. The side-effectful module is re-evaluated per case via a cache-busting dynamic import (vi.resetModules() does not re-run native modules in Browser Mode).

Run locally with pnpm test.

🤖 Generated with Claude Code

rqbazan and others added 4 commits June 27, 2026 18:00
useColorMode and the inline pre-paint script now resolve "system" against
the OS prefers-color-scheme, and the hook tracks OS changes live while in
system mode. Previously "system" always rendered light because the apply
step only checked for an explicit "dark" value.

Add functional tests under test/functional that run in a real browser via
Vitest Browser Mode + Playwright, covering both entry points: the npm hook
(src/index.ts) and the inline IIFE script (src/initial.ts).

Set up project tooling (Biome, tsdown lib + IIFE build, tsconfig, Vitest
browser config, CI workflows) and document usage, styling, and the
window.__COLOR_MODE__ runtime contract in the README.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Install Chromium via `playwright install --with-deps` before the test step
so the browser-mode functional suite can run in CI. Switch the release
workflow trigger from pull_request events to push on main.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vland-bot

vland-bot Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Preview release

Latest commit: 3eeea85

Some packages have been released:

Package Version Install
@vlandoss/theme-toggle 0.0.1-git-3eeea85.0 @vlandoss/theme-toggle@0.0.1-git-3eeea85.0

Note

Use the PR number as tag to install any package. For instance:

pnpm add @vlandoss/theme-toggle@pr-2

useColorMode now returns { colorMode, setColorMode } instead of
{ mode, setMode }. Update the hook internals, the functional tests, and
the README usage example accordingly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Jun 27, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 3eeea85

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@vlandoss/theme-toggle Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

rqbazan and others added 2 commits June 27, 2026 18:44
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@rqbazan rqbazan merged commit dd42ff8 into main Jun 28, 2026
2 checks passed
@github-actions github-actions Bot mentioned this pull request Jun 29, 2026
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