[DynamicContainers] Callback support for tabs#14007
Conversation
✅ PR preview is ready!
|
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
7c5b44b to
9aa118f
Compare
9aa118f to
9fa2210
Compare
There was a problem hiding this comment.
Pull request overview
Adds callable callback support to st.tabs so apps can run user code on tab switches (with optional args/kwargs), while keeping the existing "ignore" / "rerun" / None behaviors intact.
Changes:
- Extend
st.tabs(..., on_change=...)to accept a callable, plus newargs/kwargsparameters that forward to the callback. - Add Python unit tests covering proto/id wiring,
.openbehavior, callback invocation semantics, and args/kwargs forwarding. - Add typing tests and Playwright E2E coverage for callback behavior.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
lib/streamlit/elements/layouts.py |
Extends st.tabs API + widget registration to support callable on_change with args/kwargs and updates docstring + validation. |
lib/tests/streamlit/elements/layouts_test.py |
Adds unit tests for callback wiring, state transitions, and args/kwargs forwarding. |
lib/tests/streamlit/typing/tab_container_types.py |
Updates typing tests to ensure callable on_change and args/kwargs type-check. |
e2e_playwright/st_tabs.py |
Adds app scenarios exercising st.tabs callbacks (including args/kwargs). |
e2e_playwright/st_tabs_test.py |
Adds E2E tests asserting callback execution on tab switches and updates tab component count. |
| - A callable: A callback function to execute before rerunning the | ||
| app when tabs are switched. Enables state tracking (equivalent to | ||
| ``"rerun"`` plus the callback). The callback receives no arguments | ||
| by default, but you can pass arguments using ``args`` and | ||
| ``kwargs``. |
There was a problem hiding this comment.
The docstring note near the top of st.tabs still says to use on_change="rerun" to enable lazy execution, but this PR adds callable on_change with the same stateful/lazy behavior. Please update that note to also mention the callable option so users don't miss the new capability.
lib/streamlit/elements/layouts.py
Outdated
| args : tuple or None | ||
| An optional tuple of args to pass to the ``on_change`` callback. |
There was a problem hiding this comment.
args is typed as WidgetArgs (tuple or list) across Streamlit widgets, and other widget docstrings document this as “list or tuple”. Here it’s documented as “tuple or None”, which is inconsistent with the actual accepted types. Either update the docstring to “list or tuple” (and keep the WidgetArgs type), or add runtime/type-level validation to only accept tuples.
| args : tuple or None | |
| An optional tuple of args to pass to the ``on_change`` callback. | |
| args : list or tuple or None | |
| An optional list or tuple of args to pass to the ``on_change`` callback. |
5d5fe20 to
b119d39
Compare
lib/streamlit/elements/layouts.py
Outdated
| if not callable(on_change) and (args is not None or kwargs is not None): | ||
| raise StreamlitAPIException( | ||
| "`args` and `kwargs` can only be used when `on_change` is a callable." | ||
| ) |
There was a problem hiding this comment.
suggestion: I think it's slightly better here to just not throw the error because 1) for consistency, since I believe we are not doing it anywhere else, 2) with agents, it might be better to be a bit more forgiving.
There was a problem hiding this comment.
OK, that sounds good to me. This was a suggestion from one of the AI reviews but it also seemed a bit heavy to me.
8bae35c to
13f8f8f
Compare
Co-authored-by: lawilby <[email protected]>
13f8f8f to
d379ac7
Compare

Describe your changes
Adds callable
on_changecallback support tost.tabs, extending the existing"ignore"/"rerun"/Nonestring literals.on_changenow accepts a callable in addition to the existing string optionsargsandkwargsparameters pass through to the callbackst.session_state[key]contains the label of the newly active tab, so the callback can branch on which tab was selected.GitHub Issue Link (if applicable)
Testing Plan
lib/tests/streamlit/elements/layouts_test.pye2e_playwright/st_tabs_test.pyContribution License Agreement
By submitting this pull request you agree that all contributions to this project are made under the Apache 2.0 license.