A faster way to build and share data apps
Advanced Streamlit functionality including authentication, navigation, fragments, dialogs, custom components, and data connections for sophisticated application development.
Navigate between multiple pages in a Streamlit application.
def navigation(pages, position="sidebar"):
"""
Render a navigation widget for multipage apps.
Parameters:
- pages (list): List of Page objects or page configuration dicts
- position (str): Navigation position ('sidebar' or 'main')
Returns:
Page: Currently selected page object
"""
class Page:
"""
Configure a page for st.navigation in a multipage app.
Parameters:
- page: Callable function or file path for the page
- title (str): Page title (optional, inferred from function name or filename)
- icon (str): Page icon (emoji or icon name)
- url_path (str): Custom URL path for the page
- default (bool): Whether this is the default page
"""
def __init__(self, page, title=None, icon=None, url_path=None, default=False):
passCreate independently rerunning code sections for improved performance.
def fragment(func=None, *, run_every=None, rerun_on_update=True):
"""
Turn a function into a fragment that can rerun independently of the main app.
Parameters:
- func (callable): Function to turn into a fragment
- run_every (float): Auto-rerun interval in seconds
- rerun_on_update (bool): Rerun fragment when its state changes
Returns:
callable: Fragment function decorator
"""Create modal dialog overlays for focused user interactions.
def dialog(title, *, width="large"):
"""
Create a modal dialog overlay.
Parameters:
- title (str): Dialog title
- width (str): Dialog width ('small', 'medium', 'large')
Returns:
ContextManager: Dialog context manager
"""User authentication and session management.
def login(user_info_provider=None, **kwargs):
"""
Display a login widget and authenticate the user.
Parameters:
- user_info_provider: Custom user information provider
- **kwargs: Additional authentication configuration
Returns:
bool: True if login was successful
"""
def logout(button_text="Logout"):
"""
Display a logout button.
Parameters:
- button_text (str): Text for the logout button
Returns:
bool: True if logout button was clicked
"""
# User information proxy
user: UserInfoProxyConnect to external data sources and databases.
def connection(name, type=None, **kwargs):
"""
Create or retrieve a connection to a data source.
Parameters:
- name (str): Connection name
- type (str): Connection type ('sql', 'snowflake', etc.)
- **kwargs: Connection-specific configuration parameters
Returns:
BaseConnection: Connection object
"""Base classes for creating custom data connections.
class BaseConnection:
"""Base class for creating data connections."""
def query(self, query, **kwargs):
"""Execute a query against the connection."""
pass
def reset(self):
"""Reset the connection."""
pass
class SQLConnection(BaseConnection):
"""Connection for SQL databases."""
def query(self, query, params=None, ttl=None, **kwargs):
"""Execute SQL query with optional caching."""
pass
class SnowflakeConnection(BaseConnection):
"""Connection for Snowflake data warehouse."""
def query(self, query, params=None, ttl=None, **kwargs):
"""Execute Snowflake query."""
pass
def write_pandas(self, df, table_name, **kwargs):
"""Write pandas DataFrame to Snowflake."""
pass
class SnowparkConnection(BaseConnection):
"""Connection for Snowpark operations."""
def session(self):
"""Get Snowpark session."""
passIntegration with custom HTML/JavaScript components.
# Access via st.components.v1
def declare_component(name, path=None, url=None):
"""
Create and register a custom component.
Parameters:
- name (str): Component name
- path (str): Local component directory path
- url (str): URL to hosted component
Returns:
callable: Component function
"""
def html(html, width=None, height=None, scrolling=False):
"""
Render arbitrary HTML in an iframe.
Parameters:
- html (str): HTML content to render
- width (int): iframe width in pixels
- height (int): iframe height in pixels
- scrolling (bool): Enable scrolling
Returns:
Any: Component return value
"""
def iframe(src, width=None, height=None, scrolling=False):
"""
Render an iframe with specified source.
Parameters:
- src (str): iframe source URL
- width (int): iframe width in pixels
- height (int): iframe height in pixels
- scrolling (bool): Enable scrolling
Returns:
Any: Component return value
"""Specialized widgets for building chat applications.
def chat_message(name, avatar=None):
"""
Insert a chat message container.
Parameters:
- name (str): Message sender name
- avatar (str): Avatar image URL or emoji
Returns:
ContextManager: Chat message context manager
"""
def chat_input(placeholder=None, disabled=False, key=None, max_chars=None, on_submit=None, args=None, kwargs=None):
"""
Display a chat input widget at the bottom of the app.
Parameters:
- placeholder (str): Placeholder text
- disabled (bool): Disable the input
- key (str): Unique key for the widget
- max_chars (int): Maximum character limit
- on_submit (callable): Function to call on message submit
- args (tuple): Arguments to pass to on_submit function
- kwargs (dict): Keyword arguments to pass to on_submit function
Returns:
str or None: Submitted message text
"""import streamlit as st
# Define page functions
def home_page():
st.title("🏠 Home Page")
st.write("Welcome to the home page!")
st.subheader("Quick Stats")
col1, col2, col3 = st.columns(3)
with col1:
st.metric("Users", "1,234", "12%")
with col2:
st.metric("Revenue", "$56.7K", "8%")
with col3:
st.metric("Growth", "23%", "2%")
def analytics_page():
st.title("📊 Analytics")
st.write("Analytics dashboard")
import pandas as pd
import numpy as np
# Sample chart
chart_data = pd.DataFrame(
np.random.randn(20, 3),
columns=['A', 'B', 'C']
)
st.line_chart(chart_data)
def settings_page():
st.title("⚙️ Settings")
st.write("Application settings")
theme = st.selectbox("Theme", ["Light", "Dark", "Auto"])
notifications = st.checkbox("Enable notifications", value=True)
language = st.selectbox("Language", ["English", "Spanish", "French"])
if st.button("Save Settings"):
st.success("Settings saved!")
# Configure pages
pages = [
st.Page(home_page, title="Home", icon="🏠", default=True),
st.Page(analytics_page, title="Analytics", icon="📊"),
st.Page(settings_page, title="Settings", icon="⚙️")
]
# Render navigation
current_page = st.navigation(pages)
current_page.run()@st.fragment(run_every=5) # Auto-refresh every 5 seconds
def live_metrics():
"""Fragment that updates independently."""
import random
import time
st.subheader("📊 Live Metrics (Auto-refreshing)")
col1, col2, col3 = st.columns(3)
with col1:
cpu_usage = random.randint(20, 80)
st.metric("CPU Usage", f"{cpu_usage}%", f"{random.randint(-5, 5)}%")
with col2:
memory_usage = random.randint(40, 90)
st.metric("Memory", f"{memory_usage}%", f"{random.randint(-3, 3)}%")
with col3:
active_users = random.randint(100, 500)
st.metric("Active Users", active_users, random.randint(-20, 50))
st.caption(f"Last updated: {time.strftime('%H:%M:%S')}")
@st.fragment
def user_feedback():
"""Independent feedback fragment."""
st.subheader("💬 User Feedback")
if 'feedback_messages' not in st.session_state:
st.session_state.feedback_messages = []
# Feedback form
with st.form("feedback_form", clear_on_submit=True):
message = st.text_area("Your feedback:")
rating = st.slider("Rating:", 1, 5, 3)
if st.form_submit_button("Submit Feedback"):
if message:
st.session_state.feedback_messages.append({
'message': message,
'rating': rating,
'timestamp': time.strftime('%H:%M:%S')
})
st.success("Thank you for your feedback!")
# Display recent feedback
if st.session_state.feedback_messages:
st.write("**Recent Feedback:**")
for feedback in st.session_state.feedback_messages[-3:]:
with st.expander(f"Rating: {feedback['rating']}/5 - {feedback['timestamp']}"):
st.write(feedback['message'])
# Use fragments
st.title("Fragment Demo")
# These fragments update independently
live_metrics()
st.divider()
user_feedback()
# Regular content (reruns with main app)
st.subheader("🔄 Main App Content")
st.write("This content reruns with the main app.")
if st.button("Refresh Main App"):
st.success("Main app refreshed!")# Dialog for user confirmation
@st.dialog("Confirm Delete")
def confirm_delete_dialog(item_name):
st.write(f"Are you sure you want to delete **{item_name}**?")
st.warning("This action cannot be undone!")
col1, col2 = st.columns(2)
with col1:
if st.button("Cancel", use_container_width=True):
st.rerun()
with col2:
if st.button("Delete", type="primary", use_container_width=True):
st.session_state.deleted_item = item_name
st.rerun()
# Dialog for data input
@st.dialog("Add New Item", width="medium")
def add_item_dialog():
st.write("Enter item details:")
name = st.text_input("Item name:")
category = st.selectbox("Category:", ["Electronics", "Books", "Clothing"])
price = st.number_input("Price:", min_value=0.01, format="%.2f")
description = st.text_area("Description:")
col1, col2 = st.columns(2)
with col1:
if st.button("Cancel", use_container_width=True):
st.rerun()
with col2:
if st.button("Add Item", type="primary", use_container_width=True):
if name and price:
if 'items' not in st.session_state:
st.session_state.items = []
st.session_state.items.append({
'name': name,
'category': category,
'price': price,
'description': description
})
st.rerun()
else:
st.error("Please fill in required fields")
# Main interface
st.title("Dialog Demo")
# Items list
if 'items' not in st.session_state:
st.session_state.items = [
{'name': 'Laptop', 'category': 'Electronics', 'price': 999.99, 'description': 'Gaming laptop'},
{'name': 'Book', 'category': 'Books', 'price': 19.99, 'description': 'Programming guide'}
]
# Add item button
if st.button("➕ Add Item"):
add_item_dialog()
# Display items
st.subheader("Items")
for i, item in enumerate(st.session_state.items):
col1, col2, col3, col4 = st.columns([2, 1, 1, 1])
with col1:
st.write(f"**{item['name']}**")
st.caption(item['description'])
with col2:
st.write(item['category'])
with col3:
st.write(f"${item['price']:.2f}")
with col4:
if st.button("🗑️", key=f"delete_{i}", help="Delete item"):
confirm_delete_dialog(item['name'])
# Handle deletion
if 'deleted_item' in st.session_state:
st.session_state.items = [
item for item in st.session_state.items
if item['name'] != st.session_state.deleted_item
]
st.success(f"Deleted {st.session_state.deleted_item}")
del st.session_state.deleted_item
st.rerun()# Basic authentication example
if 'authenticated' not in st.session_state:
st.session_state.authenticated = False
if not st.session_state.authenticated:
st.title("🔐 Login Required")
# Simple login form
with st.form("login_form"):
username = st.text_input("Username:")
password = st.text_input("Password:", type="password")
if st.form_submit_button("Login"):
# Simple authentication (replace with real auth)
if username == "admin" and password == "password":
st.session_state.authenticated = True
st.session_state.username = username
st.success("Login successful!")
st.rerun()
else:
st.error("Invalid credentials")
else:
# Authenticated content
col1, col2 = st.columns([3, 1])
with col1:
st.title(f"Welcome, {st.session_state.username}!")
with col2:
if st.button("Logout"):
st.session_state.authenticated = False
del st.session_state.username
st.rerun()
# Protected content
st.subheader("Protected Dashboard")
st.write("This content is only visible to authenticated users.")
# Sample dashboard
col1, col2, col3 = st.columns(3)
with col1:
st.metric("Total Sales", "$45,231", "12%")
with col2:
st.metric("New Users", "156", "8%")
with col3:
st.metric("Conversion Rate", "3.2%", "0.5%")# Initialize chat history
if 'chat_history' not in st.session_state:
st.session_state.chat_history = [
{"role": "assistant", "content": "Hello! How can I help you today?"}
]
st.title("💬 Chat Interface")
# Display chat history
for message in st.session_state.chat_history:
with st.chat_message(message["role"]):
st.write(message["content"])
# Chat input
if prompt := st.chat_input("Type your message here..."):
# Add user message to history
st.session_state.chat_history.append({"role": "user", "content": prompt})
# Display user message
with st.chat_message("user"):
st.write(prompt)
# Generate response (simulate AI response)
import random
responses = [
"That's an interesting question!",
"I understand what you're asking.",
"Let me help you with that.",
"That's a great point!",
"I see what you mean."
]
response = random.choice(responses) + f" You said: '{prompt}'"
# Add assistant response to history
st.session_state.chat_history.append({"role": "assistant", "content": response})
# Display assistant response
with st.chat_message("assistant"):
st.write(response)
# Chat controls
col1, col2 = st.columns([1, 1])
with col1:
if st.button("Clear Chat"):
st.session_state.chat_history = [
{"role": "assistant", "content": "Hello! How can I help you today?"}
]
st.rerun()
with col2:
if st.button("Export Chat"):
chat_text = "\n".join([
f"{msg['role'].title()}: {msg['content']}"
for msg in st.session_state.chat_history
])
st.download_button(
"Download Chat",
chat_text,
file_name="chat_history.txt",
mime="text/plain"
)# HTML component example
st.subheader("Custom HTML Component")
html_content = """
<div style="
background: linear-gradient(45deg, #FF6B6B, #4ECDC4);
padding: 20px;
border-radius: 10px;
color: white;
text-align: center;
font-family: Arial, sans-serif;
">
<h2>🎨 Custom HTML Widget</h2>
<p>This is a custom HTML component with styling!</p>
<button onclick="alert('Hello from custom component!')"
style="
background: white;
color: #333;
border: none;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
">
Click Me!
</button>
</div>
"""
st.components.v1.html(html_content, height=200)
# Iframe component example
st.subheader("Embedded Content")
# Embed external content
st.components.v1.iframe(
"https://www.openstreetmap.org/export/embed.html?bbox=-0.1,51.5,-0.05,51.52",
width=700,
height=400
)# SQL Connection example (conceptual - requires actual database)
try:
# Create connection
conn = st.connection("my_database", type="sql", url="sqlite:///example.db")
# Query with caching
@st.cache_data
def get_user_data():
return conn.query("SELECT * FROM users LIMIT 10")
# Use connection
st.subheader("Database Connection")
data = get_user_data()
st.dataframe(data)
except Exception as e:
st.info("Database connection example (requires actual database setup)")
st.code("""
# SQL Connection usage:
conn = st.connection("my_db", type="sql", url="postgresql://...")
data = conn.query("SELECT * FROM table", ttl=600)
""")
# File-based connection example
st.subheader("File Connection Simulation")
@st.cache_data
def load_sample_data():
import pandas as pd
import numpy as np
# Simulate loading from external source
return pd.DataFrame({
'id': range(1, 101),
'name': [f'User_{i}' for i in range(1, 101)],
'value': np.random.randn(100),
'category': np.random.choice(['A', 'B', 'C'], 100)
})
data = load_sample_data()
st.dataframe(data.head())
# Connection refresh
if st.button("Refresh Data"):
st.cache_data.clear()
st.rerun()Install with Tessl CLI
npx tessl i tessl/pypi-streamlit@1.49.0