Add 'default' parameter to st.tabs to set default tab#11005
Add 'default' parameter to st.tabs to set default tab#11005dweepvira wants to merge 3 commits intostreamlit:developfrom
Conversation
🎉 Snyk checks have passed. No issues have been found so far.✅ security/snyk check is complete. No issues have been found. (View Details) ✅ license/snyk check is complete. No issues have been found. (View Details) |
sfc-gh-bnisco
left a comment
There was a problem hiding this comment.
Hi @dweepvira thank you for your contribution! I left some comments inline. I also noticed there are a number of failing jobs in CI. Could you please take a look at these?
| } | ||
|
|
||
| message TabContainer { | ||
| repeated Tab tabs = 1; // Stores the list of tabs |
There was a problem hiding this comment.
question: Is adding tabs to the proto necessary? I believe the Tab messages should handle this for us like it does today
proto/streamlit/proto/Block.proto
Outdated
|
|
||
| message TabContainer { | ||
| repeated Tab tabs = 1; // Stores the list of tabs | ||
| optional int32 default_index = 2; // NEW: Default tab selection |
There was a problem hiding this comment.
suggestion: Please match the naming conventions of other components in the Streamlit repo. This might be better named default.
| @@ -1,32 +1,23 @@ | |||
| # Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2025) | |||
There was a problem hiding this comment.
suggestion: These headings are required and enforced by CI and pre-commit, please ensure they are maintained
e2e_playwright/st_tabs.py
Outdated
| # Initialize session state for tab selection | ||
| if "active_tab" not in st.session_state: | ||
| st.session_state.active_tab = "Tab 1" # Set default tab |
There was a problem hiding this comment.
question: What does this do? I don't see st.session_state.active_tab being used in this app
| with tab3: | ||
| st.write("tab3") | ||
| st.date_input("Date input") | ||
| for i, tab in enumerate(tabs): |
There was a problem hiding this comment.
question: What is the intent behind this change?
There was a problem hiding this comment.
Can we keep this in the previous style?
- Removed redundant �[3g �H �H �H �H �H �H �H �H �H �H �H �H �H �H �H �H field from TabContainer proto message - Renamed to for consistency - Cleaned up unused session state code in - Reverted unnecessary changes to tab loop - Added targeted test for default tab selection using the new parameter - Fixed CI issues related to headers and field validation
|
Thanks a lot for reviewing my PR and for all the helpful feedback — as this is my first contribution to the project, it’s been a great learning experience. I’ve incorporated the suggested changes, but if I’ve missed anything or if further updates are needed, I’d be happy to address them. Appreciate your time and support!
|
sfc-gh-bnisco
left a comment
There was a problem hiding this comment.
Thank you @dweepvira ! I'm not seeing all of the changes you mentioned in the last comment reflected in the code. Specifically for 1 - the proto still has repeated Tabs. I left some other comments in line. Thank you in advance for addressing them!
| with tab3: | ||
| st.write("tab3") | ||
| st.date_input("Date input") | ||
| for i, tab in enumerate(tabs): |
There was a problem hiding this comment.
Can we keep this in the previous style?
|
|
||
|
|
||
| def test_default_tab_selection(app: Page): | ||
| """Ensure that the default tab (e.g. Tab 2) is selected automatically on load.""" |
There was a problem hiding this comment.
issue: This docstring does not match the actual test body. We need to have an instance of st.tabs that actually utilizes the new default param
| @@ -0,0 +1 @@ | |||
| ../../../proto/streamlit/proto No newline at end of file | |||
There was a problem hiding this comment.
issue: Please remove these symlinks
| }, [allTabLabels, props.defaultIndex]) | ||
| // TODO: Update to match React best practices | ||
| // eslint-disable-next-line react-compiler/react-compiler | ||
| // eslint-disable-next-line react-hooks/exhaustive-deps |
There was a problem hiding this comment.
issue: Moving these comments will cause eslint to fail
| */ | ||
|
|
||
| export * from "./proto" | ||
|
|
There was a problem hiding this comment.
suggestion: Please remove unnecessary change
| """files outside static directory and symlinks pointing to | ||
| files outside static directory and directories should return 403. | ||
| """ | ||
| # safe_dir_name = os.path.basename(self._tmp_dir_inside_static_folder.name) |
There was a problem hiding this comment.
issue: Please undo these changes in this file
| @@ -0,0 +1 @@ | |||
| ../../../proto/streamlit/proto No newline at end of file | |||
There was a problem hiding this comment.
issue: Please remove these symlinks
|
Dear Johannes,
Apologies for not being active on GitHub recently. I am currently a
student, and for the past 1 to 1.5 months, I’ve been engaged with my
end-semester exams, project submissions, and vivas. My exams will continue
until 30th May, which has limited my availability to follow up on the
pull request.
Thank you for your feedback and for pointing out the related PR #11267. I
completely understand if you prefer to proceed with merging either that PR
or my current one. However, if you're open to waiting until my exams
conclude, I’d be happy to resume work on my PR and make any necessary
changes based on your comments.
I’m really keen on contributing, as I’ll be applying for jobs next year,
and having meaningful open-source contributions will greatly strengthen my
resume and learning experience. I truly appreciate the opportunity to be
part of the Streamlit community.
Please feel free to proceed as you see fit, and thank you again for your
support and understanding.
Warm regards,
Dweep Vira
GitHub: dweepvira
…On Thu, 22 May 2025 at 06:55, Johannes Rieke ***@***.***> wrote:
*jrieke* left a comment (streamlit/streamlit#11005)
<#11005 (comment)>
Note that there's another PR for this feature: #11267
<#11267>
I'm in principle fine with merging this feature but please see my notes
here
<#11267 (comment)>
.
—
Reply to this email directly, view it on GitHub
<#11005 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AS7R6WVUB5WU75T33LZ4YOT27URSPAVCNFSM6AAAAAB2J43IY2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDQOJZGY2DCNJRGU>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
|
No worries at all! :) I flagged the duplicate PRs to our eng team and they will have a look how far each one is and which one makes more sense to merge. |
There was a problem hiding this comment.
Pull Request Overview
This PR adds a new default parameter to st.tabs so users can specify which tab is selected by default. Key changes include modifications to protocols to support the default parameter, updates to the layouts API to compute and pass the default tab index, and corresponding adjustments in the frontend components and tests.
Reviewed Changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| proto/streamlit/proto/Block.proto | Removed the Tab field and added a default field in TabContainer |
| proto/proto | Updated include path for protobuf definitions |
| lib/tests/streamlit/web/server/app_static_file_handler_test.py | Introduced commented-out code segments for static file handling tests |
| lib/streamlit/elements/layouts.py | Updated st.tabs signature and set default tab index for proto |
| frontend/protobuf/proto, frontend/protobuf/index.js, etc. | Minor updates to sync with protobuf changes |
| frontend/lib/src/components/elements/Tabs/Tabs.tsx | Adjusted default tab selection logic in the UI component |
| e2e_playwright/st_tabs_test.py & st_tabs.py | Added/updated tests to verify default tab selection |
Comments suppressed due to low confidence (1)
proto/streamlit/proto/Block.proto:29
- Removing the 'Tab' field directly can break backward compatibility. Instead, mark this field as deprecated and retain it to avoid breaking changes in existing clients.
TabContainer tab_container = 6;
|
|
||
| block_proto = BlockProto() | ||
| block_proto.tab_container.SetInParent() | ||
| block_proto.tab_container.default_index = default_index # Set default tab index |
There was a problem hiding this comment.
The code assigns to 'default_index' while the protobuf field is named 'default'. Update the assignment to use the correct field name (e.g. 'block_proto.tab_container.default') to avoid runtime errors.
| block_proto.tab_container.default_index = default_index # Set default tab index | |
| block_proto.tab_container.default = default_index # Set default tab index |
| """files outside static directory and symlinks pointing to | ||
| files outside static directory and directories should return 403. | ||
| """ | ||
| # safe_dir_name = os.path.basename(self._tmp_dir_inside_static_folder.name) |
There was a problem hiding this comment.
[nitpick] There are several commented-out lines that appear to be leftover debugging code. Consider removing them to improve code clarity and maintainability.
|
Closing since this was implemented in #12313 |
Describe your changes
This PR introduces a default parameter to the st.tabs function, allowing users to specify which tab should be selected by default when rendering. This enhancement provides better control over the user experience and aligns with similar features recently added to st.pills and st.segmented_control. If no default value is specified, the first tab remains selected by default to ensure backward compatibility.
GitHub Issue Link (if applicable)
#10910
Testing Plan
Explanation of Why No Additional Tests Are Needed
Tests could not be executed due to setup and installation issues, specifically related to proto compilation and npm dependencies. However, the necessary test modifications have been made in st_tabs_tests.py to validate the new default tab selection functionality. The expectation is that the CI/CD pipeline will run these tests automatically upon submission.
Unit Tests (Python)
def test_default_tab_selection(app: Page):
"""Ensure that the first tab is selected by default or the specified default tab is selected."""
tabs = app.get_by_test_id("stTabs").nth(0)
first_tab = tabs.get_by_role("tab").nth(0)
expect(first_tab).to_have_attribute("aria-selected", "true")
End-to-End (E2E) Tests
Manual Testing
st.pills and st.segmented_control.
Contribution License Agreement
By submitting this pull request, I agree that all contributions to this project are made under the Apache 2.0 license