Skip to content

Conversation

@sfc-gh-lwilby
Copy link
Collaborator

@sfc-gh-lwilby sfc-gh-lwilby commented Oct 28, 2025

Describe your changes

Fixed segmented control buttons wrapping unexpectedly to a new line when using width='content' (default). The bug was caused by negative margins interfering with flexbox width calculations, leading to sub-pixel rounding errors.

Changes Made:

  • Remove pseudo-element

Root Cause:
The original implementation used negative right margins (-1px) to overlap borders between adjacent buttons. However, when flexbox calculates available space for wrapping, it computes flex-basis BEFORE considering negative margins. Combined with the ::after { flex: 10000 } pseudo-element trick used for content-width layouts, this caused precision errors in width calculations that triggered premature wrapping of the last button.

Additional Notes:

I was not able to reproduce the issue locally since we have to deterministic repro steps.

Removing the negative margins was the first attempt, but this leads to other style regressions when buttons wrap or are selected.

I am not sure in which scenario we need the pseudo-element, but we do have quite extensive regression test coverage and removing this does not lead to any failures. It could be that this element is not needed anymore with the other changes that were made to support more width options.

GitHub Issue Link

Fixes #12857

Testing Plan

  • Existing E2E Tests - Comprehensive coverage already exists in st_segmented_control_test.py
    • Tests various width scenarios (content, stretch, fixed pixels)
    • Visual snapshot comparisons for all configurations
    • Multi-select, single-select, disabled states, forms, fragments
  • Manual testing - Verified fix visually in browser across multiple scenarios
    • All buttons stay on single line
    • Seamless borders maintained (no visual regression)
    • Works in narrow columns, fixed widths, and default content width

Contribution License Agreement

By submitting this pull request you agree that all contributions to this project are made under the Apache 2.0 license.

…th border removal

Fixes #12857

Replaces negative marginRight approach with borderLeft removal to prevent flexbox width calculation errors that caused buttons to wrap unexpectedly.
@snyk-io
Copy link
Contributor

snyk-io bot commented Oct 28, 2025

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@github-actions
Copy link
Contributor

github-actions bot commented Oct 28, 2025

✅ PR preview is ready!

Name Link
📦 Wheel file https://core-previews.s3-us-west-2.amazonaws.com/pr-12879/streamlit-1.51.0-py3-none-any.whl
📦 @streamlit/component-v2-lib Download from artifacts
🕹️ Preview app pr-12879.streamlit.app (☁️ Deploy here if not accessible)

@sfc-gh-lwilby sfc-gh-lwilby added security-assessment-completed Security assessment has been completed for PR change:bugfix PR contains bug fix implementation impact:users PR changes affect end users labels Oct 28, 2025
@sfc-gh-lwilby sfc-gh-lwilby changed the title Fix segmented control wrapping issue [WIP] Fix segmented control wrapping issue Oct 28, 2025
@sfc-gh-lwilby sfc-gh-lwilby changed the title [WIP] Fix segmented control wrapping issue [fix] segmented control wrapping issue Oct 28, 2025
rowGap: spacing.twoXS,
// Adding an empty pseudo-element after the last button in the group.
// This will make buttons only as big as needed without stretching to the whole container width (aka let them 'hug' to the side)
// This is only needed if the button group has content width.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't see regression tests failing after removing this. Perhaps there are other changes that make it unnecessary now.

Copilot AI review requested due to automatic review settings November 24, 2025 23:02
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a bug where segmented control buttons wrap unexpectedly to a new line when using width='content' (default setting). The root cause was a pseudo-element with flex: 10000 that, combined with negative margins in BaseWeb, caused sub-pixel rounding errors in flexbox width calculations.

Key Changes:

  • Removed the segmentedControlNoStretch variable and its associated ::after pseudo-element that was causing precision errors in content-width layouts

@sfc-gh-lwilby
Copy link
Collaborator Author

Just for sanity sake I did another look at what this was used for and it looks like it was necessary due to the flex-grow: 1 property on the button prior to the width changes were added. Now, we don't add this if the button group is content-width (only case where pseudo-element is still used) so this seems safe to remove and clean up the implementation.

@sfc-gh-lwilby sfc-gh-lwilby enabled auto-merge (squash) November 24, 2025 23:09
@sfc-gh-lwilby sfc-gh-lwilby merged commit f30aaa8 into develop Nov 24, 2025
50 checks passed
@sfc-gh-lwilby sfc-gh-lwilby deleted the fix/segmented-control-wrapping-issue branch November 24, 2025 23:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

change:bugfix PR contains bug fix implementation impact:users PR changes affect end users security-assessment-completed Security assessment has been completed for PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

st.segmented control unnecessarily wraps

3 participants