Skip to content

feat(components): serve all.css via CSS cascade layers#2626

Open
mfal wants to merge 3 commits into
mainfrom
claude/css-layer-all-css
Open

feat(components): serve all.css via CSS cascade layers#2626
mfal wants to merge 3 commits into
mainfrom
claude/css-layer-all-css

Conversation

@mfal

@mfal mfal commented Jul 8, 2026

Copy link
Copy Markdown
Member

Summary

Serve the generated component stylesheet (all.css) via CSS cascade layers, so consuming applications can override Flow with unlayered CSS without specificity battles.

Layer order (low → high priority):

@layer flow.reset, flow.base, flow.components, flow.components-override;
  • flow.reset – the hard reset (all: initial + display restoration).
  • flow.base – base typography, Josh-Comeau reset, color-scheme, reduced-motion.
  • flow.components – every component CSS module (wrapped automatically at build time).
  • flow.components-override – inter-component overrides (one Flow component restyling another).
  • Unlayered on purpose: design tokens (CSS custom properties) and @font-face.

How it works

  • Split styles/globals.scss into globals-reset.scss / globals-base.scss, loaded into flow.reset / flow.base.
  • New Vite/PostCSS plugin dev/vite/flowCssLayerPlugin.ts:
    • wraps every *.module.(scss|css) in @layer flow.components;
    • prepends the layer-order statement to all.css (after @charset, via a post generateBundle hook).
  • @layer unlayered { … } escape hatch: the plugin hoists such rules out of any layer, so components can still override third-party CSS injected unlayered at runtime. Applied to CodeEditor (CodeMirror) and ImageCropper (react-easy-crop).
  • @layer flow.components-override applied to the genuine inter-component overrides (CartesianChart, CheckboxGroup, MarkdownEditor, CodeBlock, DateInput, DateRangeInput, Message, LayoutCard, ListItemView) — replacing reliance on specificity/source-order and one !important.

Behavior change (documented, not a forced major)

Flow's styles now live in a cascade layer, so unlayered CSS in a consuming app overrides Flow automatically. Apps that relied on Flow winning over their own unlayered global CSS can move those rules into a layer ordered before flow. Documented in:

  • packages/components/MIGRATION.md (consumer migration note)
  • docs stylesheet page (apps/docs/.../01-get-started/stylesheet/index.mdx)
  • packages/components/CONTRIBUTE.md (the @layer unlayered / flow.components-override conventions)

Verification

  • Built the components package: all.css is emitted with the correct layer order (@charset → order statement → layer blocks), tokens/@font-face unlayered, all component modules in flow.components, and the CodeMirror / react-easy-crop overrides correctly unlayered.
  • Visual regression (WebKit): the initial layering broke CodeEditor / CodeBlock / ImageCropper (they override third-party unlayered CSS) — the @layer unlayered fix restored all three to green.
  • The remaining visual diffs were confirmed pre-existing via a pristine-master control run (byte-identical renders with and without layers) — environment/baseline noise (font AA + backdrop-filter blur), not caused by this change.
  • The flow.components-override moves are behavior-preserving (selectors/values unchanged; only the layer assignment changes).

Notes

  • MIGRATION.md uses a placeholder version (>=0.2.0-alpha.897) — adjust to the actual release version.
  • Branch is a few commits behind main; rebase before merge if needed.

🤖 Generated with Claude Code

mfal and others added 2 commits July 8, 2026 16:11
Wrap the generated component stylesheet (all.css) in a `flow` cascade layer
so consuming applications can override Flow with unlayered CSS without
specificity battles.

Sublayer order (low -> high): flow.reset, flow.base, flow.components,
flow.components-override. Design tokens (CSS custom properties) and
@font-face are intentionally left unlayered.

- Split styles/globals.scss into globals-reset.scss (the hard reset) and
  globals-base.scss (typography, Josh-Comeau reset, color-scheme,
  reduced-motion), loaded into flow.reset / flow.base.
- Add a Vite/PostCSS plugin (dev/vite/flowCssLayerPlugin.ts) that wraps
  every component CSS module in @layer flow.components and prepends the
  layer-order statement to all.css (after @charset).
- Support an `@layer unlayered { ... }` escape hatch: the plugin hoists its
  rules out of any layer so components can still override third-party CSS
  injected unlayered at runtime. Applied to CodeEditor (CodeMirror) and
  ImageCropper (react-easy-crop).
- Document for consumers (MIGRATION.md, docs stylesheet page) and
  contributors (CONTRIBUTE.md).

Note: Flow's styles now live in a cascade layer, so unlayered CSS in a
consuming app overrides Flow automatically. Apps that relied on Flow winning
over their own unlayered global CSS can move those rules into a layer ordered
before `flow` (see MIGRATION.md).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
…omponent overrides

Move the rules where one Flow component overrides another (nested/composed)
component into the `flow.components-override` sublayer, so they win via the
cascade layer instead of via selector specificity, source order or `!important`.

- CartesianChart: focus-outline suppression (drops `!important`)
- CheckboxGroup, MarkdownEditor: FormField `display` override
- CodeBlock: CodeEditor/CodeMirror border color
- DateInput, DateRangeInput: embedded Button geometry
- Message: sender Text alignment
- LayoutCard: Tabs context-menu button corner radius
- ListItemView: Avatar icon/initials sizing in tile view

Behavior-preserving: selectors and declarations are unchanged; only the layer
assignment changes.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@mfal mfal marked this pull request as draft July 8, 2026 15:02
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for ./packages/components/

Status Category Percentage Covered / Total
🔵 Lines 84.1% 328 / 390
🔵 Statements 84.42% 336 / 398
🔵 Functions 89.77% 79 / 88
🔵 Branches 74.66% 165 / 221
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/components/dev/vite/flowCssLayerPlugin.ts 100% 90% 100% 100%
Generated in workflow #5540 for commit 476c4b4 by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

🚀 Preview Deployment

Preview environments are ready:

Type URL
docs pr-2626.docs.review.flow-components.de
storybook pr-2626.storybook.review.flow-components.de

Images:

  • docs: ghcr.io/mittwald/flow/docs:pr-2626
  • storybook: ghcr.io/mittwald/flow/storybook:pr-2626

Covers flowComponentsLayerPostcssPlugin (flow.components wrapping, @layer unlayered unwrap, flow.components-override passthrough, module-file gating) and flowLayerOrderPlugin (order-statement prepend after @charset, idempotency, target-asset gating).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@mfal mfal marked this pull request as ready for review July 9, 2026 06:18
@Lisa18289

Copy link
Copy Markdown
Member
Bildschirmfoto 2026-07-09 um 08 39 13 In den docs sind die Anchor Link Headings kaputt gegangen (liegt daran das deren display:flex für den Content das display:none für leeren Heading Content überschreibt )

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.

2 participants