Skip to content

fix(color-mode): respect page-declared themes, add an opt-out; refresh all dev deps - #6095

Merged
puikinsh merged 2 commits into
masterfrom
fix/color-mode-declared-theme-and-opt-out
Aug 5, 2026
Merged

fix(color-mode): respect page-declared themes, add an opt-out; refresh all dev deps#6095
puikinsh merged 2 commits into
masterfrom
fix/color-mode-declared-theme-and-opt-out

Conversation

@puikinsh

@puikinsh puikinsh commented Aug 5, 2026

Copy link
Copy Markdown
Member

Two commits: the color-mode work that builds on #6093, and a full dev-dependency refresh that supersedes #6085#6092.

1. Color mode (#6084, #6093)

ColorMode rewrote <html data-bs-theme> on every init pass, so applications with their own theming — or a server-rendered per-user preference — lost it on load. @dfsmania's #6093 correctly identified the markup as a preference source; this keeps that precedence chain (stored choice → theme declared in the markup → OS) and closes the gaps around it:

  • Capture the declared theme once, at module evaluation. The attribute is both input and output: after the first _applyTheme() write, reading it back returns ColorMode's own value on later lifecycle passes (turbo:load, initialize()), not the page's intent.
  • The prefers-color-scheme listener consults it too. Previously only getStoredTheme(), so a declared theme was clobbered by the first OS change and never came back.
  • <html data-lte-color-mode="off"> stops every write — init, toggle clicks, OS changes. This is the answer for adminlte v4.1.0 - disable ColorMode #6084, and for custom Bootstrap theme names, which ColorMode cannot resolve.
  • The pre-paint snippet follows the same precedence and flags values it resolved itself with data-lte-theme-resolved. Without that flag the demo pages — whose theme that snippet always writes — would have stopped following the OS, since its output is indistinguishable from an authored theme.

Measured in headless Chromium against the published 4.1.0 bundle, OS preference starting light:

scenario build after load OS→dark OS→light toggle click
<html data-bs-theme="dark">, nothing stored 4.1.0 light dark light dark
this PR dark dark dark dark
custom theme + data-lte-color-mode="off" 4.1.0 light dark light dark
this PR myapp-dark myapp-dark myapp-dark myapp-dark
demo: snippet, no markup, no storage 4.1.0 light dark light dark
this PR light dark light dark (unchanged)

Also removes the pre-4.1 inline toggler still shipping on the Color Mode docs page — it bound its own handlers to the same [data-bs-theme-value] buttons as the bundled module and persisted to theme instead of lte-theme, so that page ran two switchers at once.

13 new unit tests cover the precedence chain, OS changes and the opt-out (getPreferredTheme() previously had no coverage at all). Docs and FAQ updated. Bundlewatch ceilings +0.5 kB for +346 B gzip.

2. Dev dependency refresh (supersedes #6085#6092)

Lockfile regenerated from scratch, every dev dependency at latest, including two majors: eslint-plugin-astro 2 → 3 and eslint-plugin-unicorn 72 → 73 (whose new single-line-block-comment-style rule flagged four banner comments in util/index.ts — fixed rather than disabled).

TypeScript deliberately stays on 6.0.3: 7.0.2 is out, but typescript-eslint peers on >=4.8.4 <6.1.0 and @astrojs/check on ^5 || ^6, so installing it fails ERESOLVE and would break npm ci for everyone.

Verification

npm run lint, npm test (51 passing), npm run build, bundlewatch (all PASS), npm run test-a11y (0 violations), plus a functional pass over the built docs/color-mode.html in Chromium. Nothing in dist/ changed.

Note: no workflow runs vitest today, so those 51 tests aren't gating anything yet — worth a follow-up.

puikinsh and others added 2 commits August 5, 2026 17:36
ColorMode rewrote <html data-bs-theme> on every init pass, so an
application with its own theming lost it on load (#6084, reported by
@cytech). #6093 (thanks @dfsmania) proposed reading the attribute as a
preference source; this takes that idea and closes the gaps it left:

- resolve from the visitor's stored choice, then a theme the page
  declared itself, then the OS preference
- capture the declared theme once, at module evaluation, before the
  first _applyTheme() write. The attribute is both input and output, so
  reading it at init returns ColorMode's own value on later lifecycle
  passes (turbo:load, initialize()), not the page's intent
- teach the prefers-color-scheme listener about it too: a declared theme
  is a preference, and must outlive an OS change. Without this the fix
  only held until the first light/dark switch
- add <html data-lte-color-mode="off">, which stops every write: init,
  toggle clicks and OS changes. Also the answer for custom Bootstrap
  theme names, which ColorMode cannot resolve
- the pre-paint snippet follows the same precedence, honours the opt-out,
  and flags values it resolved itself with data-lte-theme-resolved so
  they are not mistaken for a declared theme — otherwise the demo, whose
  theme that snippet always writes, would stop following the OS

Also removes the pre-4.1 inline toggler still shipping on the Color Mode
docs page: it bound its own handlers to the same [data-bs-theme-value]
buttons as the bundled module and persisted to a different localStorage
key (theme, not lte-theme).

13 new unit tests cover the precedence chain, OS preference changes and
the opt-out. Bundlewatch ceilings raised for +346 B gzip on adminlte.js.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Full refresh (lockfile regenerated from scratch), superseding the open
Dependabot PRs #6085-#6092. Two majors:

- eslint-plugin-astro 2.1.1 -> 3.1.0
- eslint-plugin-unicorn 72.0.0 -> 73.0.0, whose new
  single-line-block-comment-style rule flagged four one-line banner
  comments in util/index.ts; converted to line comments rather than
  disabling the rule

Plus astro 7.1.6, eslint 10.8.0, typescript-eslint 8.66.0, sass 1.102.0,
rollup 4.62.4, terser 5.49.2, postcss 8.5.25, happy-dom 20.11.1,
@astrojs/check 0.9.10, @astrojs/mdx 7.0.5, concurrently 10.0.4,
fs-extra 11.4.0, globals 17.9.0.

TypeScript deliberately stays on 6.0.3. TypeScript 7.0.2 is out, but
typescript-eslint peers on `>=4.8.4 <6.1.0` and @astrojs/check on
`^5 || ^6`, so `npm install typescript@7` fails ERESOLVE outright and
would break `npm ci` for everyone. Revisit once both ship TS 7 support.

Verified: npm run lint, npm test (51), npm run build, bundlewatch (all
PASS), npm run test-a11y (0 violations). No dist/ output changed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@netlify

netlify Bot commented Aug 5, 2026

Copy link
Copy Markdown

Deploy Preview for adminlte-v4 ready!

Name Link
🔨 Latest commit b0c2ef6
🔍 Latest deploy log https://app.netlify.com/projects/adminlte-v4/deploys/6a738adbc06448000866399d
😎 Deploy Preview https://deploy-preview-6095--adminlte-v4.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

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