Skip to content

Add enum-specific condition negation - #1869

Draft
nmn wants to merge 2 commits into
feat/lightningcss-conditionsfrom
feat/enum-condition-negation
Draft

nmn wants to merge 2 commits into
feat/lightningcss-conditionsfrom
feat/enum-condition-negation

Conversation

@nmn

@nmn nmn commented Sep 10, 2026

Copy link
Copy Markdown
Collaborator

Adds the enum-specific condition logic that #1870 uses for conditional assignments. This PR adds the planner and its tests; the public conditional-call API is connected in the next PR.

For an enum with comfortable, compact, and spacious states, the next PR enables this call:

density({
  default: 'comfortable',
  ':hover': 'compact',
  ':active': 'spacious',
});

Hover and active can both match. Ordinary styles can let two rules compete over color; an enum writes a different custom property for each state. Simply activating compact and spacious in separate rules would leave both states active.

The planner therefore excludes active from the compact branch. This is the planned CSS structure, using readable names for the classes and state variables:

:where(.densityReset) {
  --density-comfortable: ;
  --density-compact: ;
  --density-spacious: ;
}

.selection {
  --density-comfortable: initial;
}

.selection:where(:hover):not(:where(:active)) {
  --density-comfortable: ;
  --density-compact: initial;
}

.selection:where(:active) {
  --density-comfortable: ;
  --density-spacious: initial;
}

With hover alone, compact is selected. While pressed, spacious is selected even if hover also matches. With neither condition, comfortable remains selected. initial activates a state; the empty value deactivates it.

The default is set unconditionally, and matching branches explicitly clear it. Container branches also clear earlier states when they match, so an element with no eligible container keeps its default.

Nested conditions are excluded as a whole. If spacious requires both active and a wide viewport, compact remains available while hovering on a narrow viewport. Branches that select the same state do not need exclusions from one another.

Ordinary styles keep the simpler output from #1867. This stronger negation is isolated to enum assignments, where multiple active custom properties would otherwise break stylex.match.

Validated with selector snapshots, all combinations of hover/active/focus, container fallback cases, and the existing ordinary-style snapshots across 1,025 Babel tests.

PR 5 of 6. Builds on #1868. Next: #1870.

@vercel

vercel Bot commented Sep 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
stylex Ignored Ignored Sep 10, 2026 9:57am UTC

Request Review

@nmn
nmn added this pull request to stack #1871 September 10, 2026 01:49
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Sep 10, 2026
@github-actions

github-actions Bot commented Sep 10, 2026

Copy link
Copy Markdown

workflow: benchmarks/perf

Comparison of performance test results, measured in operations per second. Larger is better.
yarn workspace v1.22.22
yarn run v1.22.22
$ node ./compare.js /tmp/tmp.lrqLWHocoM /tmp/tmp.YGKPfCqMOx

Results Base Patch Ratio
babel-plugin: stylex.create
· basic create 576 575 1.00 -
· complex create 62 63 1.02 +
babel-plugin: stylex.createTheme
· basic themes 454 462 1.02 +
· complex themes 32 32 1.00
Done in 0.08s.
Done in 0.34s.

@nmn nmn changed the title Add isolated enum condition exclusions with safe fallback resets Add enum-specific condition negation Sep 10, 2026
@github-actions

github-actions Bot commented Sep 10, 2026

Copy link
Copy Markdown

workflow: benchmarks/size

Comparison of minified (terser) and compressed (brotli) size results, measured in bytes. Smaller is better.
yarn workspace v1.22.22
yarn run v1.22.22
$ node ./compare.js /tmp/tmp.507cnz4YLE /tmp/tmp.CE76K3hgAz

Results Base Patch Ratio
@stylexjs/stylex/lib/cjs/stylex.js
· compressed 1,571 1,571 1.00
· minified 5,346 5,346 1.00
@stylexjs/stylex/lib/cjs/inject.js
· compressed 1,793 1,793 1.00
· minified 4,915 4,915 1.00
benchmarks/size/.build/bundle.js
· compressed 496,732 496,732 1.00
· minified 4,847,825 4,847,825 1.00
benchmarks/size/.build/stylex.css
· compressed 99,735 99,735 1.00
· minified 740,755 740,755 1.00
Done in 0.07s.
Done in 0.30s.

@nmn
nmn force-pushed the feat/enum-condition-negation branch from 9f282fc to 1ed5fb9 Compare September 10, 2026 02:01
@nmn
nmn force-pushed the feat/enum-condition-negation branch from 1ed5fb9 to 6dd777a Compare September 10, 2026 09:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant