Skip to content

fix: avoid pseudo-selector duplicate for conditional borderColor + :focus override#391

Merged
skovhus merged 2 commits intomainfrom
cursor/fix-pseudo-border-color-conflict-f3c2
Apr 20, 2026
Merged

fix: avoid pseudo-selector duplicate for conditional borderColor + :focus override#391
skovhus merged 2 commits intomainfrom
cursor/fix-pseudo-border-color-conflict-f3c2

Conversation

@skovhus
Copy link
Copy Markdown
Owner

@skovhus skovhus commented Apr 20, 2026

Fixes "the same pseudo selector or at-rule cannot be used more than once" when a property has a prop ? value : undefined override at the base scope and another conditional override under a pseudo selector. (p) => p.$x ? value : undefined now resolves to a single positive variant bucket (matching && semantics), and inherited pseudo maps are unwrapped when seeding default so the variant bucket no longer nests them.

Open in Web Open in Cursor 

…rides target the same property

Two related bugs caused 'the same pseudo selector or at-rule cannot be used more than once'
for components like:

  styled.textarea`
    border: ${themedBorder('bgBorder')};
    border-color: ${(p) => p.$hasError ? p.theme.color.redBase : undefined};
    &:focus {
      border-color: ${(p) => p.$hasError ? p.theme.color.redBase : p.theme.color.controlPrimary};
    }
  `;

1. `(p) => p.$x ? value : undefined` (or `null`/`false`/`""`) now resolves to a
   single positive variant bucket via `splitVariantsResolved*` instead of falling
   through to a dynamic style function, matching the semantics of `p.$x && value`
   and avoiding pseudo-map collisions.
2. When seeding `default` of a new pseudo map from an inherited base value, the
   inherited value's own `default` is now unwrapped instead of being nested,
   preventing malformed shapes like `{ default: { default: A, ":focus": B }, ":focus": C }`.

Co-authored-by: Kenneth Skovhus <skovhus@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 20, 2026

PR Preview Action v1.8.1

🚀 View preview at
https://skovhus.github.io/styled-components-to-stylex-codemod/pr-preview/pr-391/

Built to branch gh-pages at 2026-04-20 15:44 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

@skovhus skovhus marked this pull request as ready for review April 20, 2026 15:30
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d38a23cd5c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/internal/builtin-handlers/conditionals.ts Outdated
… : value`

The negative-only branch added in the previous commit emitted a single
`splitVariantsResolvedValue` variant with a `!prop` `when` key, but
`handleSplitVariantsResolvedValue` treats negated entries as the
unconditional default and applies them directly to the base `styleObj`.
That silently dropped the `!prop` gate and produced always-on styles.

Restrict `buildOneSidedVariantResult` to the positive-only direction
(`prop ? value : undefined/null/false/""`) — which was the originally
reported pattern — and let the inverse fall through to the dynamic
style-function fallback. Add a regression test that fails if the
unconditional-leak ever reappears.

Addresses Codex review on PR #391.

Co-authored-by: Kenneth Skovhus <skovhus@users.noreply.github.com>
@skovhus skovhus merged commit bc86c6d into main Apr 20, 2026
6 checks passed
@skovhus skovhus deleted the cursor/fix-pseudo-border-color-conflict-f3c2 branch April 20, 2026 16:04
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