feat(components): add opt-in layered stylesheet variant (CSS cascade layers)#2643
Open
mfal wants to merge 4 commits into
Open
feat(components): add opt-in layered stylesheet variant (CSS cascade layers)#2643mfal wants to merge 4 commits into
mfal wants to merge 4 commits into
Conversation
Wrap the generated stylesheet in nested CSS cascade layers (@layer flow.tokens, flow.reset, flow.base, flow.components) so consumers can override Flow styles with unlayered CSS without specificity hacks or !important. - design-tokens: new Style Dictionary format `css/variables-layered` wraps token CSS in @layer flow.tokens (all destinations, selectors preserved) - components: index.scss assigns the reset to flow.reset and fonts to flow.base and declares the layer order; a PostCSS plugin wraps component modules (.module.scss/.module.css) in flow.components; a Vite writeBundle plugin hoists the layer-order declaration to the top (esbuild drops it during minify) - additionally export an UNLAYERED variant as an opt-out for apps that cannot adopt layers (e.g. a global `* { all: initial }` reset that would otherwise wipe layered Flow styles): @mittwald/flow-react-components/all.unlayered.css and @mittwald/flow-stylesheet/css-unlayered, derived by stripping @layer from the built all.css - docs: ADRs (docs/adr/0001, 0002), the stylesheet docs page, and MIGRATION.md - add AGENTS.md: run package scripts via `corepack pnpm --filter <pkg> <script>` Co-Authored-By: Claude Opus 4.8 <[email protected]>
Translate the two cascade-layer ADRs from German to English and rename the files to English slugs (cross-links updated): - 0001-css-cascade-layers-im-stylesheet.md -> 0001-css-cascade-layers-in-the-stylesheet.md - 0002-stylesheet-generierung.md -> 0002-stylesheet-generation.md Co-Authored-By: Claude Opus 4.8 <[email protected]>
Flip the two stylesheet variants so adopting this release is non-breaking: - `all.css` / `@mittwald/flow-stylesheet/css` stays UNLAYERED (unchanged behavior). - The layered variant moves to `all-layered.css` / `@mittwald/flow-stylesheet/css-layered` as an opt-in export. Both variants come from the same build: the pipeline layers the CSS at the source (that is the layered output), and the default is that output with the `@layer` wrappers stripped. Renames the Vite plugin `unlayeredCssPlugin` -> `stylesheetVariantsPlugin` (writes `all-layered.css`, strips `@layer` into `all.css`). Updates package exports and the flow-stylesheet copy step accordingly. Docs updated to the non-breaking, opt-in framing (ADR 0001, stylesheet docs page); removes the now-obsolete breaking-change entry from MIGRATION.md. Co-Authored-By: Claude Opus 4.8 <[email protected]>
Member
Author
|
@copilot resolve the merge conflicts in this pull request |
Contributor
Resolved and merged latest |
There was a problem hiding this comment.
Pull request overview
Adds an opt-in layered stylesheet variant for Flow using CSS cascade layers (tokens → reset → base → components), while keeping the existing default stylesheet path and behavior intended to remain unlayered.
Changes:
- Generates and exports new layered CSS entrypoints:
all-layered.css/css-layeredalongside existingall.css/css. - Introduces build-time layering: tokens wrapped in
@layer flow.tokens, component CSS modules wrapped in@layer flow.components, and awriteBundlehoist to ensure the layer order declaration is at the top. - Adds ADR documentation and updates the docs “stylesheet” page to explain the new variant and when to choose it.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/stylesheet/package.json | Adds ./css-layered export pointing at dist/styles-layered.css. |
| packages/stylesheet/build.js | Copies both all.css and all-layered.css into dist/styles.css and dist/styles-layered.css. |
| packages/design-tokens/build-tokens.js | Adds a layered Style Dictionary format and switches CSS output to it. |
| packages/components/vite.build.config.ts | Adds PostCSS + Vite plugins to wrap CSS in layers and emit split variants. |
| packages/components/src/styles/index.scss | Declares layer order and moves reset/fonts into flow.reset / flow.base layers. |
| packages/components/package.json | Exports the new ./all-layered.css artifact. |
| packages/components/dev/vite/stylesheetVariantsPlugin.ts | Writes all-layered.css and strips @layer to overwrite all.css (default). |
| packages/components/dev/vite/layerOrderPlugin.ts | Hoists the layer order declaration to the top of emitted CSS. |
| packages/components/dev/vite/flowComponentsLayerPlugin.ts | Wraps component CSS-module output in @layer flow.components. |
| docs/adr/0001-css-cascade-layers-in-the-stylesheet.md | Records the cascade-layers decision, rationale, and implementation details. |
| docs/adr/0002-stylesheet-generation.md | Documents the existing stylesheet generation architecture (retroactively). |
| apps/docs/src/content/01-get-started/stylesheet/index.mdx | Documents the new css-layered usage and guidance for consumers. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+14
to
+17
| for (const asset of Object.values(bundle)) { | ||
| if (asset.type !== "asset" || !asset.fileName.endsWith(".css")) { | ||
| continue; | ||
| } |
Comment on lines
+49
to
+51
| const nestedVariables = selector | ||
| .reverse() | ||
| .reduce( |
Comment on lines
144
to
146
| { | ||
| format: "css/variables", | ||
| format: "css/variables-layered", | ||
| destination: `css/${destination}.css`, |
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.
What
Adds an opt-in layered variant of the generated stylesheet, organized into
nested CSS cascade layers:
The default stays unlayered and unchanged — this release is non-breaking.
@mittwald/flow-react-components/all.css,@mittwald/flow-stylesheet/css@mittwald/flow-react-components/all-layered.css,@mittwald/flow-stylesheet/css-layeredWhy
With the unlayered default, overriding Flow requires beating its specificity
(
!important, nested selectors). The layered variant lets consumers override anyFlow rule with unlayered CSS regardless of specificity, and gives a
language-guaranteed internal order (tokens → reset → base → components) plus clean
interop with consumers' own cascade layers (e.g. Tailwind). Making it opt-in
avoids changing override resolution for existing consumers (an app-wide
* { all: initial }, for example, would wipe layered Flow — so it must not beforced).
Changes
build-tokens.js): custom Style Dictionary formatcss/variables-layeredwraps token CSS in@layer flow.tokens(all destinations,selector/outputReferencespreserved).src/styles/index.scss: reset →@layer flow.reset, fonts →@layer flow.base,plus the order declaration.
dev/vite/flowComponentsLayerPlugin.ts: PostCSS plugin wrapping every*.module.(scss|css)under/src/components/in@layer flow.components.dev/vite/layerOrderPlugin.ts: VitewriteBundleplugin hoisting the orderdeclaration to the top after esbuild minification.
dev/vite/stylesheetVariantsPlugin.ts: writes the layered output toall-layered.css, then strips@layerand overwritesall.css(unlayereddefault).
@mittwald/flow-react-componentsadds./all-layered.css;@mittwald/flow-stylesheetadds./css-layered(itsbuild.jscopies bothvariants).
docs/adr/(0001 decision, 0002 current build architecture);the
stylesheetdocs page documents both variants and when to pick which.corepack pnpm --filter.Not a breaking change
Existing consumers on
all.css/csssee no change. The layered variant ispurely additive. When opting into it, an app-side unlayered reset that conflicts
with Flow (e.g.
* { all: initial }) should be moved into a layer declared beforeflow.For reviewers
corepack pnpm --filter @mittwald/flow-react-components buildand--filter @mittwald/flow-stylesheet build:all.css/styles.csscontainno
@layer;all-layered.css/styles-layered.cssstart with the orderdeclaration and contain the
@layer flow.*blocks.nx build componentscould not fully run in the working environment (icon codegentasks need network / full workspace) — please double-check in CI.
writeBundlerewrite; the many individual@layer flow.componentsblocks could bemerged.
🤖 Generated with Claude Code