Skip to content

perf(SegmentedControl): replace :has(+ [data-selected]) divider rule with adjacent-sibling selector#7903

Draft
mattcosta7 wants to merge 2 commits into
mainfrom
perf/segmentedcontrol-divider-no-has
Draft

perf(SegmentedControl): replace :has(+ [data-selected]) divider rule with adjacent-sibling selector#7903
mattcosta7 wants to merge 2 commits into
mainfrom
perf/segmentedcontrol-divider-no-has

Conversation

@mattcosta7
Copy link
Copy Markdown
Contributor

Closes #

Replaces the &:has(+ [data-selected])::after selector that hid the inter-item divider sitting just before the selected item. Previously the engine had to re-test a sibling-direction :has() against every .Item on every selection change.

Approach: flip the divider's side.

Drawing the divider on the leading edge of each non-first item (rather than the trailing edge of each non-last item) makes "the divider next to the selected item" expressible as adjacent-sibling combinators only:

/* Before */
.Item:not(:last-child)::after { /* divider */ }
.Item:has(+ [data-selected])::after,        /* item BEFORE the selected one */
.Item[data-selected]::after { background-color: transparent; }

/* After */
.Item:not(:first-child)::before { /* divider */ }
.Item[data-selected]::before,               /* selected item itself */
.Item[data-selected] + .Item::before { background-color: transparent; } /* item AFTER the selected one */

The same 1px line lives in the same gap between any two adjacent items — visually identical. The hide rules become two plain combinator selectors that the engine resolves in constant time per-element on a selection change, with no :has() walk.

The companion .Button:focus:focus-visible:not(:last-child)::after rule a few lines below is a pre-existing no-op on .Button::after (which has no content) and is left alone; it never targeted .Item::after.

Changelog

Changed

  • Internal: SegmentedControl inter-item divider is drawn on .Item::before of each non-first item instead of .Item::after of each non-last item.

Removed

  • The &:has(+ [data-selected])::after selector from SegmentedControl.module.css.

Rollout strategy

  • Patch release
  • Minor release
  • Major release; if selected, include a written rollout or migration plan
  • None; if selected, include a brief description as to why

Testing & Reviewing

  • All 19 packages/react/src/SegmentedControl/** unit tests pass.
  • tsc --noEmit on packages/react is clean.
  • Stylelint + Prettier + ESLint clean on touched file.

VRT expectations: None. The divider's geometry is unchanged — same 1px line at the same horizontal position, just attached to the item on its right rather than the item on its left. Hide-on-selection behavior is bit-identical (selected item and its trailing neighbour both lose their leading divider, mirroring the previous "item before selected + selected both lose their trailing divider").

Part of the :has()-reduction series: see also #7901 (PageHeader) and #7902 (ActionList SubGroup active indicator).

Merge checklist

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 29, 2026

🦋 Changeset detected

Latest commit: 83d8e52

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@primer/react Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions Bot added the integration-tests: recommended This change needs to be tested for breaking changes. See https://arc.net/l/quote/tdmpakpm label May 29, 2026
@github-actions
Copy link
Copy Markdown
Contributor

⚠️ Action required

👋 Hi, this pull request contains changes to the source code that github/github-ui depends on. If you are GitHub staff, test these changes with github/github-ui using the integration workflow. Check the integration testing docs for step-by-step instructions. Or, apply the integration-tests: skipped manually label to skip these checks.

To publish a canary release for integration testing, apply the Canary Release label to this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

integration-tests: recommended This change needs to be tested for breaking changes. See https://arc.net/l/quote/tdmpakpm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant