Skip to content

[feature] Add alignment parameter to column_config columns#14333

Merged
lukasmasuch merged 8 commits intodevelopfrom
lukasmasuch/column-alignment
Mar 16, 2026
Merged

[feature] Add alignment parameter to column_config columns#14333
lukasmasuch merged 8 commits intodevelopfrom
lukasmasuch/column-alignment

Conversation

@lukasmasuch
Copy link
Copy Markdown
Collaborator

@lukasmasuch lukasmasuch commented Mar 11, 2026

Describe your changes

Adds an alignment parameter to st.column_config.Column and all typed column configs (TextColumn, NumberColumn, etc.) that controls horizontal text alignment (left, center, right) of cell content in st.dataframe and st.data_editor.

  • Adds ContentAlignment type alias (Literal["left", "center", "right"])
  • Adds alignment parameter to all 19 column config functions
  • Default is None, which preserves existing column-type-specific defaults

The frontend already supports this via Glide Data Grid's contentAlign property - this PR exposes it in the Python API.

The following column types do not support alignment: SelectboxColumn, ListColumn, MultiselectColumn, BarChartColumn, LineChartColumn, AreaChartColumn, ProgressColumn.

GitHub Issue Link (if applicable)

Testing Plan

  • Unit Tests
    • lib/tests/streamlit/elements/lib/column_types_test.py — Tests alignment parameter on all column types
  • E2E Tests
    • e2e_playwright/st_dataframe_config_test.py — Visual regression test for alignment

Product Spec

  • See specs/2026-03-11-dataframe-column-alignment/product-spec.md
Agent metrics
Type Name Count
skill checking-changes 2
skill finalizing-pr 1
skill updating-internal-docs 2
subagent fixing-pr 2
subagent general-purpose 7
subagent reviewing-local-changes 2
subagent simplifying-local-changes 2

Add alignment parameter to st.column_config.Column and all typed column
configs to control horizontal text alignment in dataframe cells. The
frontend already supports this via Glide Grid's contentAlign property.

- Add ContentAlignment type alias (Literal["left", "center", "right"])
- Add alignment parameter to all 19 column config functions
- Add unit tests and E2E test for alignment
- Add product spec for the feature

Closes #12106

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Copilot AI review requested due to automatic review settings March 11, 2026 16:23
@lukasmasuch lukasmasuch added change:feature PR contains new feature or enhancement implementation impact:users PR changes affect end users labels Mar 11, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 11, 2026

✅ PR preview is ready!

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

@snyk-io
Copy link
Copy Markdown
Contributor

snyk-io bot commented Mar 11, 2026

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

Status Scan Engine 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.

Copy link
Copy Markdown
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 exposes horizontal cell-content alignment in st.dataframe / st.data_editor by adding an alignment parameter to st.column_config.Column and all typed column config helpers, leveraging the frontend’s existing support for Glide Data Grid contentAlign.

Changes:

  • Added ContentAlignment type alias and alignment to ColumnConfig plus all column config helper functions.
  • Added Python unit tests to ensure alignment is propagated into the produced column config dict.
  • Extended the Playwright dataframe configuration screenshot test app + assertions to cover alignment.

Reviewed changes

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

Show a summary per file
File Description
specs/2026-03-11-dataframe-column-alignment/product-spec.md New product spec describing the alignment API and intended behavior.
lib/streamlit/elements/lib/column_types.py Adds ContentAlignment + alignment to Column() and all typed column configs, and updates docstrings/types.
lib/tests/streamlit/elements/lib/column_types_test.py Adds unit tests for alignment propagation and default omission behavior.
e2e_playwright/st_dataframe_config.py Adds a new “Column alignment” example dataframe for visual verification.
e2e_playwright/st_dataframe_config_test.py Increments expected dataframe count and adds a new snapshot assertion for the alignment example.

@lukasmasuch lukasmasuch added the update-snapshots Trigger snapshot autofix workflow label Mar 11, 2026
@github-actions github-actions bot removed the update-snapshots Trigger snapshot autofix workflow label Mar 11, 2026
Updated the alignment parameter docstring for NumberColumn to note
that some number-like types (e.g., durations) may use a different
default alignment.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@github-actions
Copy link
Copy Markdown
Contributor

⚠️ Snapshot Autofix Failed

The snapshot autofix workflow could not update snapshots. This can happen if:

  • The Playwright E2E tests passed (no snapshot mismatches to fix)
  • No Playwright workflow run was found for the current commit
  • The snapshot artifacts could not be downloaded

Please check the workflow run logs for details.

If you need to update snapshots manually, you can:

  1. Download the snapshot artifacts from the failed Playwright workflow run
  2. Extract them to e2e_playwright/__snapshots__/
  3. Commit and push the changes

You can re-run this workflow by removing and re-adding the update-snapshots label.

@lukasmasuch lukasmasuch added the update-snapshots Trigger snapshot autofix workflow label Mar 11, 2026
@github-actions github-actions bot removed the update-snapshots Trigger snapshot autofix workflow label Mar 11, 2026
## Describe your changes

Automated snapshot updates for #14333 created via the snapshot autofix
CI workflow.

This workflow was triggered by adding the `update-snapshots` label to a
PR after Playwright E2E tests failed with snapshot mismatches.

**Updated snapshots:** 6 file(s)

⚠️ **Please review the snapshot changes carefully** - they could mask
visual bugs if accepted blindly.

This PR targets a feature branch and can be merged without review
approval.

Co-authored-by: Streamlit Bot <[email protected]>
@lukasmasuch lukasmasuch added the ai-review If applied to PR or issue will run AI review workflow label Mar 11, 2026
@github-actions github-actions bot removed the ai-review If applied to PR or issue will run AI review workflow label Mar 11, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Summary

This PR adds an alignment parameter to st.column_config.Column and all 19 typed column config functions (TextColumn, NumberColumn, CheckboxColumn, etc.) that controls horizontal text alignment ("left", "center", "right") of cell content in st.dataframe and st.data_editor. The frontend already supported this via Glide Data Grid's contentAlign property; this PR exposes it through the Python public API.

Key changes:

  • lib/streamlit/elements/lib/column_types.py: Adds ContentAlignment type alias (Literal["left", "center", "right"]), adds alignment parameter to all 19 column config functions with proper docstrings, and refactors the existing TypedDict field to use the new alias.
  • lib/tests/streamlit/elements/lib/column_types_test.py: Unit tests covering alignment on all column types plus a None-default exclusion test.
  • e2e_playwright/st_dataframe_config.py / *_test.py: E2E app scenario and visual regression snapshot test for column alignment.
  • Snapshot images: 6 new screenshots (light/dark × chromium/firefox/webkit).
  • specs/: Product spec document.

Code Quality

All three reviewers agree: the code is clean, well-typed, and follows existing codebase patterns precisely. Specific points of consensus:

  • The ContentAlignment type alias is well-placed and consistently used across all function signatures.
  • The alignment parameter is uniformly positioned (after pinned) and is keyword-only in all functions, following the existing convention.
  • Docstrings follow Numpydoc style and are appropriately customized per column type (e.g., NumberColumn mentions right-alignment default, TextColumn mentions left-alignment default).
  • Every return ColumnConfig(...) call correctly passes alignment=alignment.

No code quality issues were identified by any reviewer.

Test Coverage

All three reviewers agree: test coverage is thorough and adequate.

  • Unit tests use @pytest.mark.parametrize over ["left", "center", "right"] to verify alignment across all 19 column types. A separate test verifies None default exclusion via remove_none_values.
  • E2E tests add a visual regression snapshot (element index 35) with NUM_DATAFRAME_ELEMENTS correctly incremented from 35 to 36, covering all three browsers and both themes.
  • One reviewer (opus-4.6-thinking) noted the absence of invalid-value tests, but correctly observed that this is consistent with the codebase convention — other config params like width and pinned also lack runtime validation, relying on Literal typing + mypy instead.

Backwards Compatibility

Unanimous agreement: fully backwards compatible.

  • alignment defaults to None, preserving existing type-specific default alignments.
  • Keyword-only parameter — cannot break positional argument usage.
  • The alignment field already existed in the ColumnConfig TypedDict, so no serialization changes are needed.
  • No frontend or protobuf changes required (column config is JSON-serialized).

Security & Risk

Unanimous agreement: no security concerns. The change is purely additive to the Python API and maps to an already-supported frontend rendering property. No changes to routing, auth, WebSocket handling, embedding, assets, or cross-origin behavior. Regression risk is very low.

External test recommendation

  • Recommend external_test: No (all three reviewers agree)
  • Triggered categories: None
  • Confidence: High
  • The changes are purely UI configuration and do not interact with any externally-sensitive surfaces.

Accessibility

All reviewers agree: no accessibility concerns. The alignment is purely visual (CSS text-align-equivalent via Glide Data Grid's contentAlign), with no impact on screen readers, keyboard navigation, focus management, or ARIA attributes.

Reviewer Agreement & Conflict Resolution

All three reviewers (gemini-3.1-pro, gpt-5.3-codex-high, opus-4.6-thinking) are in complete agreement on all dimensions: code quality, test coverage, backwards compatibility, security, accessibility, and verdict. No conflicts to resolve.

Minor differences in optional recommendations are noted below — none are blocking.

Recommendations

No blocking issues. Optional follow-up suggestions from individual reviewers (non-blocking):

  1. Typing test (gpt-5.3-codex-high): Consider adding a typing test under lib/tests/streamlit/typing/ to lock in accepted alignment literal values at the public API level.
  2. Export ContentAlignment (opus-4.6-thinking): The new ContentAlignment type alias is not currently exported via st.column_config (confirmed: not in lib/streamlit/column_config.py). Could be useful for users doing type-checked column config construction.
  3. st.data_editor E2E test (gpt-5.3-codex-high): Consider adding a focused st.data_editor e2e assertion for alignment to complement the dataframe visual scenario.

Missing Reviews

All expected models completed their reviews:

  • gemini-3.1-pro: Completed
  • gpt-5.3-codex-high: Completed
  • opus-4.6-thinking: Completed

Verdict

APPROVED: All three reviewers unanimously approve. The implementation is clean, additive, well-tested (unit + E2E + visual regression), fully backwards-compatible, and carries no security or regression risk. It correctly exposes an already-supported frontend capability through the Python API, following existing codebase patterns precisely.


This is a consolidated AI review by opus-4.6-thinking.


📋 Review by `gemini-3.1-pro`

Summary

This PR adds an alignment parameter to st.column_config.Column and all typed column configs (TextColumn, NumberColumn, etc.). This allows users to control the horizontal text alignment (left, center, right) of cell content in st.dataframe and st.data_editor. The frontend already supported this via Glide Data Grid's contentAlign property, and this PR effectively exposes it in the Python API.

Code Quality

The code changes are clean, well-typed, and follow the existing patterns in lib/streamlit/elements/lib/column_types.py. The alignment parameter is correctly added to the ColumnConfig TypedDict and propagated through all column configuration functions. Docstrings have been updated consistently across all functions to explain the new parameter and its default behavior.

Test Coverage

The test coverage is excellent:

  • Unit tests in lib/tests/streamlit/elements/lib/column_types_test.py use @pytest.mark.parametrize to effectively test the new parameter across all column types, and verify that it correctly defaults to None and is omitted from the output when not set.
  • E2E tests in e2e_playwright/st_dataframe_config.py and e2e_playwright/st_dataframe_config_test.py add a visual regression test for the new alignment configurations, ensuring the frontend correctly renders the alignments.

Backwards Compatibility

The change is fully backwards compatible. The alignment parameter defaults to None, which preserves the existing type-specific default alignments on the frontend.

Security & Risk

No security concerns. The change only exposes an existing frontend property to the Python API and does not introduce any new dependencies, execution paths, or cross-origin behaviors.

External test recommendation

  • Recommend external_test: No
  • Triggered categories: None
  • Evidence:
    • lib/streamlit/elements/lib/column_types.py: Only adds a new parameter to the column configuration API.
    • e2e_playwright/st_dataframe_config.py: Adds UI test cases for the new parameter.
  • Suggested external_test focus areas: N/A
  • Confidence: High
  • Assumptions and gaps: None. The changes are purely related to UI configuration and do not interact with routing, auth, or embedding boundaries.

Accessibility

The alignment changes are visual and rely on the underlying Glide Data Grid implementation. No negative impact on accessibility is expected.

Recommendations

None. The PR is well-implemented, well-tested, and ready to merge.

Verdict

APPROVED: The PR successfully exposes the column alignment feature with excellent code quality and test coverage.


This is an automated AI review by gemini-3.1-pro. Please verify the feedback and use your judgment.

📋 Review by `gpt-5.3-codex-high`

Summary

This PR adds an alignment API parameter to st.column_config.Column and all typed column config helpers, then validates the feature with Python unit tests and a new dataframe snapshot scenario. The implementation is additive and keeps existing default alignment behavior when alignment=None.

Code Quality

The implementation is consistent and maintainable:

  • lib/streamlit/elements/lib/column_types.py introduces a shared ContentAlignment type alias and reuses it across ColumnConfig and every *Column function signature.
  • Each column helper forwards alignment through to the returned ColumnConfig object, so behavior is uniform across column types.
  • Docstrings were updated alongside signatures, including the NumberColumn-specific caveat for number-like types with potentially different default alignment behavior.

No code-quality issues were identified that should block merge.

Test Coverage

Coverage is good for this scope:

  • Unit tests in lib/tests/streamlit/elements/lib/column_types_test.py validate alignment for all column config helpers and verify default omission when unset.
  • E2E coverage in e2e_playwright/st_dataframe_config.py + e2e_playwright/st_dataframe_config_test.py adds a dedicated visual scenario and corresponding snapshots for all three browsers/themes.
  • Snapshot count updates in the e2e test were adjusted correctly (NUM_DATAFRAME_ELEMENTS = 36), matching the additional dataframe section.

Overall, tests are adequate for this change.

Backwards Compatibility

No breaking changes found:

  • alignment is an optional keyword-only parameter with default None.
  • Existing user code paths remain unchanged unless users opt in.
  • Default column-type alignment behavior is preserved when alignment is not set.

Security & Risk

No security-sensitive surfaces are modified. The PR does not touch auth/session logic, routes, websocket transport, asset serving, CSP/CORS, storage, or dynamic code execution paths. Regression risk is low and mostly limited to display alignment behavior in dataframes/data editors.

External test recommendation

  • Recommend external_test: No
  • Triggered categories: None
  • Evidence:
    • lib/streamlit/elements/lib/column_types.py: API surface/docstring/type updates for column config only; no routing/auth/websocket/embedding/network/security-header changes.
    • lib/tests/streamlit/elements/lib/column_types_test.py: unit tests for alignment propagation/default behavior only.
    • e2e_playwright/st_dataframe_config.py and e2e_playwright/st_dataframe_config_test.py: local visual regression scenario only; no external-host or cross-origin behavior changes.
  • Suggested external_test focus areas:
    • None required for this PR.
  • Confidence: High
  • Assumptions and gaps:
    • Assumes existing frontend contentAlignment plumbing (already in place) remains unchanged and is already covered by existing integration paths.

Accessibility

No direct accessibility regressions were identified. The change affects horizontal content alignment only and does not alter semantics, keyboard interaction, focus management, or ARIA behavior. Snapshot tests provide visual confidence but do not replace dedicated accessibility assertions.

Recommendations

  1. Optional follow-up: add a typing test under lib/tests/streamlit/typing/ to lock in accepted alignment literal values at the public API level.
  2. Optional follow-up: add a focused st.data_editor e2e assertion for alignment to complement the dataframe visual scenario.

Verdict

APPROVED: The implementation is clean, additive, well-tested for the feature scope, and ready for merge.


This is an automated AI review by gpt-5.3-codex-high. Please verify the feedback and use your judgment.

📋 Review by `opus-4.6-thinking`

Summary

This PR adds an alignment parameter to st.column_config.Column and all 19 typed column config functions (TextColumn, NumberColumn, CheckboxColumn, etc.) that controls horizontal text alignment ("left", "center", "right") of cell content in st.dataframe and st.data_editor.

The change is purely an API-exposure task — the alignment field already existed in the ColumnConfig TypedDict and the frontend already wires contentAlignment to Glide Data Grid's contentAlign property. This PR simply exposes the parameter in the Python public API.

Key changes:

  • lib/streamlit/elements/lib/column_types.py: Adds ContentAlignment type alias, adds alignment parameter to all 19 column config functions with proper docstrings, and refactors the existing TypedDict field to use the new type alias.
  • lib/tests/streamlit/elements/lib/column_types_test.py: Unit tests covering alignment on all column types plus a None-default test.
  • e2e_playwright/st_dataframe_config.py / *_test.py: E2E app and visual regression snapshot test for column alignment.
  • Snapshot images: 6 new screenshots (light/dark × chromium/firefox/webkit).
  • specs/: Product spec document.

Code Quality

The code is clean, consistent, and follows existing patterns precisely. Specific observations:

  • The ContentAlignment type alias (Literal["left", "center", "right"]) is well-placed and properly used across all function signatures — replacing the inline Literal in the TypedDict field.
  • The alignment parameter is consistently positioned after pinned in all function signatures, maintaining a uniform API surface.
  • Docstrings follow Numpydoc style, are descriptive, and appropriately customized per column type (e.g., NumberColumn mentions right-alignment default, TextColumn mentions left-alignment default).
  • Every return ColumnConfig(...) call correctly passes alignment=alignment.
  • The parameter is keyword-only (after *) in all functions, following the existing pattern.

No issues found.

Test Coverage

Unit Tests (lib/tests/streamlit/elements/lib/column_types_test.py):

  • test_column_alignment: Parametrized over ["left", "center", "right"], verifies the alignment value is correctly set on all 19 column types. Good coverage.
  • test_column_alignment_none_by_default: Verifies that None default means alignment is excluded from the output dict when remove_none_values is applied. This is the correct negative/boundary test.

E2E Tests (e2e_playwright/st_dataframe_config_test.py):

  • Adds a visual regression snapshot test for a new dataframe element demonstrating left, center, and right alignment across text, number, and checkbox columns. Covers both light and dark themes across 3 browsers.
  • NUM_DATAFRAME_ELEMENTS is correctly incremented from 35 to 36.

Coverage assessment: Tests adequately cover the happy path (all three alignment values on all column types), the default behavior (None exclusion), and visual appearance (E2E snapshots). One minor observation: there is no test for invalid alignment values (e.g., passing "justify" or 123), but since the parameter is typed as Literal["left", "center", "right"] | None, mypy will catch such misuse at type-checking time, and there's no runtime validation in the existing pattern (other column config params like width and pinned also don't validate at runtime). This is consistent with the codebase convention.

Backwards Compatibility

Fully backwards compatible:

  • The alignment parameter defaults to None on all functions, preserving existing behavior.
  • It's keyword-only, so it cannot break positional argument usage.
  • The alignment field already existed in the ColumnConfig TypedDict, so no serialization changes are needed.
  • The frontend already handled contentAlignment — no frontend changes were required.
  • No protobuf changes needed (column config is JSON-serialized).

Security & Risk

No security concerns:

  • No new dependencies introduced.
  • No changes to server endpoints, WebSocket handling, authentication, or file serving.
  • No HTML/Markdown rendering or sanitization changes.
  • No external network requests or dynamic code execution.
  • The change is purely additive to the Python API and maps to an already-supported frontend rendering property.

Regression risk is very low — the only code path affected is column config construction, and the None default ensures existing behavior is unchanged.

External test recommendation

  • Recommend external_test: No
  • Triggered categories: None
  • Evidence:
    • lib/streamlit/elements/lib/column_types.py: Pure Python API parameter addition, no routing/auth/embedding/asset changes
    • e2e_playwright/st_dataframe_config.py: Standard E2E app script, no external dependencies
    • No frontend code changes — the contentAlignment mapping already existed
  • Suggested external_test focus areas: N/A
  • Confidence: High
  • Assumptions and gaps: None. This is a purely additive Python API change that maps to an already-working frontend feature. No network, auth, embedding, or cross-origin behavior is affected.

Accessibility

No accessibility concerns. The alignment parameter controls CSS text-align-equivalent rendering inside Glide Data Grid cells. This is a visual presentation change only — it does not affect:

  • Screen reader behavior (cell content is unchanged)
  • Keyboard navigation
  • Focus management
  • ARIA attributes

The alignment is applied via Glide Data Grid's built-in contentAlign property, which handles rendering correctly.

Recommendations

No blocking issues. A few minor, non-blocking observations:

  1. Consider exporting ContentAlignment type alias: The new ContentAlignment type alias could be useful for users doing type-checked column config construction. It's not currently exported via st.column_config (in lib/streamlit/column_config.py). This is a low-priority enhancement that could be done in a follow-up if there's user demand.

  2. Spec file in repo: The specs/2026-03-11-dataframe-column-alignment/product-spec.md is included in the PR. Verify this aligns with the team's convention for checking in spec files (appears consistent with the specs/ directory existing in the repo).

Verdict

APPROVED: Clean, well-tested, fully backwards-compatible feature that exposes an already-supported frontend capability through the Python API. The implementation is consistent with existing codebase patterns, has good test coverage (unit + E2E + visual regression), and carries no security or regression risk.


This is an automated AI review by opus-4.6-thinking.

@lukasmasuch lukasmasuch changed the title [feature] Add alignment parameter to column config [feature] Add alignment parameter to column_config columns Mar 11, 2026
lukasmasuch and others added 2 commits March 11, 2026 19:31
Several column types (SelectboxColumn, chart columns, ProgressColumn,
ListColumn, MultiselectColumn) use third-party or custom renderers that
don't honor glide-data-grid's contentAlign property. This removes the
alignment parameter from these columns to avoid misleading users.

Also updates the E2E test to use right-aligned checkbox (instead of
center) to actually demonstrate the alignment feature works, since
checkboxes are center-aligned by default.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@lukasmasuch lukasmasuch added the ai-review If applied to PR or issue will run AI review workflow label Mar 11, 2026
@github-actions github-actions bot removed the ai-review If applied to PR or issue will run AI review workflow label Mar 11, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Summary

This PR adds an alignment parameter to st.column_config.Column and 11 typed column config variants (TextColumn, NumberColumn, CheckboxColumn, DateColumn, TimeColumn, DatetimeColumn, LinkColumn, ImageColumn, AudioColumn, VideoColumn, JsonColumn), enabling users to control horizontal text alignment ("left", "center", "right") of cell content in st.dataframe and st.data_editor. It also fixes an operator precedence bug in the frontend NumberColumn.ts where || was incorrectly used instead of ??, causing custom alignment values to be ignored.

Column types that use custom renderers (SelectboxColumn, ListColumn, MultiselectColumn, ProgressColumn, BarChartColumn, LineChartColumn, AreaChartColumn) correctly do not receive the parameter, as Glide Data Grid's contentAlign does not apply to them.

Reviewer Agreement

All three reviewers (gemini-3.1-pro, gpt-5.3-codex-high, opus-4.6-thinking) are in unanimous agreement on all major points:

Aspect Consensus
Code quality Clean, well-structured, follows existing patterns
Bug fix correctness `
Backwards compatibility Fully compatible; additive keyword-only params defaulting to None
Test coverage Adequate across Python unit, frontend unit, and E2E layers
Security risk None
External test needed No
Accessibility impact Neutral
Verdict All three: APPROVED

No disagreements were found between any of the reviewers.

Code Quality

The implementation is clean and consistent:

  • Backend: A ContentAlignment type alias is introduced, and the alignment parameter is consistently added to all applicable column config functions with proper docstrings and consistent parameter ordering (after pinned).
  • Frontend bug fix: The change from props.contentAlignment || useArrowFormatting ? "left" : "right" to props.contentAlignment ?? (useArrowFormatting ? "left" : "right") in NumberColumn.ts (line 103) correctly fixes the operator precedence issue where || binds tighter than ?:, causing any truthy custom alignment to resolve to "left".
  • The alignment field already existed in the ColumnConfig TypedDict but was not previously exposed in the Python API function signatures—this PR surfaces it cleanly.

Test Coverage

Coverage is thorough and appropriately layered:

  • Python unit tests (column_types_test.py): Tests all 12 supported column types with all three alignment values via @pytest.mark.parametrize, plus default-value verification.
  • Frontend unit tests (NumberColumn.test.ts): Parameterized tests for all three contentAlignment values on the column with the code change.
  • E2E tests (st_dataframe_config_test.py): Visual snapshot tests covering alignment combinations across browsers and themes. NUM_DATAFRAME_ELEMENTS correctly updated from 35 to 36.

Backwards Compatibility

Fully backwards compatible. No breaking changes: all new parameters are keyword-only with None defaults, no protobuf changes needed (column config is JSON-serialized), and the NumberColumn.ts fix only changes behavior when contentAlignment is explicitly set—which was not possible via the Python API prior to this PR.

Security & Risk

No security concerns. Changes are limited to UI rendering configuration (column alignment) with no impact on auth, networking, WebSocket handling, file serving, or code execution paths.

External test recommendation

  • Recommend external_test: No
  • Triggered categories: None
  • Confidence: High
  • The change surface is narrow and entirely within the dataframe column config pipeline.

Accessibility

Accessibility-neutral. Cell alignment is a visual styling property in Glide Data Grid's canvas rendering. No ARIA attributes or semantic HTML are affected. Default alignment conventions (numbers right-aligned, text left-aligned) are preserved.

Recommendations

  1. (Non-blocking, cosmetic) Consider updating MediaColumn.ts:43 and ImageColumn.ts:36 to use ?? instead of || for default alignment fallback, for consistency with the NumberColumn.ts fix. While functionally equivalent (the only falsy value is undefined), ?? is more idiomatic. (Raised by opus-4.6-thinking)

  2. (Non-blocking) Consider adding ContentAlignment to the __all__ export list in column_config.py so users can import it for type annotations. Note that other type aliases (ColumnWidth, NumberFormat, DateTimeFormat) are also not exported, so this would be a broader enhancement. (Raised by opus-4.6-thinking)

  3. (Non-blocking) Consider updating the PR description to reflect the final scope (alignment added to supported column types, not all typed columns) to avoid reviewer confusion. (Raised by gpt-5.3-codex-high)

Verdict

APPROVED: All three reviewers unanimously approved. The PR is a clean, well-tested, backwards-compatible feature addition that exposes an existing frontend capability through the Python API, accompanied by a correct operator precedence bug fix in NumberColumn.ts. No blocking issues identified.


This is a consolidated AI review by opus-4.6-thinking, synthesizing reviews from gemini-3.1-pro, gpt-5.3-codex-high, and opus-4.6-thinking.


📋 Review by `gemini-3.1-pro`

Summary

This PR introduces a new alignment parameter to st.column_config.Column and its typed variants (e.g., TextColumn, NumberColumn). This allows users to explicitly control the horizontal text alignment ("left", "center", "right") of cell content in st.dataframe and st.data_editor. It also fixes a bug in the frontend NumberColumn where custom alignment was previously ignored due to a logical OR (||) instead of a nullish coalescing operator (??).

Code Quality

The code is well-structured and follows the established patterns for adding parameters to column_config.

  • The Python backend correctly propagates the alignment parameter and includes clear, NumPy-style docstrings.
  • The frontend fix in frontend/lib/src/components/widgets/DataFrame/columns/NumberColumn.ts (line 103) correctly replaces || with ??, ensuring that custom alignment values like "center" or "right" are respected instead of defaulting to "left".

Test Coverage

  • Unit Tests: lib/tests/streamlit/elements/lib/column_types_test.py thoroughly tests the new alignment parameter across all supported column types using @pytest.mark.parametrize, which aligns with the Python testing guidelines. It also verifies that the default value (None) is omitted from the serialized config.
  • Frontend Tests: frontend/lib/src/components/widgets/DataFrame/columns/NumberColumn.test.ts includes a parameterized test to ensure the contentAlignment prop is correctly applied to the cell.
  • E2E Tests: e2e_playwright/st_dataframe_config.py adds a new dataframe demonstrating the alignments, and e2e_playwright/st_dataframe_config_test.py captures a visual snapshot of it. The test coverage is excellent.

Backwards Compatibility

The changes are fully backwards compatible. The alignment parameter defaults to None, which preserves the existing default alignment behavior for all column types.

Security & Risk

No security concerns or regression risks identified. The changes are purely additive and affect only visual presentation in the frontend.

External test recommendation

  • Recommend external_test: No
  • Triggered categories: None
  • Evidence:
    • lib/streamlit/elements/lib/column_types.py: Only adds a new parameter to the column config API.
    • frontend/lib/src/components/widgets/DataFrame/columns/NumberColumn.ts: Only changes how contentAlign is calculated for the cell.
  • Suggested external_test focus areas: N/A
  • Confidence: High
  • Assumptions and gaps: The changes do not interact with routing, auth, websockets, embedding, or any other external boundaries.

Accessibility

The changes only affect text alignment within the canvas-based data grid (Glide Data Grid) and do not negatively impact accessibility.

Recommendations

No specific recommendations for improvement. The implementation is clean and complete.

Verdict

APPROVED: The PR successfully implements the requested feature with excellent test coverage and no backwards compatibility or security issues.


This is an automated AI review by gemini-3.1-pro.

📋 Review by `gpt-5.3-codex-high`

Summary

This PR adds an alignment parameter to supported st.column_config APIs, wires it through Python column config serialization, fixes NumberColumn frontend alignment precedence so explicit alignment is respected, and adds coverage via Python unit tests, frontend unit tests, and E2E snapshots.

Code Quality

The implementation is clean and follows existing Streamlit patterns:

  • Python API changes in lib/streamlit/elements/lib/column_types.py consistently add alignment only to column types that actually support contentAlign rendering.
  • The frontend fix in frontend/lib/src/components/widgets/DataFrame/columns/NumberColumn.ts correctly changes fallback logic to props.contentAlignment ?? (useArrowFormatting ? "left" : "right"), which resolves the prior precedence issue where any truthy custom alignment effectively forced "left".
  • The added test helper flexibility in frontend/lib/src/components/widgets/DataFrame/columns/NumberColumn.test.ts is minimal and focused.

No maintainability or style issues found.

Test Coverage

Coverage is good and appropriately layered for this change:

  • Python unit tests: lib/tests/streamlit/elements/lib/column_types_test.py validates alignment propagation for supported column config APIs and default None behavior.
  • Frontend unit tests: frontend/lib/src/components/widgets/DataFrame/columns/NumberColumn.test.ts adds direct assertions that custom contentAlignment values are respected.
  • E2E visual coverage: e2e_playwright/st_dataframe_config.py + e2e_playwright/st_dataframe_config_test.py add a dedicated dataframe alignment scenario and snapshots across browsers/themes.

Given the scope (API exposure + renderer behavior), this is adequate.

Backwards Compatibility

No breaking changes identified:

  • API surface changes are additive keyword-only parameters with default None.
  • Existing default alignment behavior is preserved when alignment is not provided.
  • Unsupported column types intentionally do not expose alignment, preventing misleading API behavior.

Security & Risk

No security concerns found.
Changes are limited to dataframe column configuration and frontend cell alignment behavior; they do not touch auth, networking, server routes, session handling, file serving, CSP/CORS, or code execution paths.

External test recommendation

  • Recommend external_test: No
  • Triggered categories: None
  • Evidence:
    • lib/streamlit/elements/lib/column_types.py: API parameter/doc updates and config serialization only.
    • frontend/lib/src/components/widgets/DataFrame/columns/NumberColumn.ts: cell content alignment fallback logic only.
    • e2e_playwright/st_dataframe_config.py: visual dataframe scenario additions only.
  • Suggested external_test focus areas:
    • None required for this PR; existing local E2E snapshot coverage is appropriate.
  • Confidence: High
  • Assumptions and gaps: Assumes no unshown changes outside the listed PR diff and that alignment config continues to flow through existing column config transport unchanged.

Accessibility

No new interactive controls or semantics were introduced.
The frontend change only affects horizontal content alignment in grid cells, so accessibility impact is low and non-negative.

Recommendations

  1. Optionally update the PR description to reflect the final scope (alignment added to supported column types, not all typed columns), to avoid reviewer confusion.

Verdict

APPROVED: The changes are coherent, low risk, well tested for the affected behavior, and ready to merge.


This is an automated AI review by gpt-5.3-codex-high. Please verify the feedback and use your judgment.

📋 Review by `opus-4.6-thinking`

Summary

This PR adds an alignment parameter to st.column_config.Column and 11 typed column configs (TextColumn, NumberColumn, CheckboxColumn, DateColumn, TimeColumn, DatetimeColumn, LinkColumn, ImageColumn, AudioColumn, VideoColumn, JsonColumn) that controls horizontal text alignment ("left", "center", "right") of cell content in st.dataframe and st.data_editor.

The key changes are:

  • Backend: Introduces a ContentAlignment type alias and adds an alignment keyword parameter to each supported column config function. The alignment field already existed in the ColumnConfig TypedDict but was not exposed in any Python API function signature.
  • Frontend: Fixes an operator precedence bug in NumberColumn.ts where props.contentAlignment || useArrowFormatting ? "left" : "right" was parsed as (props.contentAlignment || useArrowFormatting) ? "left" : "right", which incorrectly resolved to "left" for any custom alignment value like "center" or "right". The fix changes || to ?? with explicit parentheses.
  • Tests: Adds Python unit tests, TypeScript unit tests for NumberColumn, and an E2E visual snapshot test.

Column types that use custom or third-party renderers (SelectboxColumn, ListColumn, MultiselectColumn, ProgressColumn, BarChartColumn, LineChartColumn, AreaChartColumn) correctly do not receive the new parameter, as Glide Data Grid's contentAlign property does not apply to them.

Code Quality

The code is clean, well-structured, and follows existing patterns throughout:

  • The ContentAlignment type alias at lib/streamlit/elements/lib/column_types.py:57 mirrors the pattern of existing type aliases (ColumnWidth, NumberFormat, DateTimeFormat).
  • The alignment parameter is consistently placed after pinned in all function signatures, matching the parameter ordering convention.
  • Docstrings are clear and consistent. The NumberColumn docstring usefully notes that "numbers are right-aligned" and that "some number-like types (e.g., durations) may use a different default alignment" (line 535-538), providing column-specific detail where helpful.
  • The NumberColumn.ts fix (line 103) from || to ?? is the correct operator for this context. The original code had a genuine operator precedence bug: || binds tighter than the ternary ?:, so props.contentAlignment || useArrowFormatting ? "left" : "right" was parsed as (props.contentAlignment || useArrowFormatting) ? "left" : "right", meaning any truthy custom alignment (e.g. "center") would always resolve to "left".

Minor observation (non-blocking): MediaColumn.ts:43 and ImageColumn.ts:36 use || "center" for their default alignment fallback. While this is functionally correct (the only falsy value contentAlignment can have is undefined), updating to ?? would be more idiomatic and consistent with the NumberColumn.ts fix. This predates this PR and is not a blocker.

Test Coverage

Test coverage is adequate:

  • Python unit tests (lib/tests/streamlit/elements/lib/column_types_test.py): Tests all 12 column types that support alignment with all three alignment values ("left", "center", "right"), plus a default-value test verifying alignment is None and excluded by remove_none_values.
  • TypeScript unit tests (NumberColumn.test.ts): Tests all three custom contentAlignment values on NumberColumn, which was the only frontend column with a code change. The test correctly passes contentAlignment via baseProps, verifying the ?? fix works for all alignment values.
  • E2E test (st_dataframe_config_test.py): Adds a visual snapshot test covering four column/alignment combinations (TextColumn left, TextColumn center, NumberColumn right, CheckboxColumn right), with both light and dark themes across three browsers.

The NUM_DATAFRAME_ELEMENTS count is correctly updated from 35 to 36.

Suggestion (non-blocking): A negative test asserting that an invalid alignment value (e.g., "justify") raises an error would add anti-regression value. However, since alignment is typed as Literal["left", "center", "right"] | None, invalid values are caught at the type-checking level, and the value passes through without server-side runtime validation (consistent with how ColumnWidth and other typed config fields work).

Backwards Compatibility

This PR is fully backwards compatible:

  • All new alignment parameters default to None, preserving existing behavior.
  • No existing function signatures are changed in a breaking way (keyword-only, additive parameter).
  • No protobuf changes are needed since column config is JSON-serialized.
  • The alignment field already existed in the ColumnConfig TypedDict, so users who were passing alignment via raw dicts will continue to work identically.
  • The NumberColumn.ts bug fix only changes behavior when contentAlignment is explicitly set, which was not possible through the Python API before this PR.

Security & Risk

No security concerns:

  • The change is purely a UI rendering feature with no server-side processing of the alignment value beyond passing it through as JSON.
  • No new dependencies are added.
  • No changes to WebSocket handling, authentication, file serving, or any other security-sensitive areas.
  • The alignment value is consumed by Glide Data Grid's existing contentAlign property, which only accepts the three literal string values.

External test recommendation

  • Recommend external_test: No
  • Triggered categories: None
  • Evidence:
    • Changes are limited to Python column config functions (parameter plumbing), one frontend column file (operator fix), and tests.
    • No changes to routing, auth, WebSocket, embedding, asset serving, CORS, security headers, or any other external-facing behavior.
    • The feature is purely a frontend rendering property passed through JSON column config.
  • Suggested external_test focus areas: None
  • Confidence: High
  • Assumptions and gaps: None. The change surface is narrow and entirely within the dataframe column config pipeline.

Accessibility

The alignment feature itself is accessibility-neutral:

  • Cell content alignment is a visual styling property handled by Glide Data Grid's canvas rendering.
  • No ARIA attributes or semantic HTML are affected.
  • Screen readers interact with the dataframe through existing accessibility mechanisms, which are not impacted by horizontal alignment changes.
  • The default alignment behavior (numbers right-aligned, text left-aligned) is preserved when alignment=None, maintaining familiar reading patterns.

Recommendations

  1. Consider using ?? instead of || in MediaColumn.ts:43 and ImageColumn.ts:36 for consistency with the NumberColumn.ts fix: props.contentAlignment ?? "center". This is cosmetic and non-blocking, as the current || works correctly for the constrained type.

  2. Consider adding ContentAlignment to the __all__ export list in column_config.py so users can import it for type annotations (e.g., from streamlit.column_config import ContentAlignment). This follows a similar pattern to how users might want to type-annotate alignment variables. However, since ColumnWidth, NumberFormat, and DateTimeFormat are also not exported, this would be a separate enhancement affecting all type aliases.

Verdict

APPROVED: A clean, well-tested, backwards-compatible feature that exposes an existing frontend capability through the Python API, with a correct operator precedence bug fix in NumberColumn.ts.


This is an automated AI review by opus-4.6-thinking.

Updates alignment parameter docstrings to explicitly state the default
alignment for each column type instead of using generic wording. Also
removes the product spec as it's no longer needed.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
width=width,
help=help,
pinned=pinned,
alignment=alignment,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

question: Do we need to validate this alignment value?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I think it's somewhat fine to rely on typing for correct input + silently ignoring wrong values in this case. We don't have similar validations for most other column config props. And for other commands, we are also somewhat inconsistently validating if it gets a value different from what is specified in the type and docstring.

Previously, wrong values would have been ignored on the canvas layer, but I added something to already validate and silently ignore this in our frontend logic.

…-alignment

Resolved conflict in column_types.py by keeping both the hidden column
note from develop and the alignment parameter docstring from this branch.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Add parseAlignmentConfig() to validate column alignment configuration.
Invalid values now log a console warning and fall back to default
alignment instead of being silently ignored by the Canvas 2D API.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@lukasmasuch lukasmasuch enabled auto-merge (squash) March 16, 2026 21:32
@lukasmasuch lukasmasuch merged commit 0476a5a into develop Mar 16, 2026
43 checks passed
@lukasmasuch lukasmasuch deleted the lukasmasuch/column-alignment branch March 16, 2026 21:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

change:feature PR contains new feature or enhancement implementation impact:users PR changes affect end users

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support text/content align in st.dataframe

3 participants