Reusable React-based Streamlit components with Tailwind CSS styling
Project description
Streamlit React Components
A collection of 12 reusable React-based Streamlit components with Tailwind CSS styling. All components support custom inline styles and Tailwind class names.
Installation
pip install streamlit-react-components
Quick Start
import streamlit as st
from streamlit_react_components import (
panel, section_header, stat_card, metric_row,
data_table, step_indicator, button_group, chart_legend,
plotly_chart, form_select, form_slider, checkbox_group
)
Styling
All components accept two styling parameters:
| Parameter | Type | Description |
|---|---|---|
style |
dict |
Inline CSS as Python dict (e.g., {"background": "#1e293b", "padding": "16px"}) |
class_name |
str |
Tailwind CSS classes (e.g., "bg-slate-900 p-4 rounded-lg") |
Example
stat_card(
label="Revenue",
value="$50K",
color="blue",
style={"minWidth": "200px", "boxShadow": "0 4px 6px rgba(0,0,0,0.3)"},
class_name="border border-blue-500"
)
Components
1. Panel
A styled container/card wrapper.
panel(
children: str = "", # HTML content
style: dict = None,
class_name: str = "",
key: str = None
) -> None
Example
panel(
children="<h3 style='color: white;'>Title</h3><p style='color: #94a3b8;'>Content here</p>",
class_name="border border-blue-500"
)
Default Styling
- Background:
bg-slate-900 - Border radius:
rounded-lg - Padding:
p-4
2. Section Header
A section title with optional action buttons.
section_header(
title: str, # Header text
icon: str = "", # Emoji or icon prefix
actions: list = None, # List of action buttons
style: dict = None,
class_name: str = "",
key: str = None
) -> str | None # Returns clicked action ID
Actions Format
actions = [
{"id": "refresh", "label": "Refresh", "color": "blue"},
{"id": "export", "icon": "📥", "label": "Export", "color": "green"}
]
| Action Key | Type | Description |
|---|---|---|
id |
str |
Unique identifier (returned on click) |
label |
str |
Button text (optional) |
icon |
str |
Emoji/icon (optional) |
color |
str |
Preset ("blue", "green", "red", "yellow", "purple", "slate") or hex (e.g., "#94a3b8") |
style |
dict |
Inline CSS styles for this button (optional) |
className |
str |
Tailwind classes for this button (optional) |
href |
str |
URL for link actions. External URLs (http/https) open in new tab (optional) |
Example
# Using preset colors
clicked = section_header(
title="Executive Summary",
icon="📊",
actions=[
{"id": "refresh", "label": "Refresh", "color": "blue"},
{"id": "settings", "icon": "⚙️", "color": "slate"}
]
)
# Using hex colors and custom styling
clicked = section_header(
title="Custom Actions",
actions=[
{"id": "custom", "label": "Custom", "color": "#ff5733"},
{"id": "styled", "label": "Styled", "style": {"padding": "12px", "borderRadius": "20px"}}
]
)
# External link (opens in new tab)
section_header(
title="Resources",
actions=[
{"id": "docs", "label": "Documentation", "href": "https://docs.example.com", "icon": "📚"},
{"id": "github", "label": "GitHub", "href": "https://github.com", "color": "slate"}
]
)
# Internal page navigation
clicked = section_header(
title="Settings",
actions=[{"id": "home", "label": "Home", "icon": "🏠"}]
)
if clicked == "home":
st.switch_page("pages/home.py")
3. Stat Card
A statistics display card with colored accent.
stat_card(
label: str, # Description text
value: str | int | float, # The statistic value
color: str = "blue", # Accent color
icon: str = "", # Optional icon
style: dict = None,
class_name: str = "",
key: str = None
) -> None
Colors
Supports preset color names or hex values:
| Preset | Border | Text |
|---|---|---|
"blue" |
border-blue-500 |
text-blue-400 |
"green" |
border-green-500 |
text-green-400 |
"red" |
border-red-500 |
text-red-400 |
"yellow" |
border-yellow-500 |
text-yellow-400 |
"purple" |
border-purple-500 |
text-purple-400 |
"slate" |
border-slate-500 |
text-slate-400 |
"#xxxxxx" |
Custom hex color | Custom hex color |
Example
col1, col2, col3, col4 = st.columns(4)
with col1:
stat_card(label="Within Threshold", value="4", color="green")
with col2:
stat_card(label="Above (Risk)", value="2", color="red")
with col3:
stat_card(label="Below (Underutil)", value="1", color="yellow")
with col4:
stat_card(label="Avg OEE", value="78.4%", color="blue")
# Using hex color
stat_card(label="Custom Color", value="42", color="#ff5733")
4. Metric Row
A key-value display row.
metric_row(
label: str, # Left-side label
value: str, # Right-side value
value_color: str = "", # Tailwind text color class
style: dict = None,
class_name: str = "",
key: str = None
) -> None
Example
metric_row(label="Mean", value="78.4%")
metric_row(label="Median", value="79.0%")
metric_row(label="Outliers", value="3", value_color="text-red-400")
metric_row(label="Trend", value="↑ +0.4%/mo", value_color="text-green-400")
Common Value Colors
| Color | Class |
|---|---|
| Green | text-green-400 |
| Red | text-red-400 |
| Yellow | text-yellow-400 |
| Blue | text-blue-400 |
| Gray | text-slate-400 |
5. Data Table
A styled data table with row click support.
data_table(
columns: list, # Column definitions
rows: list, # Row data
show_header: bool = True,
style: dict = None,
class_name: str = "",
key: str = None
) -> dict | None # Returns {rowIndex, rowData} on click
Column Definition
columns = [
{"key": "name", "label": "Name"},
{"key": "value", "label": "Value", "align": "right", "format": "number"},
{"key": "percent", "label": "%", "align": "center", "format": "percent"},
{"key": "status", "label": "Status", "colorByValue": True}
]
| Column Key | Type | Description |
|---|---|---|
key |
str |
Data key in row dict |
label |
str |
Column header text |
align |
str |
"left", "center", "right" |
format |
str |
"number" (adds commas), "percent" (adds %) |
colorByValue |
bool |
Color based on status values |
Auto-Colored Values
When colorByValue: True, these values get automatic colors:
| Value | Color |
|---|---|
"above" |
Red |
"below" |
Yellow |
"within" |
Green |
"approved" |
Green |
"rejected" |
Red |
"submitted" |
Yellow |
"draft" |
Gray |
Example
columns = [
{"key": "site", "label": "Site"},
{"key": "line", "label": "Line"},
{"key": "util", "label": "Utilization", "align": "right", "format": "percent"},
{"key": "volume", "label": "Volume", "align": "right", "format": "number"},
{"key": "status", "label": "Status", "align": "center", "colorByValue": True}
]
rows = [
{"site": "AML_14", "line": "L1", "util": 94, "volume": 125000, "status": "above"},
{"site": "ADL", "line": "L2", "util": 72, "volume": 98000, "status": "within"},
{"site": "Devens", "line": "L3", "util": 58, "volume": 45000, "status": "below"}
]
clicked = data_table(columns=columns, rows=rows)
if clicked:
st.write(f"Selected row {clicked['rowIndex']}: {clicked['rowData']}")
6. Step Indicator
A multi-step wizard progress indicator.
step_indicator(
steps: list, # List of step labels
current_step: int, # Current step (1-indexed)
style: dict = None,
class_name: str = "",
key: str = None
) -> int | None # Returns clicked step number
Example
if "step" not in st.session_state:
st.session_state.step = 1
clicked = step_indicator(
steps=["Supply Plan", "Configure Levers", "Review & Submit"],
current_step=st.session_state.step
)
if clicked:
st.session_state.step = clicked
st.rerun()
Visual States
| State | Appearance |
|---|---|
| Completed (< current) | Green circle with ✓ |
| Current | Blue circle with number |
| Future (> current) | Gray circle with number |
7. Button Group
A group of action buttons.
button_group(
buttons: list, # List of button configs
style: dict = None,
class_name: str = "",
key: str = None
) -> str | None # Returns clicked button ID
Button Definition
buttons = [
{"id": "view", "icon": "👁️"},
{"id": "edit", "icon": "✏️", "label": "Edit"},
{"id": "approve", "icon": "✓", "color": "green"},
{"id": "reject", "icon": "✕", "color": "red", "disabled": True}
]
| Button Key | Type | Description |
|---|---|---|
id |
str |
Unique identifier (returned on click) |
label |
str |
Button text (optional) |
icon |
str |
Emoji/icon (optional) |
color |
str |
Preset ("blue", "green", "red", "yellow", "purple", "slate") or hex (e.g., "#94a3b8") |
disabled |
bool |
Disable the button |
style |
dict |
Inline CSS styles for this button (optional) |
className |
str |
Tailwind classes for this button (optional) |
Example
# Using preset colors
clicked = button_group(
buttons=[
{"id": "view", "icon": "👁️", "label": "View"},
{"id": "edit", "icon": "✏️", "label": "Edit"},
{"id": "delete", "icon": "🗑️", "color": "red"}
]
)
# Using hex colors and custom styling
clicked = button_group(
buttons=[
{"id": "custom", "icon": "🎨", "color": "#ff5733"},
{"id": "styled", "label": "Styled", "style": {"padding": "12px"}}
]
)
if clicked == "delete":
st.warning("Delete clicked!")
8. Chart Legend
A legend for charts with colored indicators.
chart_legend(
items: list, # List of legend items
style: dict = None,
class_name: str = "",
key: str = None
) -> None
Items Format
items = [
{"color": "#94a3b8", "label": "Historical"},
{"color": "#ef4444", "label": "Outlier"},
{"color": "#8b5cf6", "label": "Prophet"},
{"color": "#10b981", "label": "ARIMA"}
]
Example
# Display a chart (using st.line_chart, plotly, etc.)
st.line_chart(data)
# Add legend below
chart_legend(
items=[
{"color": "#3b82f6", "label": "Actual"},
{"color": "#ef4444", "label": "Upper Threshold"},
{"color": "#eab308", "label": "Lower Threshold"},
{"color": "#8b5cf6", "label": "Forecast"}
]
)
9. Plotly Chart
Render Plotly charts with full interactivity and event callbacks.
plotly_chart(
# Data source (one required)
figure: Any = None, # Plotly figure or dict
data: DataFrame = None, # pandas DataFrame
# DataFrame options (when using data=)
x: str = None, # Column name for x-axis
y: str | list = None, # Column name(s) for y-axis
color: str = None, # Column name for color grouping
chart_type: str = "line", # "line", "bar", "scatter", "area", "pie", "histogram"
title: str = None, # Chart title
# Plotly config
config: dict = None, # Plotly config options
# Event callbacks
on_click: bool = False, # Enable click events
on_select: bool = False, # Enable selection events
on_hover: bool = False, # Enable hover events
on_relayout: bool = False, # Enable zoom/pan events
# Expandable dialog
expandable: bool = False, # Show expand button
modal_title: str = "", # Dialog header title
# Styling
style: dict = None,
class_name: str = "",
key: str = None
) -> dict | None # Returns event dict or None
Using Plotly Figure
import plotly.graph_objects as go
fig = go.Figure(
data=[
go.Scatter(x=[1,2,3,4,5], y=[10,15,13,17,20], mode='lines+markers', name='Sales'),
go.Bar(x=[1,2,3,4,5], y=[5,8,6,9,12], name='Orders')
],
layout=go.Layout(title='Sales Dashboard')
)
event = plotly_chart(
figure=fig,
on_click=True,
on_select=True,
style={"height": "400px"}
)
if event and event['type'] == 'click':
st.write(f"Clicked: {event['points']}")
Using DataFrame
import pandas as pd
df = pd.DataFrame({
'month': ['Jan', 'Feb', 'Mar', 'Apr'],
'sales': [100, 150, 120, 180],
'orders': [50, 75, 60, 90]
})
# Simple line chart
event = plotly_chart(
data=df,
x='month',
y='sales',
chart_type='line',
title='Monthly Sales'
)
# Multiple y columns as bar chart
event = plotly_chart(
data=df,
x='month',
y=['sales', 'orders'],
chart_type='bar',
title='Sales vs Orders'
)
# Scatter with color grouping
event = plotly_chart(
data=df,
x='sales',
y='orders',
color='month',
chart_type='scatter'
)
Chart Types (DataFrame mode)
| Type | Description |
|---|---|
"line" |
Line chart with connected points |
"scatter" |
Scatter plot with markers only |
"bar" |
Vertical bar chart |
"area" |
Area chart (filled line) |
"pie" |
Pie chart (x=labels, y=values) |
"histogram" |
Histogram of x values |
Event Types
| Event | When Triggered | Data Returned |
|---|---|---|
click |
User clicks a data point | {type: 'click', points: [...]} |
select |
User box/lasso selects points | {type: 'select', points: [...]} |
hover |
User hovers over a point | {type: 'hover', points: [...]} |
relayout |
User zooms/pans the chart | {type: 'relayout', relayout: {...}} |
Point Data Structure
Each point in the points array contains:
{
"curveNumber": 0, # Index of the trace
"pointNumber": 2, # Index of the point in the trace
"pointIndex": 2, # Same as pointNumber
"x": "Mar", # X value
"y": 120, # Y value
"customdata": None # Custom data if provided
}
Expandable Dialog
Charts can be expanded into a full-page dialog using Streamlit's native st.dialog():
event = plotly_chart(
figure=fig,
expandable=True, # Show expand button in corner
modal_title="Sales Dashboard", # Title in dialog header
style={"height": "300px"}
)
Dialog Features:
- Click the expand icon (⛶) in the top-right corner to open
- Dialog uses Streamlit's native full-width dialog overlay
- Click outside the dialog or press Escape to close
- Chart renders at full dialog width for better visibility
10. Form Select
A styled dropdown select input.
form_select(
label: str, # Label text
options: list, # Options list
value: str = "", # Selected value
groups: list = None, # Option groups (for optgroup)
style: dict = None,
class_name: str = "",
key: str = None
) -> str # Returns selected value
Simple Options
options = ["Option A", "Option B", "Option C"]
Options with Labels
options = [
{"value": "a", "label": "Option A"},
{"value": "b", "label": "Option B"}
]
Grouped Options
groups = [
{"label": "Baselines", "options": ["Baseline v7", "Baseline v6"]},
{"label": "Scenarios", "options": ["Q2 Demand Surge", "OEE Initiative"]}
]
Example
# Simple
site = form_select(
label="Site",
options=["AML_14", "ADL", "Devens"],
value="AML_14"
)
# With groups
scenario = form_select(
label="Base On",
groups=[
{"label": "Baselines", "options": ["Baseline v7 (Current)", "Baseline v6"]},
{"label": "Scenarios", "options": ["Q2 Demand Surge", "OEE Initiative"]}
],
class_name="max-w-xs"
)
11. Form Slider
A styled range slider input.
form_slider(
label: str, # Label text
value: float, # Current value
min_val: float, # Minimum value
max_val: float, # Maximum value
step: float = 1, # Step increment
unit: str = "", # Unit suffix (e.g., "%", "hrs")
color: str = "blue", # Preset or hex color (e.g., "#94a3b8")
style: dict = None,
class_name: str = "",
key: str = None
) -> float # Returns current value
Example
# Percentage slider with preset color
threshold = form_slider(
label="Upper Threshold",
value=90,
min_val=75,
max_val=100,
unit="%",
color="red"
)
# Time slider
hold_time = form_slider(
label="VPHP Hold Time",
value=5.0,
min_val=2.0,
max_val=8.0,
step=0.5,
unit=" hrs",
color="blue"
)
# Slider with hex color
custom_slider = form_slider(
label="Custom Color",
value=50,
min_val=0,
max_val=100,
color="#ff5733"
)
12. Checkbox Group
A group of checkboxes.
checkbox_group(
items: list, # List of checkbox items
label: str = "", # Optional group label
style: dict = None,
class_name: str = "",
key: str = None
) -> list # Returns list of checked item IDs
Items Format
items = [
{"id": "opt1", "label": "Option 1", "checked": True},
{"id": "opt2", "label": "Option 2", "checked": True},
{"id": "opt3", "label": "Option 3"} # checked defaults to False
]
Example
selected = checkbox_group(
label="Parameters to Optimize",
items=[
{"id": "vphp", "label": "VPHP Hold Time", "checked": True},
{"id": "lot_co", "label": "Lot Changeover", "checked": True},
{"id": "campaign_co", "label": "Campaign Changeover"},
{"id": "batch", "label": "Batch Size"}
]
)
st.write(f"Selected parameters: {selected}")
# Output: ['vphp', 'lot_co']
Complete Example App
import streamlit as st
from streamlit_react_components import (
section_header, stat_card, data_table,
form_select, form_slider, checkbox_group
)
st.set_page_config(page_title="Dashboard", layout="wide")
# Header
action = section_header(
title="Production Dashboard",
icon="🏭",
actions=[{"id": "refresh", "label": "Refresh", "color": "blue"}]
)
# Stats row
col1, col2, col3 = st.columns(3)
with col1:
stat_card(label="Lines Active", value="12", color="green")
with col2:
stat_card(label="At Risk", value="3", color="red")
with col3:
stat_card(label="Avg Utilization", value="82%", color="blue")
# Filters
st.markdown("### Filters")
col1, col2 = st.columns(2)
with col1:
site = form_select(label="Site", options=["All", "AML", "ADL", "Devens"])
with col2:
threshold = form_slider(label="Risk Threshold", value=90, min_val=80, max_val=100, unit="%")
# Data table
st.markdown("### Lines Overview")
clicked = data_table(
columns=[
{"key": "line", "label": "Line"},
{"key": "util", "label": "Utilization", "format": "percent", "align": "right"},
{"key": "status", "label": "Status", "colorByValue": True}
],
rows=[
{"line": "L1", "util": 94, "status": "above"},
{"line": "L2", "util": 82, "status": "within"},
{"line": "L3", "util": 65, "status": "below"}
]
)
if clicked:
st.info(f"Selected: {clicked['rowData']['line']}")
Tailwind CSS Classes Reference
Since components use Tailwind CSS, here are commonly used classes:
Spacing
p-1top-8: Paddingm-1tom-8: Marginmt-4,mb-4,ml-4,mr-4: Directional margin
Layout
w-full: Full widthmax-w-xs,max-w-sm,max-w-md: Max widthflex,grid: Display typesgap-2,gap-4: Gap between items
Colors (Dark Theme)
bg-slate-900,bg-slate-800: Backgroundstext-white,text-slate-400: Text colorsborder-slate-700: Border colors
Effects
rounded,rounded-lg: Border radiusshadow,shadow-lg: Box shadowsopacity-50: Transparency
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file streamlit_react_components-1.7.2.tar.gz.
File metadata
- Download URL: streamlit_react_components-1.7.2.tar.gz
- Upload date:
- Size: 1.6 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9ddc16c077ac08c15f4a0918789339120b4f3fa3d4cfe3f9918fd14e1de43693
|
|
| MD5 |
7be5c95fdd6cf7e4fcafbc01f87607c5
|
|
| BLAKE2b-256 |
dd32acd5fd2a37cec9f5f8aba656ac3008dd0c15656505b657c8e25d9717086c
|
File details
Details for the file streamlit_react_components-1.7.2-py3-none-any.whl.
File metadata
- Download URL: streamlit_react_components-1.7.2-py3-none-any.whl
- Upload date:
- Size: 1.6 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0e4d9cfab79884aacbab6994735c32abb7535ffa5b768591878954bb23d28820
|
|
| MD5 |
d64afd03cb01d2ae86f31bbd1307b6f4
|
|
| BLAKE2b-256 |
8d33941005d27bc8c61e8111b4759c644f3c474ce4b688609e45b9bf3b37ca0f
|