CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-streamlit

A faster way to build and share data apps

Overview
Eval results
Files

advanced-features.mddocs/

Advanced Features

Chat interfaces, app fragments, modal dialogs, and database connections for sophisticated applications. These features enable building complex, interactive applications with modern UI patterns.

Capabilities

Chat Interface

Build conversational interfaces and chatbots with built-in message containers and input handling.

def chat_message(name, *, avatar=None):
    """
    Create chat message container with sender name and optional avatar.

    Args:
        name (str): Name of the message sender
        avatar (str, optional): Avatar image URL, emoji, or user type ("user", "assistant")

    Returns:
        DeltaGenerator: Chat message container context manager
    """

def chat_input(placeholder=None, key=None, max_chars=None, on_submit=None, args=None, kwargs=None, *, disabled=False):
    """
    Display chat input widget for user message entry.

    Args:
        placeholder (str, optional): Placeholder text when empty
        key (str, optional): Unique widget key for state management
        max_chars (int, optional): Maximum number of characters allowed
        on_submit (callable, optional): Callback function when message is submitted
        args (tuple, optional): Arguments for on_submit callback
        kwargs (dict, optional): Keyword arguments for on_submit callback
        disabled (bool): Whether input is disabled

    Returns:
        str: Submitted message text or empty string if no submission
    """

Example usage:

# Initialize chat history in session state
if "messages" not in st.session_state:
    st.session_state.messages = []

# Display chat history
for message in st.session_state.messages:
    with st.chat_message(message["role"], avatar=message.get("avatar")):
        st.write(message["content"])

# Chat input
user_input = st.chat_input("Type your message here...")

if user_input:
    # Add user message to history
    st.session_state.messages.append({
        "role": "user",
        "content": user_input,
        "avatar": "🧑‍💻"
    })

    # Display user message
    with st.chat_message("user", avatar="🧑‍💻"):
        st.write(user_input)

    # Generate and display assistant response
    response = generate_response(user_input)  # Your AI logic here

    st.session_state.messages.append({
        "role": "assistant",
        "content": response,
        "avatar": "🤖"
    })

    with st.chat_message("assistant", avatar="🤖"):
        st.write(response)

App Fragments

Create reusable, independently updating app components for better performance and modularity.

def fragment(func):
    """
    Decorator to create app fragment that can update independently.

    Args:
        func (callable): Function to convert to fragment

    Returns:
        callable: Fragment function that can be called with arguments
    """

Example usage:

@st.fragment
def live_metrics_fragment():
    """Fragment that updates metrics independently."""
    col1, col2, col3 = st.columns(3)

    with col1:
        cpu_usage = get_cpu_usage()  # Real-time data
        st.metric("CPU Usage", f"{cpu_usage}%")

    with col2:
        memory_usage = get_memory_usage()
        st.metric("Memory", f"{memory_usage}%")

    with col3:
        active_users = get_active_users()
        st.metric("Active Users", active_users)

    # Auto-refresh every 5 seconds
    time.sleep(5)
    st.rerun()

@st.fragment
def data_table_fragment(data, filters):
    """Fragment for data table that updates based on filters."""
    filtered_data = apply_filters(data, filters)
    st.dataframe(filtered_data)

    if st.button("Export Data"):
        export_data(filtered_data)
        st.success("Data exported!")

# Main app
st.title("Dashboard")

# Independent fragments
live_metrics_fragment()  # Updates independently

# Fragment with parameters
data = load_data()
current_filters = st.selectbox("Filter by", ["All", "Active", "Inactive"])
data_table_fragment(data, current_filters)

Modal Dialogs

Create modal dialog overlays for focused user interactions and confirmations.

def dialog(title, *, width="small"):
    """
    Create modal dialog container that overlays the main content.

    Args:
        title (str): Dialog title displayed in header
        width (str): Dialog width ("small", "medium", "large")

    Returns:
        DeltaGenerator: Dialog container context manager
    """

Example usage:

# Dialog trigger
if st.button("Open Settings"):
    st.session_state.show_settings = True

# Dialog content
if st.session_state.get("show_settings", False):
    @st.dialog("Application Settings")
    def settings_dialog():
        st.write("Configure your application settings")

        # Settings form
        theme = st.selectbox("Theme", ["Light", "Dark"])
        notifications = st.checkbox("Enable notifications")
        auto_save = st.checkbox("Auto-save changes")

        col1, col2 = st.columns(2)
        with col1:
            if st.button("Save", type="primary"):
                save_settings(theme, notifications, auto_save)
                st.session_state.show_settings = False
                st.rerun()

        with col2:
            if st.button("Cancel"):
                st.session_state.show_settings = False
                st.rerun()

    settings_dialog()

# Confirmation dialog
if st.button("Delete Item"):
    st.session_state.confirm_delete = True

if st.session_state.get("confirm_delete", False):
    @st.dialog("Confirm Deletion", width="medium")
    def confirm_dialog():
        st.warning("Are you sure you want to delete this item?")
        st.write("This action cannot be undone.")

        col1, col2 = st.columns(2)
        with col1:
            if st.button("Delete", type="primary"):
                delete_item()
                st.session_state.confirm_delete = False
                st.success("Item deleted!")
                st.rerun()

        with col2:
            if st.button("Cancel"):
                st.session_state.confirm_delete = False
                st.rerun()

    confirm_dialog()

Database Connections

Streamlined database connectivity with built-in connection management and query capabilities.

def connection(name, type=None, **kwargs):
    """
    Create or retrieve database connection with automatic management.

    Args:
        name (str): Connection name for reuse
        type (str, optional): Connection type ("sql", "snowflake", etc.)
        **kwargs: Connection-specific parameters

    Returns:
        Connection: Database connection object with query methods
    """

Example usage:

# SQL database connection
conn = st.connection("my_database", type="sql", url="sqlite:///data.db")

# Execute query
@st.cache_data
def load_data():
    return conn.query("SELECT * FROM users WHERE active = 1")

data = load_data()
st.dataframe(data)

# Snowflake connection
snow_conn = st.connection(
    "snowflake_db",
    type="snowflake",
    account=st.secrets["snowflake"]["account"],
    user=st.secrets["snowflake"]["user"],
    password=st.secrets["snowflake"]["password"],
    database="ANALYTICS",
    schema="PUBLIC"
)

# Query with parameters
@st.cache_data
def get_sales_data(start_date, end_date):
    query = """
    SELECT date, product, sales
    FROM sales_data
    WHERE date BETWEEN %s AND %s
    ORDER BY date
    """
    return snow_conn.query(query, params=(start_date, end_date))

# Custom connection parameters
postgres_conn = st.connection(
    "postgres",
    type="sql",
    url="postgresql://user:password@localhost/mydb",
    engine_kwargs={
        "pool_size": 10,
        "pool_recycle": 3600
    }
)

Advanced Application Patterns

Real-time Chat Application

import time
from datetime import datetime

# Initialize chat application
if "chat_history" not in st.session_state:
    st.session_state.chat_history = []
    st.session_state.user_name = ""

# User setup
if not st.session_state.user_name:
    st.session_state.user_name = st.text_input("Enter your name to start chatting:")
    if not st.session_state.user_name:
        st.stop()

st.title(f"💬 Chat - Welcome {st.session_state.user_name}!")

# Chat history fragment (updates independently)
@st.fragment
def chat_history_fragment():
    """Display chat messages with real-time updates."""
    chat_container = st.container(height=400, border=True)

    with chat_container:
        for message in st.session_state.chat_history:
            timestamp = message.get("timestamp", "")
            with st.chat_message(message["role"], avatar=message["avatar"]):
                st.write(f"**{message['name']}** - {timestamp}")
                st.write(message["content"])

# Display chat history
chat_history_fragment()

# Message input
message = st.chat_input("Type your message...")

if message:
    # Add message to history
    new_message = {
        "role": "user",
        "name": st.session_state.user_name,
        "content": message,
        "avatar": "🧑‍💻",
        "timestamp": datetime.now().strftime("%H:%M:%S")
    }

    st.session_state.chat_history.append(new_message)

    # Simulate bot response
    if message.lower().startswith("!bot"):
        bot_response = generate_bot_response(message[5:])  # Remove "!bot "
        bot_message = {
            "role": "assistant",
            "name": "ChatBot",
            "content": bot_response,
            "avatar": "🤖",
            "timestamp": datetime.now().strftime("%H:%M:%S")
        }
        st.session_state.chat_history.append(bot_message)

    st.rerun()

Interactive Dashboard with Fragments

@st.fragment
def metric_cards_fragment():
    """Independent metrics that update frequently."""
    col1, col2, col3, col4 = st.columns(4)

    with col1:
        revenue = get_current_revenue()
        st.metric("Revenue", f"${revenue:,.2f}", delta="12.5%")

    with col2:
        users = get_active_users()
        st.metric("Active Users", f"{users:,}", delta="5.2%")

    with col3:
        conversion = get_conversion_rate()
        st.metric("Conversion Rate", f"{conversion:.1f}%", delta="-1.2%")

    with col4:
        satisfaction = get_satisfaction_score()
        st.metric("Satisfaction", f"{satisfaction}/5", delta="0.3")

@st.fragment
def interactive_chart_fragment(data, chart_type, filters):
    """Chart fragment that updates based on user selections."""
    filtered_data = apply_dashboard_filters(data, filters)

    if chart_type == "Line":
        st.line_chart(filtered_data)
    elif chart_type == "Bar":
        st.bar_chart(filtered_data)
    elif chart_type == "Area":
        st.area_chart(filtered_data)

# Main dashboard
st.title("📊 Real-time Dashboard")

# Independent metrics (updates every few seconds)
metric_cards_fragment()

# Interactive controls
col1, col2 = st.columns([1, 3])

with col1:
    chart_type = st.selectbox("Chart Type", ["Line", "Bar", "Area"])
    date_range = st.date_input("Date Range", value=[datetime.now() - timedelta(days=30), datetime.now()])
    categories = st.multiselect("Categories", ["Sales", "Marketing", "Support"])

with col2:
    # Load data
    dashboard_data = load_dashboard_data()
    filters = {
        "date_range": date_range,
        "categories": categories
    }

    # Interactive chart fragment
    interactive_chart_fragment(dashboard_data, chart_type, filters)

Modal-Based Workflows

# Workflow state management
workflow_states = {
    "create_project": False,
    "edit_item": None,
    "confirm_action": None
}

for state_key in workflow_states:
    if state_key not in st.session_state:
        st.session_state[state_key] = workflow_states[state_key]

# Main interface
st.title("Project Management")

# Action buttons
col1, col2, col3 = st.columns(3)

with col1:
    if st.button("➕ New Project", type="primary"):
        st.session_state.create_project = True

with col2:
    if st.button("📝 Edit Selected"):
        if selected_item := get_selected_item():
            st.session_state.edit_item = selected_item

with col3:
    if st.button("🗑️ Delete Selected"):
        if selected_item := get_selected_item():
            st.session_state.confirm_action = f"delete_{selected_item['id']}"

# Create Project Dialog
if st.session_state.create_project:
    @st.dialog("Create New Project", width="large")
    def create_project_dialog():
        st.write("Enter project details:")

        project_name = st.text_input("Project Name*")
        description = st.text_area("Description")

        col1, col2 = st.columns(2)
        with col1:
            start_date = st.date_input("Start Date")
            priority = st.selectbox("Priority", ["Low", "Medium", "High"])

        with col2:
            due_date = st.date_input("Due Date")
            assignee = st.selectbox("Assignee", get_team_members())

        # Dialog actions
        col1, col2 = st.columns(2)
        with col1:
            if st.button("Create Project", type="primary", disabled=not project_name):
                create_new_project({
                    "name": project_name,
                    "description": description,
                    "start_date": start_date,
                    "due_date": due_date,
                    "priority": priority,
                    "assignee": assignee
                })
                st.session_state.create_project = False
                st.success("Project created!")
                st.rerun()

        with col2:
            if st.button("Cancel"):
                st.session_state.create_project = False
                st.rerun()

    create_project_dialog()

# Edit Item Dialog
if st.session_state.edit_item:
    @st.dialog("Edit Item", width="medium")
    def edit_item_dialog():
        item = st.session_state.edit_item
        st.write(f"Editing: {item['name']}")

        # Editable fields
        new_name = st.text_input("Name", value=item['name'])
        new_status = st.selectbox("Status", ["Active", "Completed", "On Hold"],
                                index=["Active", "Completed", "On Hold"].index(item['status']))

        # Save/Cancel actions
        col1, col2 = st.columns(2)
        with col1:
            if st.button("Save Changes", type="primary"):
                update_item(item['id'], {"name": new_name, "status": new_status})
                st.session_state.edit_item = None
                st.success("Item updated!")
                st.rerun()

        with col2:
            if st.button("Cancel"):
                st.session_state.edit_item = None
                st.rerun()

    edit_item_dialog()

# Confirmation Dialog
if st.session_state.confirm_action:
    @st.dialog("Confirm Action")
    def confirmation_dialog():
        action = st.session_state.confirm_action

        if action.startswith("delete_"):
            item_id = action.split("_")[1]
            st.warning(f"Are you sure you want to delete item {item_id}?")
            st.write("This action cannot be undone.")

        col1, col2 = st.columns(2)
        with col1:
            if st.button("Confirm", type="primary"):
                execute_action(action)
                st.session_state.confirm_action = None
                st.success("Action completed!")
                st.rerun()

        with col2:
            if st.button("Cancel"):
                st.session_state.confirm_action = None
                st.rerun()

    confirmation_dialog()

Install with Tessl CLI

npx tessl i tessl/pypi-streamlit

docs

advanced-features.md

caching-performance.md

components-config.md

display-elements.md

index.md

input-widgets.md

layout-containers.md

navigation-pages.md

state-management.md

user-auth.md

tile.json