pypi-streamlit

Description
A faster way to build and share data apps
Author
tessl
Last updated

How to use

npx @tessl/cli registry install tessl/pypi-streamlit@1.50.0

advanced-features.md docs/

1
# Advanced Features
2
3
Chat interfaces, app fragments, modal dialogs, and database connections for sophisticated applications. These features enable building complex, interactive applications with modern UI patterns.
4
5
## Capabilities
6
7
### Chat Interface
8
9
Build conversational interfaces and chatbots with built-in message containers and input handling.
10
11
```python { .api }
12
def chat_message(name, *, avatar=None):
13
"""
14
Create chat message container with sender name and optional avatar.
15
16
Args:
17
name (str): Name of the message sender
18
avatar (str, optional): Avatar image URL, emoji, or user type ("user", "assistant")
19
20
Returns:
21
DeltaGenerator: Chat message container context manager
22
"""
23
24
def chat_input(placeholder=None, key=None, max_chars=None, on_submit=None, args=None, kwargs=None, *, disabled=False):
25
"""
26
Display chat input widget for user message entry.
27
28
Args:
29
placeholder (str, optional): Placeholder text when empty
30
key (str, optional): Unique widget key for state management
31
max_chars (int, optional): Maximum number of characters allowed
32
on_submit (callable, optional): Callback function when message is submitted
33
args (tuple, optional): Arguments for on_submit callback
34
kwargs (dict, optional): Keyword arguments for on_submit callback
35
disabled (bool): Whether input is disabled
36
37
Returns:
38
str: Submitted message text or empty string if no submission
39
"""
40
```
41
42
Example usage:
43
```python
44
# Initialize chat history in session state
45
if "messages" not in st.session_state:
46
st.session_state.messages = []
47
48
# Display chat history
49
for message in st.session_state.messages:
50
with st.chat_message(message["role"], avatar=message.get("avatar")):
51
st.write(message["content"])
52
53
# Chat input
54
user_input = st.chat_input("Type your message here...")
55
56
if user_input:
57
# Add user message to history
58
st.session_state.messages.append({
59
"role": "user",
60
"content": user_input,
61
"avatar": "πŸ§‘β€πŸ’»"
62
})
63
64
# Display user message
65
with st.chat_message("user", avatar="πŸ§‘β€πŸ’»"):
66
st.write(user_input)
67
68
# Generate and display assistant response
69
response = generate_response(user_input) # Your AI logic here
70
71
st.session_state.messages.append({
72
"role": "assistant",
73
"content": response,
74
"avatar": "πŸ€–"
75
})
76
77
with st.chat_message("assistant", avatar="πŸ€–"):
78
st.write(response)
79
```
80
81
### App Fragments
82
83
Create reusable, independently updating app components for better performance and modularity.
84
85
```python { .api }
86
def fragment(func):
87
"""
88
Decorator to create app fragment that can update independently.
89
90
Args:
91
func (callable): Function to convert to fragment
92
93
Returns:
94
callable: Fragment function that can be called with arguments
95
"""
96
```
97
98
Example usage:
99
```python
100
@st.fragment
101
def live_metrics_fragment():
102
"""Fragment that updates metrics independently."""
103
col1, col2, col3 = st.columns(3)
104
105
with col1:
106
cpu_usage = get_cpu_usage() # Real-time data
107
st.metric("CPU Usage", f"{cpu_usage}%")
108
109
with col2:
110
memory_usage = get_memory_usage()
111
st.metric("Memory", f"{memory_usage}%")
112
113
with col3:
114
active_users = get_active_users()
115
st.metric("Active Users", active_users)
116
117
# Auto-refresh every 5 seconds
118
time.sleep(5)
119
st.rerun()
120
121
@st.fragment
122
def data_table_fragment(data, filters):
123
"""Fragment for data table that updates based on filters."""
124
filtered_data = apply_filters(data, filters)
125
st.dataframe(filtered_data)
126
127
if st.button("Export Data"):
128
export_data(filtered_data)
129
st.success("Data exported!")
130
131
# Main app
132
st.title("Dashboard")
133
134
# Independent fragments
135
live_metrics_fragment() # Updates independently
136
137
# Fragment with parameters
138
data = load_data()
139
current_filters = st.selectbox("Filter by", ["All", "Active", "Inactive"])
140
data_table_fragment(data, current_filters)
141
```
142
143
### Modal Dialogs
144
145
Create modal dialog overlays for focused user interactions and confirmations.
146
147
```python { .api }
148
def dialog(title, *, width="small"):
149
"""
150
Create modal dialog container that overlays the main content.
151
152
Args:
153
title (str): Dialog title displayed in header
154
width (str): Dialog width ("small", "medium", "large")
155
156
Returns:
157
DeltaGenerator: Dialog container context manager
158
"""
159
```
160
161
Example usage:
162
```python
163
# Dialog trigger
164
if st.button("Open Settings"):
165
st.session_state.show_settings = True
166
167
# Dialog content
168
if st.session_state.get("show_settings", False):
169
@st.dialog("Application Settings")
170
def settings_dialog():
171
st.write("Configure your application settings")
172
173
# Settings form
174
theme = st.selectbox("Theme", ["Light", "Dark"])
175
notifications = st.checkbox("Enable notifications")
176
auto_save = st.checkbox("Auto-save changes")
177
178
col1, col2 = st.columns(2)
179
with col1:
180
if st.button("Save", type="primary"):
181
save_settings(theme, notifications, auto_save)
182
st.session_state.show_settings = False
183
st.rerun()
184
185
with col2:
186
if st.button("Cancel"):
187
st.session_state.show_settings = False
188
st.rerun()
189
190
settings_dialog()
191
192
# Confirmation dialog
193
if st.button("Delete Item"):
194
st.session_state.confirm_delete = True
195
196
if st.session_state.get("confirm_delete", False):
197
@st.dialog("Confirm Deletion", width="medium")
198
def confirm_dialog():
199
st.warning("Are you sure you want to delete this item?")
200
st.write("This action cannot be undone.")
201
202
col1, col2 = st.columns(2)
203
with col1:
204
if st.button("Delete", type="primary"):
205
delete_item()
206
st.session_state.confirm_delete = False
207
st.success("Item deleted!")
208
st.rerun()
209
210
with col2:
211
if st.button("Cancel"):
212
st.session_state.confirm_delete = False
213
st.rerun()
214
215
confirm_dialog()
216
```
217
218
### Database Connections
219
220
Streamlined database connectivity with built-in connection management and query capabilities.
221
222
```python { .api }
223
def connection(name, type=None, **kwargs):
224
"""
225
Create or retrieve database connection with automatic management.
226
227
Args:
228
name (str): Connection name for reuse
229
type (str, optional): Connection type ("sql", "snowflake", etc.)
230
**kwargs: Connection-specific parameters
231
232
Returns:
233
Connection: Database connection object with query methods
234
"""
235
```
236
237
Example usage:
238
```python
239
# SQL database connection
240
conn = st.connection("my_database", type="sql", url="sqlite:///data.db")
241
242
# Execute query
243
@st.cache_data
244
def load_data():
245
return conn.query("SELECT * FROM users WHERE active = 1")
246
247
data = load_data()
248
st.dataframe(data)
249
250
# Snowflake connection
251
snow_conn = st.connection(
252
"snowflake_db",
253
type="snowflake",
254
account=st.secrets["snowflake"]["account"],
255
user=st.secrets["snowflake"]["user"],
256
password=st.secrets["snowflake"]["password"],
257
database="ANALYTICS",
258
schema="PUBLIC"
259
)
260
261
# Query with parameters
262
@st.cache_data
263
def get_sales_data(start_date, end_date):
264
query = """
265
SELECT date, product, sales
266
FROM sales_data
267
WHERE date BETWEEN %s AND %s
268
ORDER BY date
269
"""
270
return snow_conn.query(query, params=(start_date, end_date))
271
272
# Custom connection parameters
273
postgres_conn = st.connection(
274
"postgres",
275
type="sql",
276
url="postgresql://user:password@localhost/mydb",
277
engine_kwargs={
278
"pool_size": 10,
279
"pool_recycle": 3600
280
}
281
)
282
```
283
284
### Advanced Application Patterns
285
286
#### Real-time Chat Application
287
288
```python
289
import time
290
from datetime import datetime
291
292
# Initialize chat application
293
if "chat_history" not in st.session_state:
294
st.session_state.chat_history = []
295
st.session_state.user_name = ""
296
297
# User setup
298
if not st.session_state.user_name:
299
st.session_state.user_name = st.text_input("Enter your name to start chatting:")
300
if not st.session_state.user_name:
301
st.stop()
302
303
st.title(f"πŸ’¬ Chat - Welcome {st.session_state.user_name}!")
304
305
# Chat history fragment (updates independently)
306
@st.fragment
307
def chat_history_fragment():
308
"""Display chat messages with real-time updates."""
309
chat_container = st.container(height=400, border=True)
310
311
with chat_container:
312
for message in st.session_state.chat_history:
313
timestamp = message.get("timestamp", "")
314
with st.chat_message(message["role"], avatar=message["avatar"]):
315
st.write(f"**{message['name']}** - {timestamp}")
316
st.write(message["content"])
317
318
# Display chat history
319
chat_history_fragment()
320
321
# Message input
322
message = st.chat_input("Type your message...")
323
324
if message:
325
# Add message to history
326
new_message = {
327
"role": "user",
328
"name": st.session_state.user_name,
329
"content": message,
330
"avatar": "πŸ§‘β€πŸ’»",
331
"timestamp": datetime.now().strftime("%H:%M:%S")
332
}
333
334
st.session_state.chat_history.append(new_message)
335
336
# Simulate bot response
337
if message.lower().startswith("!bot"):
338
bot_response = generate_bot_response(message[5:]) # Remove "!bot "
339
bot_message = {
340
"role": "assistant",
341
"name": "ChatBot",
342
"content": bot_response,
343
"avatar": "πŸ€–",
344
"timestamp": datetime.now().strftime("%H:%M:%S")
345
}
346
st.session_state.chat_history.append(bot_message)
347
348
st.rerun()
349
```
350
351
#### Interactive Dashboard with Fragments
352
353
```python
354
@st.fragment
355
def metric_cards_fragment():
356
"""Independent metrics that update frequently."""
357
col1, col2, col3, col4 = st.columns(4)
358
359
with col1:
360
revenue = get_current_revenue()
361
st.metric("Revenue", f"${revenue:,.2f}", delta="12.5%")
362
363
with col2:
364
users = get_active_users()
365
st.metric("Active Users", f"{users:,}", delta="5.2%")
366
367
with col3:
368
conversion = get_conversion_rate()
369
st.metric("Conversion Rate", f"{conversion:.1f}%", delta="-1.2%")
370
371
with col4:
372
satisfaction = get_satisfaction_score()
373
st.metric("Satisfaction", f"{satisfaction}/5", delta="0.3")
374
375
@st.fragment
376
def interactive_chart_fragment(data, chart_type, filters):
377
"""Chart fragment that updates based on user selections."""
378
filtered_data = apply_dashboard_filters(data, filters)
379
380
if chart_type == "Line":
381
st.line_chart(filtered_data)
382
elif chart_type == "Bar":
383
st.bar_chart(filtered_data)
384
elif chart_type == "Area":
385
st.area_chart(filtered_data)
386
387
# Main dashboard
388
st.title("πŸ“Š Real-time Dashboard")
389
390
# Independent metrics (updates every few seconds)
391
metric_cards_fragment()
392
393
# Interactive controls
394
col1, col2 = st.columns([1, 3])
395
396
with col1:
397
chart_type = st.selectbox("Chart Type", ["Line", "Bar", "Area"])
398
date_range = st.date_input("Date Range", value=[datetime.now() - timedelta(days=30), datetime.now()])
399
categories = st.multiselect("Categories", ["Sales", "Marketing", "Support"])
400
401
with col2:
402
# Load data
403
dashboard_data = load_dashboard_data()
404
filters = {
405
"date_range": date_range,
406
"categories": categories
407
}
408
409
# Interactive chart fragment
410
interactive_chart_fragment(dashboard_data, chart_type, filters)
411
```
412
413
#### Modal-Based Workflows
414
415
```python
416
# Workflow state management
417
workflow_states = {
418
"create_project": False,
419
"edit_item": None,
420
"confirm_action": None
421
}
422
423
for state_key in workflow_states:
424
if state_key not in st.session_state:
425
st.session_state[state_key] = workflow_states[state_key]
426
427
# Main interface
428
st.title("Project Management")
429
430
# Action buttons
431
col1, col2, col3 = st.columns(3)
432
433
with col1:
434
if st.button("βž• New Project", type="primary"):
435
st.session_state.create_project = True
436
437
with col2:
438
if st.button("πŸ“ Edit Selected"):
439
if selected_item := get_selected_item():
440
st.session_state.edit_item = selected_item
441
442
with col3:
443
if st.button("πŸ—‘οΈ Delete Selected"):
444
if selected_item := get_selected_item():
445
st.session_state.confirm_action = f"delete_{selected_item['id']}"
446
447
# Create Project Dialog
448
if st.session_state.create_project:
449
@st.dialog("Create New Project", width="large")
450
def create_project_dialog():
451
st.write("Enter project details:")
452
453
project_name = st.text_input("Project Name*")
454
description = st.text_area("Description")
455
456
col1, col2 = st.columns(2)
457
with col1:
458
start_date = st.date_input("Start Date")
459
priority = st.selectbox("Priority", ["Low", "Medium", "High"])
460
461
with col2:
462
due_date = st.date_input("Due Date")
463
assignee = st.selectbox("Assignee", get_team_members())
464
465
# Dialog actions
466
col1, col2 = st.columns(2)
467
with col1:
468
if st.button("Create Project", type="primary", disabled=not project_name):
469
create_new_project({
470
"name": project_name,
471
"description": description,
472
"start_date": start_date,
473
"due_date": due_date,
474
"priority": priority,
475
"assignee": assignee
476
})
477
st.session_state.create_project = False
478
st.success("Project created!")
479
st.rerun()
480
481
with col2:
482
if st.button("Cancel"):
483
st.session_state.create_project = False
484
st.rerun()
485
486
create_project_dialog()
487
488
# Edit Item Dialog
489
if st.session_state.edit_item:
490
@st.dialog("Edit Item", width="medium")
491
def edit_item_dialog():
492
item = st.session_state.edit_item
493
st.write(f"Editing: {item['name']}")
494
495
# Editable fields
496
new_name = st.text_input("Name", value=item['name'])
497
new_status = st.selectbox("Status", ["Active", "Completed", "On Hold"],
498
index=["Active", "Completed", "On Hold"].index(item['status']))
499
500
# Save/Cancel actions
501
col1, col2 = st.columns(2)
502
with col1:
503
if st.button("Save Changes", type="primary"):
504
update_item(item['id'], {"name": new_name, "status": new_status})
505
st.session_state.edit_item = None
506
st.success("Item updated!")
507
st.rerun()
508
509
with col2:
510
if st.button("Cancel"):
511
st.session_state.edit_item = None
512
st.rerun()
513
514
edit_item_dialog()
515
516
# Confirmation Dialog
517
if st.session_state.confirm_action:
518
@st.dialog("Confirm Action")
519
def confirmation_dialog():
520
action = st.session_state.confirm_action
521
522
if action.startswith("delete_"):
523
item_id = action.split("_")[1]
524
st.warning(f"Are you sure you want to delete item {item_id}?")
525
st.write("This action cannot be undone.")
526
527
col1, col2 = st.columns(2)
528
with col1:
529
if st.button("Confirm", type="primary"):
530
execute_action(action)
531
st.session_state.confirm_action = None
532
st.success("Action completed!")
533
st.rerun()
534
535
with col2:
536
if st.button("Cancel"):
537
st.session_state.confirm_action = None
538
st.rerun()
539
540
confirmation_dialog()
541
```