Skip to content

Conversation

@sfc-gh-tteixeira
Copy link
Contributor

@sfc-gh-tteixeira sfc-gh-tteixeira commented Dec 13, 2025

Describe your changes

The SIZE in st.container(gap=SIZE), st.columns(gap=SIZE), st.space(SIZE) now supports smaller and larger settings:"xxsmall", "xsmall", "xlarge", and "xxlarge".

The smaller settings are important because the smallest today is 1rem, which is too large for many use cases, especially when laying out widgets next to each other. The larger settings are less important, but they're here mostly for symmetry -- though I could see them being useful to separate large sections of an app.

One weird thing: the existing SIZE settings for st.space do not match those for st.container/st.columns. There are reasons for that, but it's still somewhat funky. For this work I didn't touch any of this. But I also didn't contribute to making the problem larger. Insteade I just ignored it altogether and made the new st.space sizes match the ones I'm adding for st.container/st.columns.

Wishlist: If we didn't care about breaking changes, I'd love to make the default gap be medium rather than small, and make medium mean 1rem (same as today's small). But we'll have to fight that fight some other day!

Screenshot or video (only for visual changes)

See e2e snapshot updates.

GitHub Issue Link (if applicable)

n/a

Testing Plan

  • Explanation of why no additional tests are needed
  • ✅ Unit Tests (JS and/or Python)
  • ✅ E2E Tests
  • Any manual testing needed?

Contribution License Agreement

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

@sfc-gh-tteixeira sfc-gh-tteixeira requested a review from a team as a code owner December 13, 2025 13:48
Copilot AI review requested due to automatic review settings December 13, 2025 13:48
@snyk-io
Copy link
Contributor

snyk-io bot commented Dec 13, 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 Dec 13, 2025

✅ PR preview is ready!

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

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 extends the gap and size options for st.container, st.columns, and st.space by adding four new settings: "xxsmall" (0.25rem), "xsmall" (0.5rem), "xlarge" (6rem), and "xxlarge" (8rem). The smaller sizes address the need for tighter spacing when laying out widgets, while the larger sizes provide symmetry and enable separating major app sections.

Key changes:

  • Extended the GapSize protobuf enum with four new values (XXSMALL, XSMALL, XLARGE, XXLARGE)
  • Updated Python backend type definitions, validation, error messages, and documentation
  • Added frontend spacing values (fiveXL, sixXL) and updated gap translation logic
  • Refactored E2E tests to comprehensively cover all gap/size options using loops

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
proto/streamlit/proto/GapSize.proto Adds four new gap size enum values to support the extended size range
lib/streamlit/elements/lib/layout_utils.py Updates type aliases, SIZE_TO_REM_MAPPING, validation logic, and gap_mapping to include new sizes
lib/streamlit/elements/space.py Updates docstring to document the new xxsmall, xsmall, xlarge, and xxlarge size options
lib/streamlit/elements/layouts.py Updates docstrings for st.container and st.columns to document the new gap options
lib/streamlit/errors.py Updates error message to include all seven valid gap size options
lib/tests/streamlit/elements/space_test.py Adds parameterized test cases for the four new space sizes
lib/tests/streamlit/elements/lib/layout_utils_test.py Adds parameterized test cases for new sizes in validation and config tests
frontend/lib/src/theme/primitives/spacing.ts Adds fiveXL (6rem) and sixXL (8rem) spacing values
frontend/lib/src/components/core/Block/styled-components.ts Updates translateGapWidth switch statement to handle all new gap sizes
e2e_playwright/st_space.py Refactors test to loop through all space sizes including new ones
e2e_playwright/st_layouts_container_gap_size.py Refactors test to loop through all gap sizes for both horizontal and vertical containers
e2e_playwright/st_columns.py Refactors test to loop through all gap sizes for column layouts

@github-actions
Copy link
Contributor

github-actions bot commented Dec 13, 2025

📉 Frontend coverage change detected

The frontend unit test (vitest) coverage has decreased by 0.0000%

  • Current PR: 86.5100% (12761 lines, 1721 missed)
  • Latest develop: 86.5100% (12759 lines, 1720 missed)

✅ Coverage change is within normal range.

📊 View detailed coverage comparison

width="stretch",
)
if TYPE_CHECKING:
from streamlit.elements.lib.layout_utils import Gap
st.space("small")
st.write("After small space")
if TYPE_CHECKING:
from streamlit.elements.lib.layout_utils import Gap
Comment on lines 44 to 48
for height_em in heights_em:
height_px = round(height_em * 16)
space = space_elements.nth(0)

wait_until(app, wait_for(space, height_px))
Copy link
Contributor

Choose a reason for hiding this comment

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

The test loop always checks space_elements.nth(0) (the first space element) for all height values, which will cause test failures. The loop should iterate through different space elements using an incrementing index.

Fix:

for i, height_em in enumerate(heights_em):
    height_px = round(height_em * 16)
    space = space_elements.nth(i)
    
    wait_until(app, wait_for(space, height_px))
Suggested change
for height_em in heights_em:
height_px = round(height_em * 16)
space = space_elements.nth(0)
wait_until(app, wait_for(space, height_px))
for i, height_em in enumerate(heights_em):
height_px = round(height_em * 16)
space = space_elements.nth(i)
wait_until(app, wait_for(space, height_px))

Spotted by Graphite Agent

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

@sfc-gh-tteixeira sfc-gh-tteixeira added security-assessment-completed Security assessment has been completed for PR area:layout Related to layout and positioning type:enhancement Requests for feature enhancements or new features change:feature PR contains new feature or enhancement implementation impact:users PR changes affect end users labels Dec 29, 2025
@mayagbarnes mayagbarnes added the ai-review If applied to PR or issue will run AI review workflow label Dec 31, 2025
@github-actions github-actions bot removed the ai-review If applied to PR or issue will run AI review workflow label Dec 31, 2025
@github-actions
Copy link
Contributor

Summary

This PR adds four new gap/space size options (xxsmall, xsmall, xlarge, xxlarge) to st.container, st.columns, and st.space. The smaller sizes (0.25rem and 0.5rem) address a user need for tighter spacing when laying out widgets next to each other, while the larger sizes (6rem and 8rem) provide options for separating large sections of an app.

Key changes:

  • Proto: Added new GapSize enum values (XXSMALL=5, XSMALL=6, XLARGE=7, XXLARGE=8)
  • Backend: Updated SIZE_TO_REM_MAPPING, type aliases, validation functions, and docstrings
  • Frontend: Added spacing primitives and gap translation logic with a cleaner switch statement
  • Tests: Comprehensive unit tests (Python and TypeScript) and E2E tests with snapshots

Code Quality

The code is well-structured and follows existing patterns in the codebase:

  1. Clean refactoring (frontend/lib/src/components/core/Block/styled-components.ts lines 31-50): The change from if/else chains to a switch statement is a good improvement that makes the gap mapping clearer and more maintainable.

  2. Consistent type definitions (lib/streamlit/elements/lib/layout_utils.py lines 38-46): The SpaceSize and Gap type aliases are properly updated with all new size options.

  3. Well-documented docstrings (lib/streamlit/elements/layouts.py, lib/streamlit/elements/space.py): All public API docstrings are updated with the new size options and their corresponding rem values.

  4. Error message updated (lib/streamlit/errors.py lines 267-270): The StreamlitInvalidColumnGapError now lists all valid gap options.

Test Coverage

Excellent test coverage across all layers:

Python Unit Tests

  • lib/tests/streamlit/elements/space_test.py: Parameterized tests for all 7 rem sizes (xxsmall through xxlarge)
  • lib/tests/streamlit/elements/lib/layout_utils_test.py: Tests for validation and config generation functions

TypeScript Unit Tests

  • frontend/lib/src/components/core/Block/Block.test.tsx (lines 221-256): Added it.each parameterized tests for all new gap sizes verifying correct CSS output

E2E Tests

  • st_columns_test.py: Tests all gap sizes with snapshots
  • st_space_test.py: Tests all space sizes with dynamic height verification
  • st_layouts_container_gap_size_test.py: Refactored to cleanly loop through all gap options

The E2E tests follow best practices:

  • ✅ Use expect for auto-wait assertions
  • ✅ Use descriptive test names following st_command-test_description pattern
  • ✅ Screenshot specific elements, not full pages
  • ✅ Use parameterized loops to avoid code duplication

Backwards Compatibility

This PR is fully backwards compatible:

  1. Proto enum values: New values are added at the end with sequential numbers (5, 6, 7, 8), preserving all existing values (GAP_UNDEFINED=0, SMALL=1, MEDIUM=2, LARGE=3, NONE=4)

  2. Additive changes only: All existing sizes (small, medium, large) retain their original values and behavior

  3. Default behavior unchanged: The default gap for containers/columns remains small (1rem)

  4. No breaking changes to the public API

Security & Risk

No security concerns identified. These are purely additive visual/layout changes:

  • No user input processing changes
  • No authentication/authorization changes
  • No data handling changes
  • No network communication changes

Regression risk is low:

  • Existing gap sizes are unchanged
  • Comprehensive test coverage validates new functionality
  • Visual snapshots catch any unintended rendering changes

Recommendations

No blocking issues. A few minor observations:

  1. Documentation note (informational only): The comment in layout_utils.py line 52-53 references sizes.ts but the gap values are actually defined in spacing.ts. This is a pre-existing documentation inconsistency, not introduced by this PR.

  2. Acknowledged quirk: As the PR author notes, st.space size values don't perfectly align with st.container/st.columns gap values for small, medium, large (e.g., small space = 0.75rem vs small gap = 1rem). The new sizes (xxsmall, xsmall, xlarge, xxlarge) do align, which is a reasonable approach that doesn't worsen the existing asymmetry.

Verdict

APPROVED: This is a well-implemented feature addition with excellent test coverage, clean code, and full backwards compatibility. The new gap sizes address a real user need for finer-grained layout control.


This is an automated AI review. Please verify the feedback and use your judgment.

Copy link
Collaborator

@mayagbarnes mayagbarnes left a comment

Choose a reason for hiding this comment

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

Couple comments but overall LGTM 👍🏼

@sfc-gh-tteixeira sfc-gh-tteixeira enabled auto-merge (squash) January 3, 2026 15:52
@sfc-gh-tteixeira sfc-gh-tteixeira merged commit cffc27d into develop Jan 3, 2026
43 checks passed
@sfc-gh-tteixeira sfc-gh-tteixeira deleted the xsmall branch January 3, 2026 20:42
majiayu000 pushed a commit to majiayu000/streamlit that referenced this pull request Jan 9, 2026
…er/columns/space (streamlit#13345)

## Describe your changes

The `SIZE` in `st.container(gap=SIZE)`, `st.columns(gap=SIZE)`,
`st.space(SIZE)` now supports smaller and larger settings:`"xxsmall"`,
`"xsmall"`, `"xlarge"`, and `"xxlarge"`.

The smaller settings are important because the smallest today is `1rem`,
which is too large for many use cases, especially when laying out
widgets next to each other. The larger settings are less important, but
they're here mostly for symmetry -- though I _could_ see them being
useful to separate large sections of an app.

One weird thing: the existing `SIZE` settings for `st.space` do not
match those for `st.container`/`st.columns`. There are reasons for that,
but it's still somewhat funky. For this work I didn't touch any of this.
But I also didn't contribute to making the problem larger. Insteade I
just ignored it altogether and made the new `st.space` sizes match the
ones I'm adding for `st.container`/`st.columns`.

Wishlist: If we didn't care about breaking changes, I'd love to make the
default gap be `medium` rather than `small`, and make `medium` mean
`1rem` (same as today's `small`). But we'll have to fight that fight
some other day!

## Screenshot or video (only for visual changes)

See e2e snapshot updates.

## GitHub Issue Link (if applicable)

n/a

## Testing Plan

- ~~Explanation of why no additional tests are needed~~
- ✅ Unit Tests (JS and/or Python)
- ✅ E2E Tests
- ~~Any manual testing needed?~~

---

**Contribution License Agreement**

By submitting this pull request you agree that all contributions to this
project are made under the Apache 2.0 license.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:layout Related to layout and positioning change:feature PR contains new feature or enhancement implementation impact:users PR changes affect end users security-assessment-completed Security assessment has been completed for PR type:enhancement Requests for feature enhancements or new features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants