From cdb5057618af93ae7c206b9993c622d6372fbab2 Mon Sep 17 00:00:00 2001 From: "Ricardo Q. Bazan" Date: Sun, 18 Oct 2026 07:34:54 -0500 Subject: [PATCH 1/3] chore: name rcrd in the LICENSE Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01XRCpaD5QTPJsEjnhikoV2S --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 3f5ef46..f65a6b1 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2026 Ricardo Q. Bazan +Copyright (c) 2026 rcrd Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 0374fcd62c3cac47c1884845252769855e50b868 Mon Sep 17 00:00:00 2001 From: "Ricardo Q. Bazan" Date: Sun, 18 Oct 2026 07:34:54 -0500 Subject: [PATCH 2/3] docs: restructure the README and add the contributing and development guides The README takes the structure of a Project in its own repository: the name links to the Project page, Install states the React requirement, and the Development section moves to docs/development.md. Contributing links both guides, License takes the Project form, and the Signature closes the page. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01XRCpaD5QTPJsEjnhikoV2S --- .changeset/readme-structure.md | 5 +++ README.md | 72 ++++++++++++++-------------------- docs/contributing.md | 25 ++++++++++++ docs/development.md | 33 ++++++++++++++++ 4 files changed, 92 insertions(+), 43 deletions(-) create mode 100644 .changeset/readme-structure.md create mode 100644 docs/contributing.md create mode 100644 docs/development.md diff --git a/.changeset/readme-structure.md b/.changeset/readme-structure.md new file mode 100644 index 0000000..d53d202 --- /dev/null +++ b/.changeset/readme-structure.md @@ -0,0 +1,5 @@ +--- +"@variablelab/theme-toggle": patch +--- + +Restructure the README, with the name linked to the Project page and the development notes moved to the repository's development guide, and name `rcrd ` in the LICENSE. diff --git a/README.md b/README.md index c34b71b..28da498 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,33 @@

- +

-

theme-toggle

+

theme-toggle

The theme is set before first paint.

-Light/dark/system color-mode toggle for React apps, with a tiny inline script that -sets the theme **before first paint** to avoid the flash of the wrong theme (FOUC). +Light, dark and system color modes for React apps. A blocking script in `` puts the `dark` class on `` from the stored mode, and the `useColorMode` hook reads and changes it. -- Three modes: `light`, `dark`, and `system` (defaults to `system`). -- `system` resolves against the OS `prefers-color-scheme` and tracks it live. -- Persists the user's choice in `localStorage`. -- Applies a `dark` class on `` so you can style with plain CSS. -- Emits a `CustomEvent` on every change so non-React code can react too. +- `system` is the default. It resolves against the OS `prefers-color-scheme` and follows it live. +- The choice is stored in `localStorage`. +- You style the `dark` class with plain CSS. +- Every change dispatches a `CustomEvent`, so code outside React can follow it too. -## Installation +## Install ```sh pnpm add @variablelab/theme-toggle ``` +It needs React 18 or later. + ## Usage -The package ships **two pieces** that work together. +theme-toggle ships two pieces that work together. -### 1. Inline script (prevents the theme flash) +### 1. The inline script -Load the prebuilt IIFE **before your app renders** — ideally as the first thing in -``, blocking, so the correct `dark` class is on `` before the page paints. +Load the prebuilt script as the first thing in ``, blocking, so the `dark` class is on `` before the page paints. ```html @@ -37,11 +36,9 @@ Load the prebuilt IIFE **before your app renders** — ideally as the first thin ``` -On load it reads the stored mode (or `system` by default), toggles the `dark` class -on `` — resolving `system` against the OS preference — persists the mode, and -exposes its runtime contract on `window.__COLOR_MODE__`. +On load it reads the stored mode, or `system` when there is none, and toggles the `dark` class on ``, resolving `system` against the OS preference. Then it stores the mode and exposes its runtime contract on `window.__COLOR_MODE__`. -### 2. React hook (read & control the mode) +### 2. The React hook ```tsx import { useColorMode } from "@variablelab/theme-toggle"; @@ -60,13 +57,11 @@ function ThemeSwitch() { } ``` -Calling `setColorMode` persists the choice to `localStorage`, toggles the `dark` class -on ``, and dispatches the change event. While `colorMode` is `system`, the hook -also follows the OS preference live as it changes. +Calling `setColorMode` stores the choice in `localStorage`, toggles the `dark` class on `` and dispatches the change event. While `colorMode` is `system`, the hook also follows the OS preference as it changes. ## Styling -Style the two themes with the `dark` class that gets toggled on ``: +Style the two themes with the `dark` class on ``: ```css :root { @@ -93,8 +88,7 @@ body { | Storage key | `@variablelab/theme-toggle.colorMode` | | Change event | `@variablelab/theme-toggle.colorModeChange` | -The change event is a `CustomEvent` dispatched on `document`, with the new value in -`event.detail.colorMode`: +The change event is a `CustomEvent` dispatched on `document`, with the new value in `event.detail.colorMode`: ```ts document.addEventListener("@variablelab/theme-toggle.colorModeChange", (event) => { @@ -102,33 +96,25 @@ document.addEventListener("@variablelab/theme-toggle.colorModeChange", (event) = }); ``` -The inline script also publishes these names on `window.__COLOR_MODE__` -(`STORAGE_KEY`, `CUSTOM_EVENT`, `COLOR_MODE`) so other scripts can read them without -importing the package. +The inline script also publishes these names on `window.__COLOR_MODE__` (`STORAGE_KEY`, `CUSTOM_EVENT`, `COLOR_MODE`), so other scripts can read them without importing the package. ## Upgrading from `@vlandoss/theme-toggle` 1.x The package was renamed to `@variablelab/theme-toggle` in 2.0.0: -1. Replace the dependency and imports: `pnpm remove @vlandoss/theme-toggle && pnpm add @variablelab/theme-toggle`, - and update the inline script URL to `https://unpkg.com/@variablelab/theme-toggle/dist/initial.js`. -2. Listeners of the change event must use the new name, `@variablelab/theme-toggle.colorModeChange` - (or read it from `window.__COLOR_MODE__.CUSTOM_EVENT`). - -Saved preferences carry over automatically. On init, if the old `@vlandoss/theme-toggle.colorMode` -key exists, its value is copied to the new storage key, unless the new key already holds a value -(that value wins). The old key is then removed either way. +1. Replace the dependency and imports with `pnpm remove @vlandoss/theme-toggle && pnpm add @variablelab/theme-toggle`, and change the inline script URL to `https://unpkg.com/@variablelab/theme-toggle/dist/initial.js`. +2. Listeners of the change event must use the new name, `@variablelab/theme-toggle.colorModeChange`, or read it from `window.__COLOR_MODE__.CUSTOM_EVENT`. -## Development +Saved preferences carry over. On init, if the old `@vlandoss/theme-toggle.colorMode` key exists, its value is copied to the new key, unless the new key already holds a value: then that value wins. The old key is removed either way. -```sh -pnpm install -pnpm test # functional tests run in a real browser via Vitest Browser Mode + Playwright -``` +## Contributing -The suite in `test/functional` covers both entry points: the `useColorMode` hook -(`src/index.ts`) and the inline script (`src/initial.ts`). +The [contributing guide](https://github.com/withvariablelab/theme-toggle/blob/main/docs/contributing.md) covers issues, pull requests and releases, and the [development guide](https://github.com/withvariablelab/theme-toggle/blob/main/docs/development.md) covers setting up the repo and running its checks. ## License -MIT +The code is [MIT](https://github.com/withvariablelab/theme-toggle/blob/main/LICENSE). The Sign in `brand/` is not: its use is set by [BRAND-USE.md](https://github.com/withvariablelab/brand/blob/main/BRAND-USE.md). + +

+  Variable Land +

diff --git a/docs/contributing.md b/docs/contributing.md new file mode 100644 index 0000000..71daa16 --- /dev/null +++ b/docs/contributing.md @@ -0,0 +1,25 @@ +# Contributing + +theme-toggle takes bug reports, fixes and small features. To set up the repo and run its checks, see the [development guide](development.md). + +## Issues + +- A bug report says what you expected, what happened, and which browser, React version and theme-toggle version you use. +- A new feature, or a change to the hook or the inline script, starts as an issue before any pull request. + +## Pull requests + +1. Branch from `main` with a prefix: `feat/`, `fix/`, `docs/`, `chore/` or `test/`. +2. Write commits as [Conventional Commits](https://www.conventionalcommits.org), such as `docs: fix the inline script URL`. The pull request title takes the same form, because it becomes the squash commit. +3. Run `rr check` and `pnpm test` before you push. +4. A pull request from a `feat/` or `fix/` branch, or with the `preview` label, publishes a preview to npm under the `pr-` tag: `pnpm add @variablelab/theme-toggle@pr-123`. + +CI has to pass, and a maintainer squash-merges. + +## Changesets + +A change to what ships to npm, the README and the LICENSE included, needs a changeset. Run `pnpm changeset`, pick the bump (`patch` for a fix, `minor` for a feature, `major` for a breaking change), and write one sentence for the changelog. Changes to tests, CI or `docs/` need none. Nobody edits versions or `CHANGELOG.md` by hand. + +## Releases + +When changesets land on `main`, `vland-bot` opens or updates a "chore: update versions" pull request. A maintainer merges it, and that publishes the new version to npm. diff --git a/docs/development.md b/docs/development.md new file mode 100644 index 0000000..08d4d93 --- /dev/null +++ b/docs/development.md @@ -0,0 +1,33 @@ +# Development + +How to work on theme-toggle in a clone. The [contributing guide](contributing.md) covers how a change gets in. + +## Setup + +[mise](https://mise.jdx.dev) pins Node 24 and pnpm in `mise.toml`, with checksums in `mise.lock`, and puts `node_modules/.bin` on the `PATH`, so the tools run by name: + +```sh +mise install +pnpm install +playwright install chromium # the browser the tests run in +lefthook install # the git hooks in lefthook.yml +``` + +pnpm doesn't run lefthook's own install script, so the hooks need `lefthook install` once. After changing a version in `mise.toml`, run `mise lock` and commit both files. + +## Tasks + +```sh +pnpm test # the functional tests, in a real browser +rr check # Biome's format and lint, then the type check +rr jsc --fix # apply Biome's fixes +rr pack # build dist/ with tsdown, as prepublishOnly does +``` + +The suite in `test/functional` runs in Vitest Browser Mode with Playwright. It covers both entry points: the `useColorMode` hook (`src/index.ts`) and the inline script (`src/initial.ts`). + +## CI + +- **On each pull request to `main`:** `pnpm rr check`, `pnpm test` and the build with `pnpm rr pack` (CI), and zizmor on the workflows (Workflow audit). +- **Git hooks** ([lefthook](https://lefthook.dev)): on commit, Biome's fixes on the staged files and the type check; on push, the tests. +- **Every Monday:** `pnpm audit` on the lockfile, which keeps an issue labeled `dependency-audit` open while it finds known vulnerabilities (Dependency audit). From 442e1ad0b273e8dc2d5599be7b720732e1c6cc68 Mon Sep 17 00:00:00 2001 From: "Ricardo Q. Bazan" Date: Sun, 18 Oct 2026 07:37:11 -0500 Subject: [PATCH 3/3] docs: keep the scoped package name out of the Upgrading title GitHub shows a code span in a title as a gray block the size of the title, so the title says "Upgrading from 1.x" and its first sentence names both packages. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01XRCpaD5QTPJsEjnhikoV2S --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 28da498..42c64a6 100644 --- a/README.md +++ b/README.md @@ -98,9 +98,9 @@ document.addEventListener("@variablelab/theme-toggle.colorModeChange", (event) = The inline script also publishes these names on `window.__COLOR_MODE__` (`STORAGE_KEY`, `CUSTOM_EVENT`, `COLOR_MODE`), so other scripts can read them without importing the package. -## Upgrading from `@vlandoss/theme-toggle` 1.x +## Upgrading from 1.x -The package was renamed to `@variablelab/theme-toggle` in 2.0.0: +The package was renamed from `@vlandoss/theme-toggle` to `@variablelab/theme-toggle` in 2.0.0: 1. Replace the dependency and imports with `pnpm remove @vlandoss/theme-toggle && pnpm add @variablelab/theme-toggle`, and change the inline script URL to `https://unpkg.com/@variablelab/theme-toggle/dist/initial.js`. 2. Listeners of the change event must use the new name, `@variablelab/theme-toggle.colorModeChange`, or read it from `window.__COLOR_MODE__.CUSTOM_EVENT`.