Skip to content

[eslint-plugin] valid-styles rejects compound pseudo-classes like :hover:not(:disabled) #1618

Description

@skovhus

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions