Dynamic tabs/expander/popover #3
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
Make it possible for
st.tabs
,st.expander
, andst.popover
content to run lazily (only when opened/active), instead of always executing on every rerun.Problem statement
Currently, tabs, expanders and popovers always execute their content, even if not visible:
This ensures instant visibility when toggled, but it slows apps significantly when hidden content is expensive to compute.
Requests:
Related:
st.tabs
&st.expander
- Improve handling of frontend state/mount streamlit#8239 -> should explore in parallel in case there's some implementation overlap to this featureProposed solution
API
Option 1: Add
on_change="ignore"|"rerun"|callback
This is the same API as for selections on charts/dataframes/maps. It's in fact a similar situation: all of these elements are static and we want to allow making them interactive (i.e. trigger a rerun of the app). This API also allows adding a callback (that is getting executed before the rest of the app).
What makes this complex is the return value: while for chart/dataframe/map selections, we return a dictionary when
on_select
is set, for tabs/expander/popover we need to keep returning the delta generator, so you can add elements to the container. But we need a way to communicate the open/closed state as well. Some possible solutions:Option 1a: Boolean evaluation of delta generator
Pros: Clean, readable, minimal changes.
Cons: Slight “magic” in truthiness of delta generator.
Option 1b: Attribute on delta generator
Pros: Explicit, type-safe.
Cons: Slightly wordier than Option 1, new pattern.
Option 1c: Session state value
Pros: Consistent with widgets.
Cons: Verbose, need to add
key
everytime, need to understand keys and session state.Option 2: Function argument
st.download_button
.on_change
) and fragment/dialog (which use a decorator).st.dialog
?Option 3: Function decorator
@st.fragment
and@st.dialog
st.tabs
, where we have multiple functions?st.expander
etc then – this might be tricky to explain.Behavior
Checklist
TBD