The @stylexjs/valid-styles ESLint rule rejects compound pseudo-class selectors like :hover:not(:disabled) and :active:not(:disabled) when used as conditional style keys in stylex.create().
The Babel plugin compiles these correctly — they produce valid CSS like .x15hc757:active:not(:disabled){background-color:blue}. But the ESLint rule's pseudoClassesAndAtRules allowlist in cssProperties.js uses exact literal matching (makeLiteralRule) which doesn't account for compound pseudo-classes.
Steps to reproduce
import * as stylex from "@stylexjs/stylex";
const styles = stylex.create({
button: {
backgroundColor: {
default: "red",
// ✅ ESLint passes — flat value
":active:not(:disabled)": "blue",
// ❌ ESLint fails — nested media query value
":hover:not(:disabled)": { default: null, "@media (any-hover: hover) and (any-pointer: fine)": "blue" },
},
},
});
Note: the flat value on :active:not(:disabled) passes, but the nested media query object on :hover:not(:disabled) triggers the error. This appears to be because the validation code path differs depending on whether the value is a literal vs an object with further nesting.
Expected behavior
The rule should accept compound pseudo-classes that combine known pseudo-classes (:hover, :active, etc.) with :not() containing another valid pseudo-class.
Actual behavior
error Invalid Pseudo class or At Rule used for conditional style value @stylexjs/valid-styles
Root cause
In lib/reference/cssProperties.js, the pseudoClassesAndAtRules union rule only contains makeLiteralRule entries for simple pseudo-classes (:hover, :active, :disabled, etc.). There's no regex or pattern matcher for compound selectors.
Suggested fix
Add a makeRegExRule entry to the union that matches compound pseudo-class patterns:
(0, _makeRegExRule.default)(
/^:(hover|focus|focus-visible|focus-within|active|visited|disabled):not\(:[a-z-]+\)$/,
'a compound pseudo class'
)
Environment
@stylexjs/eslint-plugin: 0.18.1
@stylexjs/babel-plugin: 0.18.1
The
@stylexjs/valid-stylesESLint rule rejects compound pseudo-class selectors like:hover:not(:disabled)and:active:not(:disabled)when used as conditional style keys instylex.create().The Babel plugin compiles these correctly — they produce valid CSS like
.x15hc757:active:not(:disabled){background-color:blue}. But the ESLint rule'spseudoClassesAndAtRulesallowlist incssProperties.jsuses exact literal matching (makeLiteralRule) which doesn't account for compound pseudo-classes.Steps to reproduce
Note: the flat value on
:active:not(:disabled)passes, but the nested media query object on:hover:not(:disabled)triggers the error. This appears to be because the validation code path differs depending on whether the value is a literal vs an object with further nesting.Expected behavior
The rule should accept compound pseudo-classes that combine known pseudo-classes (
:hover,:active, etc.) with:not()containing another valid pseudo-class.Actual behavior
Root cause
In
lib/reference/cssProperties.js, thepseudoClassesAndAtRulesunion rule only containsmakeLiteralRuleentries for simple pseudo-classes (:hover,:active,:disabled, etc.). There's no regex or pattern matcher for compound selectors.Suggested fix
Add a
makeRegExRuleentry to the union that matches compound pseudo-class patterns:Environment
@stylexjs/eslint-plugin: 0.18.1@stylexjs/babel-plugin: 0.18.1