A faster way to build and share data apps
Layout management and container elements for organizing app structure and controlling element positioning. These components provide the foundation for creating well-structured, responsive Streamlit applications.
Create multi-column layouts for side-by-side element placement.
def columns(spec, gap="small"):
"""
Insert containers laid out as side-by-side columns.
Parameters:
- spec (int or sequence): Number of columns or sequence of column widths
- gap (str): Gap size between columns ('small', 'medium', 'large')
Returns:
list: List of column containers
"""Organize content into selectable tabs.
def tabs(tab_labels):
"""
Insert containers separated into tabs.
Parameters:
- tab_labels (list): List of tab labels
Returns:
list: List of tab containers
"""Multi-element containers for grouping related content.
def container(height=None, border=False):
"""
Insert a multi-element container.
Parameters:
- height (int): Container height in pixels
- border (bool): Show container border
Returns:
DeltaGenerator: Container object
"""
def expander(label, expanded=False):
"""
Insert a multi-element container that can be expanded/collapsed.
Parameters:
- label (str): Expander label
- expanded (bool): Initial expanded state
Returns:
DeltaGenerator: Expander container object
"""
def popover(label, help=None, disabled=False, use_container_width=False, icon=None):
"""
Insert a popover container that appears on click.
Parameters:
- label (str): Popover trigger button label
- help (str): Optional tooltip text
- disabled (bool): Disable the popover trigger
- use_container_width (bool): Use full container width for trigger
- icon (str): Optional icon for trigger button
Returns:
DeltaGenerator: Popover container object
"""Dedicated sidebar area for navigation and controls.
# Sidebar container object with all main interface methods
sidebar: DeltaGeneratorContainer for batching widget interactions and submissions.
def form(key, clear_on_submit=False, border=True):
"""
Create a form that batches elements together with a submit button.
Parameters:
- key (str): Unique form identifier
- clear_on_submit (bool): Clear form values after submission
- border (bool): Show form border
Returns:
DeltaGenerator: Form container object
"""
def form_submit_button(label="Submit", help=None, on_click=None, args=None, kwargs=None, type="secondary", disabled=False, use_container_width=False, icon=None):
"""
Display a form submit button (only works inside st.form).
Parameters:
- label (str): Button label
- help (str): Optional tooltip text
- on_click (callable): Function to call when submitted
- args (tuple): Arguments to pass to on_click function
- kwargs (dict): Keyword arguments to pass to on_click function
- type (str): Button type ('primary' or 'secondary')
- disabled (bool): Disable the button
- use_container_width (bool): Use full container width
- icon (str): Optional icon name
Returns:
bool: True if form was submitted, False otherwise
"""Special-purpose containers for specific layout needs.
def empty():
"""
Insert a single-element container for placeholder content.
Returns:
DeltaGenerator: Empty container object
"""
def divider():
"""
Display a horizontal rule divider.
Returns:
None
"""Containers for displaying progress and status information.
def progress(value, text=None):
"""
Display a progress bar.
Parameters:
- value (float): Progress value between 0.0 and 1.0
- text (str): Optional progress text
Returns:
DeltaGenerator: Progress bar object
"""
def status(label, expanded=False, state="running"):
"""
Display a status container to show progress of long-running tasks.
Parameters:
- label (str): Status label
- expanded (bool): Show contents by default
- state (str): Status state ('running', 'complete', 'error')
Returns:
DeltaGenerator: Status container object
"""
def spinner(text="In progress..."):
"""
Temporarily display a message with spinner while executing a block of code.
Parameters:
- text (str): Message to display
Returns:
ContextManager: Spinner context manager
"""import streamlit as st
# Equal-width columns
col1, col2, col3 = st.columns(3)
with col1:
st.header("Column 1")
st.write("Content for column 1")
st.button("Button 1")
with col2:
st.header("Column 2")
st.write("Content for column 2")
st.selectbox("Options", ["A", "B", "C"])
with col3:
st.header("Column 3")
st.write("Content for column 3")
st.slider("Value", 0, 100, 50)
# Custom column widths
col1, col2 = st.columns([2, 1]) # 2:1 ratio
with col1:
st.write("This column is twice as wide")
with col2:
st.write("Narrow column")
# Columns with different gaps
st.subheader("Large Gap Between Columns")
col1, col2 = st.columns(2, gap="large")
with col1:
st.info("Column with large gap")
with col2:
st.info("Another column")# Create tabs
tab1, tab2, tab3 = st.tabs(["📊 Charts", "📋 Data", "⚙️ Settings"])
with tab1:
st.header("Charts Tab")
# Sample chart
import pandas as pd
import numpy as np
chart_data = pd.DataFrame(
np.random.randn(20, 3),
columns=['a', 'b', 'c']
)
st.line_chart(chart_data)
with tab2:
st.header("Data Tab")
st.dataframe(chart_data)
with tab3:
st.header("Settings Tab")
st.checkbox("Enable notifications")
st.selectbox("Theme", ["Light", "Dark", "Auto"])# Basic expander
with st.expander("See explanation"):
st.write("""
This is additional content that can be hidden or shown.
Perfect for detailed explanations, advanced options, or FAQ sections.
""")
st.code('''
def hello():
print("Hello, World!")
''')
# Expander with initial expanded state
with st.expander("Advanced Configuration", expanded=True):
st.slider("Advanced parameter 1", 0, 100, 50)
st.checkbox("Enable advanced feature")
st.text_input("Custom setting")# Add content to sidebar
st.sidebar.title("Navigation")
st.sidebar.markdown("Use the controls below:")
# Sidebar inputs
page = st.sidebar.selectbox(
"Choose a page:",
["Home", "Data Analysis", "Visualization", "Settings"]
)
if page == "Data Analysis":
# Sidebar filters for data analysis
st.sidebar.header("Filters")
date_range = st.sidebar.date_input(
"Select date range:",
value=[pd.Timestamp('2023-01-01'), pd.Timestamp('2023-12-31')]
)
categories = st.sidebar.multiselect(
"Select categories:",
["Category A", "Category B", "Category C"],
default=["Category A"]
)
# Main content based on sidebar selection
st.title(f"{page} Page")
st.write(f"Content for {page}")# Contact form example
with st.form("contact_form"):
st.write("Contact Us")
name = st.text_input("Name *", placeholder="Enter your full name")
email = st.text_input("Email *", placeholder="your@email.com")
subject = st.selectbox("Subject", [
"General Inquiry",
"Technical Support",
"Bug Report",
"Feature Request"
])
message = st.text_area("Message *", placeholder="Enter your message here...")
# Form will only submit when this button is clicked
submitted = st.form_submit_button("Send Message", type="primary")
if submitted:
if name and email and message:
st.success("Message sent successfully!")
st.balloons()
else:
st.error("Please fill in all required fields (*)")
# Form with clear on submit
with st.form("survey_form", clear_on_submit=True):
st.write("Quick Survey")
rating = st.slider("How would you rate our service?", 1, 5, 3)
feedback = st.text_area("Additional feedback:")
recommend = st.checkbox("Would you recommend us to others?")
if st.form_submit_button("Submit Survey"):
st.success("Thank you for your feedback!")
st.write(f"Rating: {rating}/5")
st.write(f"Would recommend: {'Yes' if recommend else 'No'}")# Generic container
with st.container():
st.write("This content is in a container")
st.info("Containers help organize related content")
# Container with border
with st.container(border=True):
st.write("This container has a visible border")
col1, col2 = st.columns(2)
with col1:
st.metric("Metric 1", "1,234", "12")
with col2:
st.metric("Metric 2", "5,678", "-5")
# Empty placeholder for dynamic content
placeholder = st.empty()
# Later, replace the placeholder content
import time
for i in range(5):
placeholder.text(f"Loading... {i+1}/5")
time.sleep(1)
placeholder.success("Loading complete!")# Progress bar
progress_bar = st.progress(0)
status_text = st.empty()
for i in range(100):
# Update progress
progress_bar.progress(i + 1)
status_text.text(f'Progress: {i+1}%')
time.sleep(0.01)
status_text.text('Processing complete!')
# Status container
with st.status("Processing data...", expanded=True) as status:
st.write("Loading dataset...")
time.sleep(1)
st.write("Cleaning data...")
time.sleep(1)
st.write("Running analysis...")
time.sleep(1)
status.update(label="Analysis complete!", state="complete", expanded=False)
# Spinner context manager
with st.spinner('Computing complex calculation...'):
time.sleep(2) # Simulate long computation
st.success('Calculation finished!')# Simple popover
with st.popover("Open popover"):
st.markdown("Hello World 👋")
name = st.text_input("What's your name?")
if name:
st.write(f"Nice to meet you, {name}!")
# Popover with custom button
with st.popover("⚙️ Settings", help="Click to configure settings"):
st.checkbox("Enable notifications")
st.selectbox("Language", ["English", "Spanish", "French"])
theme = st.radio("Theme", ["Light", "Dark", "Auto"])
if st.button("Apply Settings"):
st.success("Settings applied!")# Responsive metric dashboard
col1, col2, col3, col4 = st.columns(4)
metrics = [
("Revenue", "$125K", "12%"),
("Users", "2.8K", "-5%"),
("Conversion", "3.2%", "0.8%"),
("Retention", "87%", "2%")
]
for col, (label, value, delta) in zip([col1, col2, col3, col4], metrics):
with col:
st.metric(label, value, delta)
# Two-column layout with different content
left_col, right_col = st.columns([2, 1])
with left_col:
st.subheader("Main Content")
st.write("This is the main content area with more space.")
# Chart or main visualization
chart_data = pd.DataFrame(
np.random.randn(50, 3),
columns=['A', 'B', 'C']
)
st.line_chart(chart_data)
with right_col:
st.subheader("Sidebar Content")
st.write("Controls and filters go here.")
# Controls
show_data = st.checkbox("Show raw data")
chart_type = st.selectbox("Chart type", ["Line", "Area", "Bar"])
if show_data:
st.dataframe(chart_data.tail())Install with Tessl CLI
npx tessl i tessl/pypi-streamlit@1.49.0