Sparkline Advanced
Advanced SparklineChart demo: a liquid glass (glassmorphism) stock card with reveal animation, hover opacity effects and real-time value display.
Overview
An Apple-inspired glassmorphism stock card built around a single SparklineChart, showing how far the component styles with plain CSS:
- liquid glass (glassmorphism) card design —
assets/liquid_glass.css - left-to-right reveal animation on page load
- hover effect: left side 100% opacity, right side 40% opacity, driven by a
CSS custom property the callback sets from hoverIndex
- x-axis highlight line follows the cursor
- real-time value display fed by
hoverIndex/hoverValue
The card's entire look lives in assets/liquid_glass.css (liquid-glass-background, liquid-glass-card, sparkline-container, value-display-panel, …). The component itself only carries data and hover props — delete the stylesheet and the page silently degrades to unstyled divs.
Live example
# File: docs/sparkline-style-advanced/glass_example.py
"""Liquid glass sparkline card — glassmorphism via assets/liquid_glass.css.
Rendered on /sparkline-style-advanced via `.. exec::`; ported verbatim from
the pre-migration pages/sparkline_style_advanced.py (same ids, same
callback).
"""
from dash import html, callback, Input, Output
from dash_mui_charts import SparklineChart
# Stock-like data with realistic movement
STOCK_DATA = [
142.50, 143.20, 141.80, 144.50, 146.20, 145.80, 147.90, 149.20,
148.50, 150.10, 151.80, 150.90, 152.40, 154.20, 153.80, 155.50,
157.20, 156.80, 158.40, 160.10, 159.50, 161.20, 162.80, 164.50
]
# Calculate stats
START_VALUE = STOCK_DATA[0]
END_VALUE = STOCK_DATA[-1]
CHANGE = END_VALUE - START_VALUE
CHANGE_PERCENT = (CHANGE / START_VALUE) * 100
component = html.Div(
className='liquid-glass-background',
children=[
html.Div(
className='liquid-glass-card',
children=[
# Header
html.Div([
html.Span(className='status-dot'),
html.Span('Live', style={
'color': 'rgba(255, 255, 255, 0.7)',
'fontSize': '12px',
'fontWeight': '500',
}),
], style={'marginBottom': '15px'}),
html.H1('AAPL Stock Price', className='glass-title'),
html.P(
'Interactive sparkline with liquid glass design',
className='glass-subtitle'
),
# Sparkline Container
html.Div(
id='sparkline-container',
className='sparkline-container',
children=[
SparklineChart(
id='glass-sparkline',
data=STOCK_DATA,
width=500,
height=100,
color='rgba(79, 195, 247, 1)',
area=True,
curve='monotoneX',
showTooltip=True,
showHighlight=True,
axisHighlight={'x': 'line'},
xAxis={'id': 'x-axis'},
strokeWidth=2,
baseline='min',
slotProps={
'lineHighlight': {'r': 6},
'tooltip': {'disablePortal': True},
},
clipAreaOffset={'top': 10, 'right': 10, 'bottom': 10, 'left': 10},
),
],
),
# Value Display Panel
html.Div(
className='value-display-panel',
children=[
# Current/Hover Value
html.Div(
className='value-display',
children=[
html.Div('VALUE', className='value-label'),
html.Div(
id='hover-value-display',
className='value-number',
children=f'${END_VALUE:.2f}'
),
]
),
# Index/Position
html.Div(
className='value-display',
children=[
html.Div('POSITION', className='value-label'),
html.Div(
id='hover-index-display',
className='value-number',
children=f'{len(STOCK_DATA)}/{len(STOCK_DATA)}'
),
]
),
# Change
html.Div(
className='value-display',
children=[
html.Div('CHANGE', className='value-label'),
html.Div(
id='change-display',
className=f'value-number {"positive" if CHANGE >= 0 else "negative"}',
children=f'{"+$" if CHANGE >= 0 else "-$"}{abs(CHANGE):.2f}'
),
]
),
]
),
# Hover instruction
html.P(
id='hover-instruction',
className='hover-instruction',
children='Hover over the chart to explore values'
),
]
),
]
)
@callback(
Output('sparkline-container', 'style'),
Output('sparkline-container', 'className'),
Output('hover-value-display', 'children'),
Output('hover-index-display', 'children'),
Output('change-display', 'children'),
Output('change-display', 'className'),
Output('hover-instruction', 'className'),
Input('glass-sparkline', 'hoverIndex'),
Input('glass-sparkline', 'hoverValue'),
)
def update_hover_effect(hover_index, hover_value):
data_length = len(STOCK_DATA)
# Base style for container
base_style = {}
if hover_index is not None and hover_value is not None:
# Calculate hover position as percentage
hover_percent = ((hover_index + 1) / data_length) * 100
# Update style with CSS custom property for mask position
new_style = {
**base_style,
'--hover-percent': f'{hover_percent}%',
}
# Add hovering class for mask effect
class_name = 'sparkline-container hovering'
# Format value display
value_text = f'${hover_value:.2f}'
index_text = f'{hover_index + 1}/{data_length}'
# Calculate change from start
change_from_start = hover_value - START_VALUE
change_text = f'{"+$" if change_from_start >= 0 else "-$"}{abs(change_from_start):.2f}'
change_class = f'value-number {"positive" if change_from_start >= 0 else "negative"}'
# Hide instruction when hovering
instruction_class = 'hover-instruction hidden'
else:
# Default state (not hovering)
new_style = base_style
class_name = 'sparkline-container'
# Show end values
value_text = f'${END_VALUE:.2f}'
index_text = f'{data_length}/{data_length}'
change_text = f'{"+$" if CHANGE >= 0 else "-$"}{abs(CHANGE):.2f}'
change_class = f'value-number {"positive" if CHANGE >= 0 else "negative"}'
# Show instruction
instruction_class = 'hover-instruction'
return (
new_style,
class_name,
value_text,
index_text,
change_text,
change_class,
instruction_class,
)
:defaultExpanded: false :withExpandedButton: true
Related pages
- SparklineChart examples — the component's full demo tour
- Styling playground — interactive controls with generated code
Source: /sparkline-style-advanced
Note for AI agents: This is the static, prerendered view of an interactive Dash application served because we detected a non-JS user agent. Full prose docs:
- /sparkline-style-advanced/llms.txt — LLM-friendly documentation
- /sitemap.xml
- /robots.txt