The fastest way to build and share data apps
Functions for organizing content and creating sophisticated multi-panel layouts. These containers help structure your Streamlit application by grouping related content, creating responsive layouts, and managing form submissions.
Fundamental container types for organizing and grouping content.
def container() -> DeltaGenerator:
"""
Create an invisible container for grouping elements.
Returns:
DeltaGenerator: Container object for adding elements
"""
def empty() -> DeltaGenerator:
"""
Create a placeholder container that can be filled later.
Returns:
DeltaGenerator: Empty container that can be populated programmatically
"""import streamlit as st
# Container for grouping related content
with st.container():
st.write("This content is in a container")
st.button("Container button")
# Empty placeholder that can be filled later
placeholder = st.empty()
# Later in the code, fill the placeholder
placeholder.text("This text was added to the placeholder!")Create responsive multi-column layouts for side-by-side content arrangement.
def columns(spec, gap: str = "small") -> List[DeltaGenerator]:
"""
Create a set of columns for side-by-side layout.
Parameters:
- spec: Number of columns (int) or list of column widths
- gap: Gap size between columns ("small", "medium", "large")
Returns:
List[DeltaGenerator]: List of column containers
"""import streamlit as st
# Equal width columns
col1, col2, col3 = st.columns(3)
with col1:
st.header("Column 1")
st.write("Content for first column")
with col2:
st.header("Column 2")
st.write("Content for second column")
with col3:
st.header("Column 3")
st.write("Content for third column")
# Custom width columns (ratios)
left_col, middle_col, right_col = st.columns([1, 2, 1])
with left_col:
st.write("Narrow left")
with middle_col:
st.write("Wide middle column")
with right_col:
st.write("Narrow right")
# Large gap between columns
col_a, col_b = st.columns(2, gap="large")
with col_a:
st.metric("Revenue", "$1.2M")
with col_b:
st.metric("Users", "1,234")Create tabbed interfaces for organizing content into separate views.
def tabs(tab_labels: List[str]) -> List[DeltaGenerator]:
"""
Create a tabbed interface.
Parameters:
- tab_labels: List of tab names/labels
Returns:
List[DeltaGenerator]: List of tab containers
"""import streamlit as st
import pandas as pd
import numpy as np
# Create tabs
tab1, tab2, tab3 = st.tabs(["Data", "Charts", "Settings"])
with tab1:
st.header("Data View")
data = pd.DataFrame(np.random.randn(10, 3), columns=["A", "B", "C"])
st.dataframe(data)
with tab2:
st.header("Charts View")
st.line_chart(data)
st.bar_chart(data)
with tab3:
st.header("Settings")
st.selectbox("Theme", ["Light", "Dark"])
st.checkbox("Enable notifications")Create collapsible sections to organize content hierarchically.
def expander(label: str, expanded: bool = False) -> DeltaGenerator:
"""
Create an expandable/collapsible container.
Parameters:
- label: Text displayed on the expander header
- expanded: Whether the expander is initially expanded
Returns:
DeltaGenerator: Expandable container
"""import streamlit as st
# Basic expander
with st.expander("See explanation"):
st.write("""
This is a detailed explanation that is hidden by default.
Users can click to expand and see this content.
""")
# Initially expanded expander
with st.expander("Configuration Options", expanded=True):
st.slider("Temperature", 0, 100, 50)
st.selectbox("Model", ["GPT-3", "GPT-4"])
# Multiple expanders for organized content
with st.expander("📊 Data Analysis"):
st.write("Data analysis content here")
st.line_chart([1, 2, 3, 4, 5])
with st.expander("🔧 Settings"):
st.checkbox("Debug mode")
st.number_input("Batch size", value=32)
with st.expander("ℹ️ Help & Documentation"):
st.markdown("""
## Getting Started
1. Upload your data
2. Configure parameters
3. Run analysis
""")Special container for sidebar content (accessed via st.sidebar).
sidebar: DeltaGenerator
# Access sidebar through st.sidebar
# All regular widgets and containers work in sidebar contextimport streamlit as st
# Sidebar content
st.sidebar.title("Navigation")
page = st.sidebar.selectbox("Choose page:", ["Home", "Data", "Results"])
st.sidebar.markdown("---")
st.sidebar.write("Settings")
debug_mode = st.sidebar.checkbox("Debug mode")
batch_size = st.sidebar.slider("Batch size", 1, 100, 32)
# Sidebar with sections
with st.sidebar:
st.markdown("### Filters")
category = st.selectbox("Category:", ["All", "A", "B", "C"])
date_range = st.date_input("Date range:")
st.markdown("### Options")
show_raw_data = st.checkbox("Show raw data")
export_format = st.radio("Export format:", ["CSV", "JSON"])
# Main content area
st.title(f"Current page: {page}")
if debug_mode:
st.write(f"Debug: Batch size is {batch_size}")Group related inputs and control when they trigger app reruns.
def form(key: str, clear_on_submit: bool = False) -> DeltaGenerator:
"""
Create a form container to batch widget interactions.
Parameters:
- key: Unique key for the form
- clear_on_submit: Whether to clear form inputs after submission
Returns:
DeltaGenerator: Form container
"""
def form_submit_button(label: str = "Submit", help: str = None, on_click=None, args=None, kwargs=None, type: str = "primary", disabled: bool = False, use_container_width: bool = False) -> bool:
"""
Display a form submit button (must be used inside a form).
Parameters:
- label: Text displayed on the submit button
- help: Tooltip text shown on hover
- on_click: Callback function executed on submit
- args: Arguments passed to callback function
- kwargs: Keyword arguments passed to callback function
- type: Button type ("primary" or "secondary")
- disabled: Whether the button is disabled
- use_container_width: Whether to use full container width
Returns:
bool: True if submit button was clicked, False otherwise
"""import streamlit as st
# Simple form
with st.form("my_form"):
st.write("User Information")
name = st.text_input("Name")
age = st.number_input("Age", min_value=0, max_value=120)
email = st.text_input("Email")
# Form submission
submitted = st.form_submit_button("Submit")
if submitted:
st.success(f"Form submitted for {name}, age {age}, email {email}")
# Form with sections and validation
with st.form("contact_form", clear_on_submit=True):
st.markdown("### Contact Information")
col1, col2 = st.columns(2)
with col1:
first_name = st.text_input("First Name")
phone = st.text_input("Phone")
with col2:
last_name = st.text_input("Last Name")
email = st.text_input("Email")
st.markdown("### Message")
subject = st.selectbox("Subject", ["General Inquiry", "Support", "Feedback"])
message = st.text_area("Message", height=100)
# Submit with validation
if st.form_submit_button("Send Message"):
if first_name and last_name and email and message:
st.success("Message sent successfully!")
st.balloons()
else:
st.error("Please fill in all required fields")
# Form with custom submit handling
def handle_submission():
st.session_state.form_submitted = True
with st.form("custom_form"):
data = st.text_input("Enter data:")
submitted = st.form_submit_button(
"Process Data",
on_click=handle_submission
)
if submitted and st.session_state.get("form_submitted", False):
st.write(f"Processing: {data}")
st.session_state.form_submitted = FalseCombine containers for sophisticated layouts.
import streamlit as st
# Header section
header_container = st.container()
with header_container:
st.title("Dashboard")
col1, col2, col3 = st.columns(3)
with col1:
st.metric("Total Users", "1,234", "+5%")
with col2:
st.metric("Revenue", "$12.3K", "+12%")
with col3:
st.metric("Growth", "8.2%", "+1.2%")
# Main content with sidebar navigation
with st.sidebar:
st.selectbox("Time Period", ["Last 7 days", "Last 30 days", "Last 90 days"])
st.multiselect("Filters", ["Region A", "Region B", "Region C"])
# Tabbed main content
tab1, tab2 = st.tabs(["Overview", "Details"])
with tab1:
# Overview content with expandable sections
with st.expander("Charts", expanded=True):
col1, col2 = st.columns(2)
with col1:
st.line_chart([1, 3, 2, 4, 5])
with col2:
st.bar_chart([2, 1, 3, 4, 2])
with st.expander("Data Table"):
st.dataframe({"A": [1, 2, 3], "B": [4, 5, 6]})
with tab2:
# Details content
st.write("Detailed view content here")
# Footer placeholder
footer = st.empty()
footer.markdown("---")
footer.caption("Last updated: 2024-01-01")Install with Tessl CLI
npx tessl i tessl/pypi-streamlit@1.16.0