Skip to content

Pseudo States: Keep combinator broad pseudo selectors valid#35060

Merged
Sidnioulz merged 1 commit into
storybookjs:nextfrom
mturac:fix/issue-34933-pseudo-state-combinators
Jun 5, 2026
Merged

Pseudo States: Keep combinator broad pseudo selectors valid#35060
Sidnioulz merged 1 commit into
storybookjs:nextfrom
mturac:fix/issue-34933-pseudo-state-combinators

Conversation

@mturac

@mturac mturac commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

What I did

Fixes #34933.

When pseudo-state selectors are removed from the right-hand side of a child or sibling combinator, the pseudo-states addon could generate invalid CSS selectors such as .ds-card > or .ds-card:has(> ). This keeps those rewritten selectors valid by inserting a universal selector for the emptied combinator target.

How to test

yarn vitest run code/addons/pseudo-states/src/preview/rewriteStyleSheet.test.ts --config code/addons/pseudo-states/vitest.config.ts

Result locally: 1 test file passed, 51 tests passed, no type errors.

Also checked:

yarn oxfmt --check code/addons/pseudo-states/src/preview/rewriteStyleSheet.ts code/addons/pseudo-states/src/preview/rewriteStyleSheet.test.ts
git diff --check origin/next -- code/addons/pseudo-states/src/preview/rewriteStyleSheet.ts code/addons/pseudo-states/src/preview/rewriteStyleSheet.test.ts

Both passed locally.

Note: the repository lint command currently fails locally before linting these files because ESLint cannot resolve eslint-plugin-storybook from the code workspace after a fresh immutable install.

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Fixed pseudo-state selector rewriting to correctly handle edge cases where selectors appear after child combinators (>, +, ~)
    • Improved selector validity preservation by automatically rewriting combinators to target any child/sibling element when pseudo-states are removed
  • Tests

    • Added test coverage for pseudo-selector rewriting behavior with child combinators and :has() constructs

Manual testing

Missing but unit tests cover issue repro case.

@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR fixes CSS selector validity in the pseudo-states addon. When pseudo-state selectors are stripped from rules using child combinators, trailing combinators become invalid. The implementation now appends * to such combinators to preserve selector syntax, validated by new test cases covering child-combinator and :has(> ...) scenarios.

Changes

Selector Validity with Trailing Combinators

Layer / File(s) Summary
Trailing combinator validity fix and validation
code/addons/pseudo-states/src/preview/rewriteStyleSheet.ts, code/addons/pseudo-states/src/preview/rewriteStyleSheet.test.ts
extractPseudoStates adds regex post-processing to rewrite selectors ending with a combinator by appending *; two new test cases verify correct rewriting for child-combinator selectors and selectors inside :has(> ...) expressions.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
code/addons/pseudo-states/src/preview/rewriteStyleSheet.test.ts (1)

393-407: 💤 Low value

Consider adding test coverage for sibling combinators.

The current tests validate child combinator (>), which directly addresses the reported issue. For completeness, consider adding test cases for adjacent sibling (+) and general sibling (~) combinators, even though the regex on line 74 of rewriteStyleSheet.ts handles all three identically.

Example test cases:

it('keeps adjacent-sibling pseudo-state selectors valid', () => {
  const sheet = new Sheet('.ds-card + :focus-visible { outline: none }');
  rewriteStyleSheet(sheet as any);
  expect(sheet.cssRules[0].cssText).toEqual(
    '.ds-card + :focus-visible, .ds-card + .pseudo-focus-visible, .pseudo-focus-visible-all .ds-card + * { outline: none }'
  );
});

it('keeps general-sibling pseudo-state selectors valid', () => {
  const sheet = new Sheet('.ds-card ~ :focus-visible { outline: none }');
  rewriteStyleSheet(sheet as any);
  expect(sheet.cssRules[0].cssText).toEqual(
    '.ds-card ~ :focus-visible, .ds-card ~ .pseudo-focus-visible, .pseudo-focus-visible-all .ds-card ~ * { outline: none }'
  );
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@code/addons/pseudo-states/src/preview/rewriteStyleSheet.test.ts` around lines
393 - 407, Add unit tests in rewriteStyleSheet.test.ts to cover sibling
combinators (+ and ~) similar to the existing child-combinator tests: create
Sheet instances with selectors using '+' and '~' (e.g., '.ds-card +
:focus-visible' and '.ds-card ~ :focus-visible'), call rewriteStyleSheet(sheet
as any), and assert that sheet.cssRules[0].cssText includes the three rewritten
selectors (original, replaced pseudo-class like '.pseudo-focus-visible' on the
sibling, and the global wrapper '.pseudo-focus-visible-all .ds-card + *' /
'.pseudo-focus-visible-all .ds-card ~ *'); mirror the pattern used in the
child-combinator tests so the regex in rewriteStyleSheet correctly handles
adjacent and general sibling cases.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@code/addons/pseudo-states/src/preview/rewriteStyleSheet.test.ts`:
- Around line 393-407: Add unit tests in rewriteStyleSheet.test.ts to cover
sibling combinators (+ and ~) similar to the existing child-combinator tests:
create Sheet instances with selectors using '+' and '~' (e.g., '.ds-card +
:focus-visible' and '.ds-card ~ :focus-visible'), call rewriteStyleSheet(sheet
as any), and assert that sheet.cssRules[0].cssText includes the three rewritten
selectors (original, replaced pseudo-class like '.pseudo-focus-visible' on the
sibling, and the global wrapper '.pseudo-focus-visible-all .ds-card + *' /
'.pseudo-focus-visible-all .ds-card ~ *'); mirror the pattern used in the
child-combinator tests so the regex in rewriteStyleSheet correctly handles
adjacent and general sibling cases.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 103659b5-550f-4274-940a-ce66e8e27a26

📥 Commits

Reviewing files that changed from the base of the PR and between 64ab797 and ef327ff.

📒 Files selected for processing (2)
  • code/addons/pseudo-states/src/preview/rewriteStyleSheet.test.ts
  • code/addons/pseudo-states/src/preview/rewriteStyleSheet.ts

@Sidnioulz Sidnioulz added bug ci:normal Run our default set of CI jobs (choose this for most PRs). addon: pseudo-states qa:needed Pull Requests that will need manual QA prior to release. labels Jun 5, 2026
@Sidnioulz Sidnioulz changed the title fix(pseudo-states): keep combinator selectors valid Pseudo States: Keep combinator broad pseudo selectors valid Jun 5, 2026
@Sidnioulz Sidnioulz added qa:skip Pull Requests that do not need any QA. and removed qa:needed Pull Requests that will need manual QA prior to release. labels Jun 5, 2026
@Sidnioulz Sidnioulz merged commit 13ce265 into storybookjs:next Jun 5, 2026
142 of 153 checks passed
@github-actions github-actions Bot mentioned this pull request Jun 5, 2026
20 tasks
@mturac mturac deleted the fix/issue-34933-pseudo-state-combinators branch June 5, 2026 13:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

addon: pseudo-states agent-scan:human bug ci:normal Run our default set of CI jobs (choose this for most PRs). qa:skip Pull Requests that do not need any QA.

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[Bug]: storybook-addon-pseudo-states causes "SyntaxError: Failed to execute 'insertRule' on 'CSSGroupingRule'"

2 participants