feat(react-ui): add scheme-pinned defaults-dark.css and defaults-light.css exports#737
Open
ankit-thesys wants to merge 1 commit into
Open
feat(react-ui): add scheme-pinned defaults-dark.css and defaults-light.css exports#737ankit-thesys wants to merge 1 commit into
ankit-thesys wants to merge 1 commit into
Conversation
…t.css exports Every dark token the package ships is gated behind @media (prefers-color-scheme: dark), so an app forcing one scheme (<ThemeProvider mode="dark">) renders the stock light theme on light-scheme devices wherever the runtime style injection is not in effect: static first paint, server-rendered HTML before hydration, hydration failures, and no-JS. A downstream dark-only consumer hit this in production and now scrapes the dark token block out of the dist CSS on every upgrade. Emit plain unlayered :root blocks for each scheme from the same generator that produces openui-defaults.css, ship them as ./defaults-dark.css and ./defaults-light.css (unlayered in both style trees, like ./defaults.css), and guard them in check:css: no media query may sneak back in, and token counts must stay in parity with the combined defaults file. Fixes #736 Linear: TH-2215 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #736
Problem
Every dark token the package ships sits behind
@media (prefers-color-scheme: dark), in./index.css,./layered/styles/index.css, and./defaults.cssalike. An app that forces one scheme with<ThemeProvider mode="dark">therefore renders the stock light theme on light scheme devices wherever the runtime style injection is not in effect, meaning the static first paint, server rendered HTML before hydration, hydration failures, and pages without JavaScript. A downstream dark only consumer hit this in production and now scrapes the dark token block out of the dist CSS on every upgrade as a workaround. Full investigation:docs/dark-scheme-exports-investigation.md.Change
Two new scheme pinned stylesheets, emitted from the same generator that already produces
openui-defaults.cssso they come from the token source of truth and cannot drift:@openuidev/react-ui/defaults-dark.cssis a plain unlayered:rootblock with the full dark token set and no media query.@openuidev/react-ui/defaults-light.cssis the same for light, since light only apps have the mirrored problem on dark scheme devices.A dark only app pins the scheme statically with one extra import:
Details
src/scripts/generate-css-utils.tsgains agenerateSchemePinnedDefaultshelper and emitsopenui-defaults-dark.scssandopenui-defaults-light.scssnext to the existing generated files. Both are committed, matching howopenui-defaults.scssis tracked.css-layer-utils.mjsexports a sharedDEFAULTS_CSS_FILESlist, and the layered mirror keeps all three defaults files unlayered, matching the existing contract foropenui-defaults.css.cp-css.jsstrips the BOM from and copies all three defaults files intodist/styles.package.jsonadds the./defaults-dark.cssand./defaults-light.cssexports.check-css-artifacts.jsnow asserts the pinned files stay unlayered in both trees, contain no media query, and keep token count parity with each other and with the combinedopenui-defaults.css, so a regression fails the build instead of shipping.Verification
pnpm buildpasses includingcheck:css(55 layered files verified), andpnpm testpasses with a new test covering the verbatim mirror of the pinned files. The emitted artifacts each contain 213 tokens, matching the dark media block exactly, with no@mediaand no@layer, andrequire.resolvefinds both new export paths from a sibling workspace package.🤖 Generated with Claude Code