Skip to content

fix(SegmentedControl): prevent constrained labels from wrapping - #8532

Open
joshfarrant wants to merge 11 commits into
mainfrom
joshfarrant-segmentedcontrol-regression-fix
Open

joshfarrant wants to merge 11 commits into
mainfrom
joshfarrant-segmentedcontrol-regression-fix

Conversation

@joshfarrant

@joshfarrant joshfarrant commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Related to github/primer#7156. Replaces the wrapping approach in #8442, which was reverted by #8469.

Keep SegmentedControl labels on one line and truncate them when space is constrained. This prevents wrapped text from escaping the control's styling without changing the existing 28px small / 32px medium heights.

Truncated labels reveal their full text on hover and keyboard focus, using the existing button as the tooltip trigger. Labels that fit do not show a tooltip.

Truncation is a defensive fallback, not the preferred layout. Normally, give the control more space, shorten the labels or use another component.

Changelog

New

  • Compact Toolbar and Constrained Label Overflow examples with regression coverage.
  • Conditional hover and keyboard-focus disclosure for truncated labels.

Changed

  • Allow segments and labels to shrink, with ellipsis applied to the label rather than icons or counters.
  • Preserve full accessible names and stable segment dimensions when selection changes.
  • Remeasure truncation when selection changes the label's font weight.
  • Reveal newly truncated labels while the button remains keyboard-focused, without overriding Escape dismissal.
  • Preserve consumer focus and pointer handlers on the existing trigger.
  • Update the component guidance and patch changeset to describe the single-line behaviour.
  • Close an open Tooltip when its existing disable flag becomes true, so a label resizing to fit does not leave an empty popup.

Removed

  • No public APIs.

Rollout strategy

  • No changes needed in github/github-ui
  • Needs changes in github/github-ui
  • Ships with feature flag(s)
  • Not sure
  • None

Testing & Reviewing

  • Regression coverage checks the compact 28px height, label truncation, complete accessible names, constrained icon buttons, auto-sized controls and stable geometry across selection changes. Disclosure tests cover hover, keyboard focus, Escape, resizing, label updates, selection-dependent text width, consumer callbacks and disabled segments.
  • The component patch has passed repeated rendered-browser disclosure regressions, existing Tooltip visual regressions, unit tests, builds, type checks and lint/format checks. No existing visual baselines changed.
  • Primer CI, stress tests and Storybook visual/accessibility checks pass for rebased revision bea76d162.
  • Copilot review of b1c9555d1 reported no new code finding but requests human review of the shared Tooltip changes.
  • Refreshed GitHub UI integration still fails package tests. Its visual status passes, but the underlying reports contain failures whose cause remains unisolated; integration validation is not complete.

The fixed-height sizing, public API and existing responsive variants are unchanged. Design/Accessibility sign-off on the overflow behaviour remains outstanding.

@changeset-bot

changeset-bot Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: bea76d1

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 Oct 13, 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.

@github-actions
github-actions Bot temporarily deployed to storybook-preview-8532 October 13, 2026 14:10 Inactive
@github-actions
github-actions Bot temporarily deployed to storybook-preview-8532 October 13, 2026 14:36 Inactive
@github-actions github-actions Bot added integration-tests: failing Changes in this PR cause breaking changes in gh/gh and removed integration-tests: recommended This change needs to be tested for breaking changes. See https://arc.net/l/quote/tdmpakpm labels Oct 16, 2026
@joshfarrant
joshfarrant marked this pull request as ready for review October 16, 2026 11:21
@joshfarrant
joshfarrant requested a review from a team as a code owner October 16, 2026 11:21
@joshfarrant
joshfarrant requested review from jonrohan and a balanced review from Copilot October 16, 2026 11:21

Copilot AI 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.

🔵 Needs a closer look

The previously reverted, browser-sensitive sizing change still needs hosted CI completion and human visual sign-off.

0 open findings

What changed in this PR

Retries content-driven SegmentedControl sizing after the earlier revert, preserving compact single-line dimensions while allowing wrapped labels.

Changes:

  • Preserves 28px small and 32px medium minimum heights.
  • Reserves wrapped label dimensions to prevent selection-driven layout shifts.
  • Adds regression coverage, stories, sizing documentation, and a patch changeset.
File Description
packages/​react/​src/​SegmentedControl/​SegmentedControlButton.tsx Wraps visible labels for overlapping grid layout.
packages/​react/​src/​SegmentedControl/​SegmentedControl.tsx Clarifies minimum-height behavior.
packages/​react/​src/​SegmentedControl/​SegmentedControl.test.tsx Adds an accessible-name assertion.
packages/​react/​src/​SegmentedControl/​SegmentedControl.module.css Adds content-driven sizing and wrapped-height reservation.
packages/​react/​src/​SegmentedControl/​SegmentedControl.features.stories.tsx Adds compact toolbar and multiline examples.
packages/​react/​src/​SegmentedControl/​SegmentedControl.features.stories.module.css Styles the new sizing examples.
packages/​react/​src/​SegmentedControl/​SegmentedControl.docs.json Documents wrapping and stable sizing.
e2e/​components/​SegmentedControl.test.ts Tests compact heights and selection-stable geometry.
.changeset/​segmented-control-content-height.md Records the patch release change.

🧠 Review effort: Balanced


💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

"name": "size",
"type": "'small' | 'medium'",
"description": "The size of the buttons",
"description": "The minimum height of the control: 28px for small, 32px for medium. Labels wrap naturally when constrained, and all segments grow to fit the tallest label without shifting height on selection.",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Medium: The linked issue requires labels not to wrap and asks for Design and Accessibility approval before implementation, but this documents wrapping as the public contract while the PR says no approval is claimed. Can we record that decision or align the behavior before shipping?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks @jonrohan — totally valid point.

I checked in with @mattobee who recommended truncation as a defensive fallback but only for edge cases. Normally we'd recommend that the control be given more space, the label shortened, or that a different component be used.

I've reworked the PR so labels stay on one line and truncate when they don't fit. lmk what you think

@github-actions
github-actions Bot requested a deployment to storybook-preview-8532 October 20, 2026 14:05 Abandoned
@joshfarrant joshfarrant changed the title fix(SegmentedControl): stabilize content-driven height fix(SegmentedControl): prevent constrained labels from wrapping Oct 20, 2026
@github-actions
github-actions Bot temporarily deployed to storybook-preview-8532 October 20, 2026 14:14 Inactive
@joshfarrant
joshfarrant requested a balanced review from Copilot October 20, 2026 14:47

Copilot AI 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.

🟡 Changes recommended

Constrained layouts still have unresolved root-sizing and icon-segment overlap issues.

2 open issues

Review effort: Balanced

Comment thread packages/react/src/SegmentedControl/SegmentedControl.module.css Outdated
Comment thread packages/react/src/SegmentedControl/SegmentedControl.module.css

Copilot AI 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.

🟡 Changes recommended

Text segments can shrink below their icon and counter footprint, allowing content to overflow neighboring segments.

1 open issue
2 resolved since last review

Review effort: Balanced

Comment thread packages/react/src/SegmentedControl/SegmentedControl.module.css Outdated

Copilot AI 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.

🟡 Changes recommended

Consumer callbacks can be suppressed, and truncation disclosure can become stale after selection changes.

3 open issues

Review effort: Balanced

Comment thread packages/react/src/SegmentedControl/SegmentedControlButton.tsx Outdated
)}
</span>
</button>
<Tooltip text={isTruncated ? children : ''} _privateDisableTooltip={!isTruncated}>

Copilot AI 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.

🟡 Changes recommended

The new Tooltip wrapper duplicates consumer mouse-enter callbacks, potentially repeating side effects or throwing errors.

3 open issues
1 resolved since last review

Review effort: Balanced

Comment thread packages/react/src/TooltipV2/Tooltip.tsx

Copilot AI 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.

🔵 Needs a closer look

Overflow behavior still needs Design/Accessibility sign-off, and downstream validation remains unresolved.

2 open issues
1 previously missed issue

In code that hasn't changed since last review

Medium severity Keyboard selection can truncate labels without revealing their tooltip

packages/​react/​src/​SegmentedControl/​SegmentedControlButton.tsx:66

If an unselected label fits but its selected, semibold text does not, focusing the button and pressing Enter truncates the label without showing its tooltip. The focus handler ran while the tooltip was disabled, and re-enabling it does not call openTooltip(). Keyboard users must move focus away and back to reveal the full text. Handle the transition to truncated while the trigger remains keyboard-focused, without moving focus or undoing Escape dismissal. Add a regression that selects with Enter and expects disclosure without refocusing; the current selection-dependent test tabs away and back first.

1 resolved since last review

Review effort: Balanced

Copilot AI 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.

🔵 Needs a closer look

Shared Tooltip behavior changes need human review, with integration validation and design/accessibility sign-off still pending.

2 open issues

Review effort: Balanced

joshfarrant and others added 11 commits October 23, 2026 11:20
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 4a13eabe-bebc-4a7c-8036-de924dc3b113
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4a13eabe-bebc-4a7c-8036-de924dc3b113
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4a13eabe-bebc-4a7c-8036-de924dc3b113
Keep labels single-line and preserve compact sizing, accessible names and selection geometry. Align metadata, story guidance and component regressions with defensive truncation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 05c0d550-3955-4bec-8361-5de4ad442f19
Show full and constrained labels side by side while keeping short labels readable. Preserve the extreme fixture as separate stress coverage.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 05c0d550-3955-4bec-8361-5de4ad442f19
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 05c0d550-3955-4bec-8361-5de4ad442f19
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 05c0d550-3955-4bec-8361-5de4ad442f19
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 05c0d550-3955-4bec-8361-5de4ad442f19
…election

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 05c0d550-3955-4bec-8361-5de4ad442f19
Retain the trigger’s native handler instead of invoking it again after the tooltip delay. Extend the rendered SegmentedControl callback regression to check the event count.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 05c0d550-3955-4bec-8361-5de4ad442f19
Open disclosure when a focused segment becomes truncated without requiring a new focus event. Preserve Escape dismissal until focus returns, including across fitting and truncated transitions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 05c0d550-3955-4bec-8361-5de4ad442f19
@primer-integration

primer-integration Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Integration test results from github/github-ui PR:

Waiting  Changes   Waiting
Failed  CI   Failed
Waiting  VRT   Waiting
Running  Projects   Running

CI check runs linting, type checking, and unit tests. Check the workflow logs for specific failures.

Need help? If you believe this failure is unrelated to your changes, please reach out to the Primer team for assistance.

This branch was successfully deployed

2 active deployments
storybook-preview-8532 — bea76d16 Deployed Oct 23, 2026 by github-actions[bot]
github-pages — bea76d16 Deployed Oct 23, 2026 by joshfarrant via deploy-preview #33876
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

integration-tests: failing Changes in this PR cause breaking changes in gh/gh

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants