Skip to content

Add zero-dep theme behavior and render-blocking theme guard - #892

Open
wibjorn wants to merge 1 commit into
mainfrom
wibjorn/theme-resume-iife
Open

Add zero-dep theme behavior and render-blocking theme guard#892
wibjorn wants to merge 1 commit into
mainfrom
wibjorn/theme-resume-iife

Conversation

@wibjorn

@wibjorn wibjorn commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Mirrors docs-ui PR 1175046 ("Add render-blocking theme guard to prevent theme flash") in Atlas, and moves theme-switching logic out of the site-only theming.ts into the published, zero-dependency @microsoft/atlas-js package.

What changed

New zero-dep behavior — createThemeState (js/src/behaviors/theme.ts)

  • Manages theme resolution, persistence, cycling, and subscription.
  • The theme list is passed as config (default ['light','dark','high-contrast']) — not imported from @microsoft/atlas-css, preserving the package's zero-dependency guarantee.
  • Mirrors the conventions of the existing createLayoutState behavior.
  • Exported from js/src/index.ts.

Render-blocking theme guard

  • Added a #theme-preference inline IIFE to the <head> of the standard, token, and homepage scaffolds.
  • Reads localStorage('theme'), validates against the known themes, falls back to prefers-color-scheme: dark, and applies the theme-* class to <html> before first paint — eliminating the wrong-theme flash that occurred while the deferred module bundle loaded.

Slimmed site glue (site/src/scaffold/scripts/theming.ts)

  • Now a thin wrapper over createThemeState: derives the theme list from the Atlas tokens, keeps the non-persistent ?theme= override, and continues to expose window.setTheme (used by visual-diff tests).

Docs — site/src/components/theme.md

  • Documents the behavior, its options, cycle controls, and the inline guard snippet.
  • Includes a .notification notification-warning callout noting that the hardcoded theme array in the inline guard must be updated when using custom themes.

Changeset

  • Minor bump for @microsoft/atlas-js and @microsoft/atlas-site.

Testing

  • 34 new [ai generated]-tagged unit tests in js/test/behaviors/theme.test.ts (98% statement / 98% branch / 100% function coverage on the new module).
  • npm run lint, npm run build, and npm run test all green for atlas-js; site lint + tsc --noEmit pass.

Adds createThemeState to @microsoft/atlas-js: a zero-dependency behavior that resolves, applies, and persists the active theme-* class, falls back to the system prefers-color-scheme, and wires up [data-theme-cycle] controls. The theme list is passed in as config so the package stays free of cross-package imports.

The documentation site now uses createThemeState (replacing the bespoke site-only theming module) and ships a render-blocking inline #theme-preference guard in <head> across the scaffolds to prevent a wrong-theme flash when scripts are deferred. New components/theme.md documents the behavior and the inline guard.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@wibjorn
wibjorn requested a review from a team as a code owner June 22, 2026 22:10
@changeset-bot

changeset-bot Bot commented Jun 22, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: a2a623b

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

This PR includes changesets to release 2 packages
Name Type
@microsoft/atlas-js Minor
@microsoft/atlas-site Minor

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

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