or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

advanced-features.mdcharts-visualizations.mdconfiguration-control.mddata-display.mddisplay-content.mdindex.mdinput-widgets.mdlayout-containers.mdmedia-status.mdstate-caching.md
tile.json

advanced-features.mddocs/

Advanced Features

Advanced Streamlit functionality including authentication, navigation, fragments, dialogs, custom components, and data connections for sophisticated application development.

Capabilities

Multi-page Navigation

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):
        pass

Fragments

Create 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
    """

Dialog Modals

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
    """

Authentication

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: UserInfoProxy

Data Connections

Connect 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
    """

Connection Classes

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."""
        pass

Custom Components

Integration 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
    """

Chat Interface

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
    """

Usage Examples

Multi-page Navigation

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()

Fragment Usage

@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 Modals

# 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()

Authentication

# 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%")

Chat Interface

# 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"
        )

Custom Components

# 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
)

Data Connections

# 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()