13 MUI X components for Dash — line, bar, candlestick, pie, scatter, composite, heatmap, sparkline and live trading charts, plus TreeView, SimpleTreeView, TreeViewPro and TimeClock — with free and Pro tiers.

MUI Charts

Full documentation: https://muicharts.2plot.dev — the dedicated dash-mui-charts documentation site, with the complete API reference and deeper examples. This page is the quick-start overview.

dash-mui-charts brings MUI X to Plotly Dash — 13 components as of 1.4.0: nine chart types, three tree views and a TimeClock, with an optional Pro tier for zoom, pan, brush and heatmaps.

This page is the catalogue summary with a taste of the charts; the full interactive documentation — 40+ pages with ~250 live examples covering every component and prop — lives at muicharts.2plot.dev.

ComponentLicenseKey Features
LineChartFree + ProLine/area, stacking, zoom/pan (Pro), brush (Pro), reference lines, dateFormat (1.1.0)
BarChartFree + ProVertical/horizontal, stacked/normalized/diverging offsets, dataset mode, zoom + toolbar (Pro)
CandlestickChartFreeOHLC candles, volume overlay, support/resistance reference lines, click events
PieChartFreePie, donut, nested/concentric, gauge-arc, arc labels
ScatterChartFreeMulti-series, z-axis color mapping, voronoi interaction
CompositeChartFree + ProLayer scatter + line, zoom/pan (Pro), biaxial axes
HeatmapProMatrix visualization, continuous/piecewise color scales
SparklineChartFreeCompact inline charts for KPI cards and tables
LiveTradingChartFree + ProReal-time OHLCV candlestick streaming, volume, forecast, alerts
TreeViewFreeData-driven items, expansion/selection control, checkbox propagation, inline label editing
SimpleTreeViewFreeDeclarative tree built from children — dogfooded as the docs site's own sidebar
TreeViewProProKebab submenus, dividers and per-node menus (1.4.0)
TimeClockFreeClock-face time picking, controlled/uncontrolled, 12h/24h, pairs with DMC time inputs

Installation

Visit GitHub Repo · PyPI

pip install dash-mui-charts

For Pro features, set your license key in .env:

MUI_PRO_API_KEY=your-license-key-here

Line Charts

# File: docs/dash_mui_charts/line_basic.py

import os
import random
import math
import dash_mantine_components as dmc
from dash_mui_charts import LineChart

MUI_KEY = os.getenv('MUI_PRO_API_KEY', '')
random.seed(42)
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
revenue = [random.randint(30, 90) for _ in months]
expenses = [random.randint(20, 65) for _ in months]
profit = [r - e for r, e in zip(revenue, expenses)]
temp_data = [round(18 + 12 * math.sin(2 * math.pi * i / 12 - math.pi / 2) + random.uniform(-2, 2), 1) for i in range(12)]

# Extra datasets
random.seed(77)
organic = [random.randint(10, 30) for _ in months]
paid = [random.randint(8, 25) for _ in months]
referral = [random.randint(5, 15) for _ in months]

# Curve comparison data
random.seed(11)
curve_data = [random.randint(20, 80) for _ in range(8)]
curve_labels = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun', 'Mon']

GLASS = {
    "background": "light-dark(rgba(255,255,255,0.55), rgba(30,30,30,0.55))",
    "backdropFilter": "blur(16px) saturate(1.8)",
    "WebkitBackdropFilter": "blur(16px) saturate(1.8)",
    "border": "1px solid light-dark(rgba(255,255,255,0.5), rgba(255,255,255,0.08))",
}

component = dmc.Stack([
    dmc.Text("Line Charts", fw=700, size="xl"),
    dmc.Text("Versatile line and area charts with stacking, curves, reference lines, and biaxial axes.", size="sm", c="dimmed"),

    # --- Multi-Series ---
    dmc.Paper(
        dmc.Stack([
            dmc.Text("Multi-Series Line Chart", fw=600),
            dmc.Text("Revenue vs expenses with profit area fill.", size="sm", c="dimmed"),
            LineChart(
                id="mc-line-basic",
                licenseKey=MUI_KEY,
                series=[
                    {'data': revenue, 'label': 'Revenue ($k)', 'color': '#1976d2', 'curve': 'monotoneX', 'showMark': True},
                    {'data': expenses, 'label': 'Expenses ($k)', 'color': '#f57c00', 'curve': 'monotoneX', 'showMark': True},
                    {'data': profit, 'label': 'Profit ($k)', 'color': '#388e3c', 'curve': 'monotoneX', 'area': True},
                ],
                xAxis=[{'data': months, 'scaleType': 'point', 'label': 'Month'}],
                yAxis=[{'label': 'Amount ($k)'}],
                grid={'horizontal': True, 'vertical': False},
                height=350,
            ),
        ], gap="sm"),
        p="lg", radius="md", style=GLASS,
    ),

    # --- Stacked Area ---
    dmc.Paper(
        dmc.Stack([
            dmc.Text("Stacked Area Chart", fw=600),
            dmc.Text("Stacked areas showing cumulative traffic sources.", size="sm", c="dimmed"),
            LineChart(
                id="mc-line-stacked",
                licenseKey=MUI_KEY,
                series=[
                    {'data': organic, 'label': 'Organic', 'color': '#66bb6a', 'area': True, 'stack': 'traffic', 'curve': 'monotoneX'},
                    {'data': paid, 'label': 'Paid', 'color': '#42a5f5', 'area': True, 'stack': 'traffic', 'curve': 'monotoneX'},
                    {'data': referral, 'label': 'Referral', 'color': '#ab47bc', 'area': True, 'stack': 'traffic', 'curve': 'monotoneX'},
                ],
                xAxis=[{'data': months, 'scaleType': 'point'}],
                yAxis=[{'label': 'Visitors (k)'}],
                grid={'horizontal': True},
                height=300,
            ),
        ], gap="sm"),
        p="lg", radius="md", style=GLASS,
    ),

    # --- Curve Interpolation Comparison ---
    dmc.Paper(
        dmc.Stack([
            dmc.Text("Curve Interpolation", fw=600),
            dmc.Text("Same data rendered with different curve algorithms.", size="sm", c="dimmed"),
            dmc.SimpleGrid(cols={"base": 1, "md": 2}, children=[
                dmc.Stack([
                    dmc.Badge("linear", color="blue", variant="light", size="sm"),
                    LineChart(
                        id="mc-line-curve-linear",
                        licenseKey=MUI_KEY,
                        series=[{'data': curve_data, 'label': 'Value', 'color': '#1976d2', 'curve': 'linear', 'showMark': True}],
                        xAxis=[{'data': curve_labels, 'scaleType': 'point'}],
                        height=180, grid={'horizontal': True},
                    ),
                ], gap=4),
                dmc.Stack([
                    dmc.Badge("monotoneX", color="green", variant="light", size="sm"),
                    LineChart(
                        id="mc-line-curve-mono",
                        licenseKey=MUI_KEY,
                        series=[{'data': curve_data, 'label': 'Value', 'color': '#388e3c', 'curve': 'monotoneX', 'showMark': True}],
                        xAxis=[{'data': curve_labels, 'scaleType': 'point'}],
                        height=180, grid={'horizontal': True},
                    ),
                ], gap=4),
                dmc.Stack([
                    dmc.Badge("natural", color="orange", variant="light", size="sm"),
                    LineChart(
                        id="mc-line-curve-natural",
                        licenseKey=MUI_KEY,
                        series=[{'data': curve_data, 'label': 'Value', 'color': '#f57c00', 'curve': 'natural', 'showMark': True}],
                        xAxis=[{'data': curve_labels, 'scaleType': 'point'}],
                        height=180, grid={'horizontal': True},
                    ),
                ], gap=4),
                dmc.Stack([
                    dmc.Badge("step", color="violet", variant="light", size="sm"),
                    LineChart(
                        id="mc-line-curve-step",
                        licenseKey=MUI_KEY,
                        series=[{'data': curve_data, 'label': 'Value', 'color': '#7b1fa2', 'curve': 'step', 'showMark': True}],
                        xAxis=[{'data': curve_labels, 'scaleType': 'point'}],
                        height=180, grid={'horizontal': True},
                    ),
                ], gap=4),
            ]),
        ], gap="sm"),
        p="lg", radius="md", style=GLASS,
    ),

    # --- Reference Lines ---
    dmc.Paper(
        dmc.Stack([
            dmc.Text("Reference Lines", fw=600),
            dmc.Text("Temperature curve with comfort zone boundaries and a vertical launch marker.", size="sm", c="dimmed"),
            LineChart(
                id="mc-line-ref",
                licenseKey=MUI_KEY,
                series=[
                    {'data': temp_data, 'label': 'Temperature (°C)', 'color': '#ef5350', 'curve': 'natural', 'area': True},
                ],
                xAxis=[{'data': months, 'scaleType': 'point', 'label': 'Month'}],
                yAxis=[{'label': '°C', 'min': 0, 'max': 40}],
                referenceLines=[
                    {'y': 25, 'label': 'Upper comfort', 'lineStyle': {'stroke': '#ff9800', 'strokeDasharray': '5 3'}},
                    {'y': 18, 'label': 'Lower comfort', 'lineStyle': {'stroke': '#2196f3', 'strokeDasharray': '5 3'}},
                    {'x': 'Jun', 'label': 'Summer', 'lineStyle': {'stroke': '#9e9e9e', 'strokeDasharray': '3 3'}},
                ],
                grid={'horizontal': True},
                height=320,
            ),
        ], gap="sm"),
        p="lg", radius="md", style=GLASS,
    ),

    # --- Biaxial ---
    dmc.Paper(
        dmc.Stack([
            dmc.Text("Biaxial (Dual Y-Axis)", fw=600),
            dmc.Text("Revenue on the left axis, growth rate on the right. Independent scales for different units.", size="sm", c="dimmed"),
            LineChart(
                id="mc-line-biaxial",
                licenseKey=MUI_KEY,
                series=[
                    {'data': revenue, 'label': 'Revenue ($k)', 'color': '#1976d2', 'curve': 'monotoneX', 'showMark': True, 'yAxisId': 'left'},
                    {'data': [round(random.uniform(-5, 20), 1) for _ in months], 'label': 'Growth (%)', 'color': '#ef5350', 'curve': 'monotoneX', 'area': True, 'yAxisId': 'right'},
                ],
                xAxis=[{'data': months, 'scaleType': 'point'}],
                yAxis=[
                    {'id': 'left', 'label': 'Revenue ($k)', 'position': 'left'},
                    {'id': 'right', 'label': 'Growth (%)', 'position': 'right'},
                ],
                grid={'horizontal': True},
                height=320,
            ),
        ], gap="sm"),
        p="lg", radius="md", style=GLASS,
    ),
], gap="lg")

Line Charts — Pro Features

# File: docs/dash_mui_charts/line_pro.py

import os
import random
import math
from datetime import datetime, timedelta
import dash_mantine_components as dmc
from dash_mui_charts import LineChart

MUI_KEY = os.getenv('MUI_PRO_API_KEY', '')
random.seed(99)

# --- Signal vs Noise (100 points) ---
n = 100
x_vals = list(range(n))
signal = [round(50 + 20 * math.sin(2 * math.pi * i / 25) + random.gauss(0, 5), 1) for i in range(n)]
noise = [round(50 + random.gauss(0, 12), 1) for i in range(n)]

# --- Simulated 2-month hourly sensor data for slider preview ---
random.seed(42)
start_date = datetime(2025, 1, 1)
hours = 24 * 45  # 45 days
timestamps = []
temperature = []
humidity = []
for h in range(hours):
    dt = start_date + timedelta(hours=h)
    timestamps.append(int(dt.timestamp() * 1000))
    day_of_year = dt.timetuple().tm_yday
    hour = dt.hour
    seasonal = 2.0 + 8.0 * math.sin(2 * math.pi * (day_of_year - 30) / 365)
    daily_cycle = 4.0 * math.sin(2 * math.pi * (hour - 6) / 24)
    temp = seasonal + daily_cycle + random.gauss(0, 1.2)
    temperature.append(round(temp, 1))
    hum_base = 65 - 1.5 * (temp - 5)
    humidity.append(round(max(20, min(95, hum_base + random.gauss(0, 3))), 1))

# --- Brush data ---
random.seed(55)
brush_data = [random.randint(10, 90) for _ in range(50)]

GLASS = {
    "background": "light-dark(rgba(255,255,255,0.55), rgba(30,30,30,0.55))",
    "backdropFilter": "blur(16px) saturate(1.8)",
    "WebkitBackdropFilter": "blur(16px) saturate(1.8)",
    "border": "1px solid light-dark(rgba(255,255,255,0.5), rgba(255,255,255,0.08))",
}

component = dmc.Stack([
    dmc.Text("Line Charts — Pro Features", fw=700, size="xl"),
    dmc.Badge("Requires MUI Pro License", color="violet", variant="light", size="sm"),

    # --- Zoom + Pan + Slider ---
    dmc.Paper(
        dmc.Stack([
            dmc.Text("Zoom, Pan & Toolbar", fw=600),
            dmc.Text("Scroll to zoom, drag to pan. Toolbar provides zoom in/out and export. 100 data points.", size="sm", c="dimmed"),
            LineChart(
                id="mc-line-zoom",
                licenseKey=MUI_KEY,
                series=[
                    {'data': signal, 'label': 'Signal', 'color': '#1976d2', 'curve': 'monotoneX'},
                    {'data': noise, 'label': 'Noise', 'color': '#ef5350', 'curve': 'linear', 'showMark': False},
                ],
                xAxis=[{
                    'id': 'x-axis', 'data': x_vals, 'scaleType': 'linear', 'label': 'Sample Index',
                    'zoom': {'minSpan': 10, 'maxSpan': 100, 'panning': True},
                }],
                yAxis=[{'label': 'Value', 'min': 0, 'max': 100}],
                initialZoom=[{'axisId': 'x-axis', 'start': 0, 'end': 40}],
                showSlider=True,
                showToolbar=True,
                grid={'horizontal': True},
                height=400,
            ),
        ], gap="sm"),
        p="lg", radius="md", style=GLASS,
    ),

    # --- Zoom Slider with Preview (Time Series) ---
    dmc.Paper(
        dmc.Stack([
            dmc.Text("Zoom Slider with Preview", fw=600),
            dmc.Group([
                dmc.Text("45 days of simulated hourly sensor data. The slider shows a miniature preview of the full dataset.", size="sm", c="dimmed"),
                dmc.Badge("slider.preview", color="teal", variant="light", size="xs"),
            ]),
            LineChart(
                id="mc-line-slider-preview",
                licenseKey=MUI_KEY,
                height=420,
                series=[{
                    'id': 'temperature',
                    'data': temperature,
                    'label': 'Temperature (°C)',
                    'color': '#ef5350',
                    'showMark': False,
                    'area': True,
                    'curve': 'natural',
                }],
                xAxis=[{
                    'id': 'time-axis',
                    'data': timestamps,
                    'scaleType': 'time',
                    'label': 'Date',
                    'tickMinStep': 3600 * 1000 * 24,
                    'tickLabelStyle': {'angle': 35, 'fontSize': 11, 'textAnchor': 'start'},
                    'height': 50,
                    'zoom': {
                        'minSpan': 2,
                        'panning': True,
                        'filterMode': 'discard',
                        'slider': {'enabled': True, 'preview': True},
                    },
                }],
                yAxis=[{'label': '°C', 'width': 55, 'domainLimit': 'nice'}],
                grid={'horizontal': True},
                margin={'left': 65, 'right': 20, 'top': 20, 'bottom': 70},
                initialZoom=[{'axisId': 'time-axis', 'start': 0, 'end': 25}],
            ),
        ], gap="sm"),
        p="lg", radius="md", style=GLASS,
    ),

    # --- Biaxial with Slider Preview ---
    dmc.Paper(
        dmc.Stack([
            dmc.Text("Biaxial Chart with Slider Preview", fw=600),
            dmc.Text("Temperature and humidity on dual axes. filterMode='discard' auto-adjusts y-axis to visible range.", size="sm", c="dimmed"),
            LineChart(
                id="mc-line-biaxial-preview",
                licenseKey=MUI_KEY,
                height=420,
                series=[
                    {'id': 'temp', 'data': temperature, 'label': 'Temperature (°C)', 'color': '#ef5350', 'showMark': False, 'curve': 'natural', 'yAxisId': 'temp-axis'},
                    {'id': 'hum', 'data': humidity, 'label': 'Humidity (%)', 'color': '#42a5f5', 'showMark': False, 'curve': 'natural', 'yAxisId': 'hum-axis'},
                ],
                xAxis=[{
                    'id': 'biaxial-time',
                    'data': timestamps,
                    'scaleType': 'time',
                    'tickMinStep': 3600 * 1000 * 24,
                    'tickLabelStyle': {'angle': 35, 'fontSize': 11, 'textAnchor': 'start'},
                    'height': 50,
                    'zoom': {
                        'minSpan': 2, 'panning': True, 'filterMode': 'discard',
                        'slider': {'enabled': True, 'preview': True},
                    },
                }],
                yAxis=[
                    {'id': 'temp-axis', 'label': '°C', 'position': 'left', 'width': 50, 'domainLimit': 'nice', 'labelStyle': {'fill': '#ef5350'}},
                    {'id': 'hum-axis', 'label': '%', 'position': 'right', 'width': 50, 'domainLimit': 'nice', 'labelStyle': {'fill': '#42a5f5'}},
                ],
                grid={'horizontal': True},
                margin={'left': 60, 'right': 60, 'top': 20, 'bottom': 70},
                initialZoom=[{'axisId': 'biaxial-time', 'start': 30, 'end': 60}],
            ),
        ], gap="sm"),
        p="lg", radius="md", style=GLASS,
    ),

    # --- Brush Selection ---
    dmc.Paper(
        dmc.Stack([
            dmc.Text("Brush Selection", fw=600),
            dmc.Text("Click and drag to select a range. The brush overlay shows selected values.", size="sm", c="dimmed"),
            LineChart(
                id="mc-line-brush",
                licenseKey=MUI_KEY,
                series=[
                    {'data': brush_data, 'label': 'Metric A', 'color': '#7b1fa2', 'curve': 'monotoneX'},
                ],
                xAxis=[{'data': list(range(50)), 'scaleType': 'linear', 'label': 'Day'}],
                brushConfig={'enabled': True, 'preventTooltip': True},
                brushOverlay='values',
                grid={'horizontal': True},
                height=300,
            ),
        ], gap="sm"),
        p="lg", radius="md", style=GLASS,
    ),

    # --- Highlighting ---
    dmc.Paper(
        dmc.Stack([
            dmc.Text("Item & Axis Highlighting", fw=600),
            dmc.Text("Hover to see per-series highlight scoping — the active series stays vivid while others fade.", size="sm", c="dimmed"),
            LineChart(
                id="mc-line-highlight",
                licenseKey=MUI_KEY,
                series=[
                    {'data': [random.randint(100, 250) for _ in range(12)], 'label': 'Sales 2023', 'color': '#1976d2', 'curve': 'monotoneX', 'showMark': True,
                     'highlightScope': {'highlight': 'series', 'fade': 'global'}},
                    {'data': [random.randint(120, 280) for _ in range(12)], 'label': 'Sales 2024', 'color': '#388e3c', 'curve': 'monotoneX', 'showMark': True,
                     'highlightScope': {'highlight': 'series', 'fade': 'global'}},
                    {'data': [random.randint(80, 200) for _ in range(12)], 'label': 'Sales 2025', 'color': '#f57c00', 'curve': 'monotoneX', 'showMark': True,
                     'highlightScope': {'highlight': 'series', 'fade': 'global'}},
                ],
                xAxis=[{'data': ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], 'scaleType': 'point'}],
                yAxis=[{'label': 'Revenue ($k)'}],
                axisHighlight={'x': 'band', 'y': 'line'},
                grid={'horizontal': True},
                height=350,
            ),
        ], gap="sm"),
        p="lg", radius="md", style=GLASS,
    ),
], gap="lg")

Tick Configuration & Date Formatting

New in 1.1.0dateFormat and dateTickFormat let you format time-scale axes directly from Python without writing JavaScript. Use scaleType: 'time' with epoch-ms timestamps, control tick density with tickMinStep, and rotate labels with tickLabelStyle.

PropDescription
dateFormatFormat string for tooltip labels (e.g. "MMM d, YYYY")
dateTickFormatFormat string for axis tick labels (e.g. "M/d")
tickMinStepMinimum ms between ticks — use 86400000 * 7 for weekly ticks
tickNumberApproximate target tick count (D3 rounds for readability)
tickLabelStyle{angle, fontSize, textAnchor} for rotated labels

Format tokens: YYYY (2025), MMM (Jan), MM (01), M (1), dd (01), d (1), HH (00–23), mm (00–59)

# File: docs/dash_mui_charts/tick_hover.py

"""Tick Configuration & Date Formatting — v1.1.0 dateFormat/dateTickFormat."""
import os
import math
import random
import json
from datetime import datetime, timedelta

import dash_mantine_components as dmc
from dash import html, callback, Input, Output
from dash_mui_charts import LineChart

MUI_KEY = os.getenv('MUI_PRO_API_KEY', '')

GLASS = {
    "background": "light-dark(rgba(255,255,255,0.55), rgba(30,30,30,0.55))",
    "backdropFilter": "blur(16px) saturate(1.8)",
    "WebkitBackdropFilter": "blur(16px) saturate(1.8)",
    "border": "1px solid light-dark(rgba(255,255,255,0.5), rgba(255,255,255,0.08))",
}

# ---------------------------------------------------------------------------
# Data — 90-day sensor readings, two sensors
# ---------------------------------------------------------------------------
random.seed(42)

def _make_sensor(start, n, base, noise, trend):
    vals = []
    for i in range(n):
        vals.append(round(base + trend * i + noise * math.sin(i * 0.3) + random.gauss(0, noise * 0.3), 1))
    return vals

_start = datetime(2025, 1, 1)
_n = 90

# Epoch-ms timestamps — required for scaleType: 'time'
timestamps = [
    int((_start + timedelta(days=i)).timestamp()) * 1000
    for i in range(_n)
]

sensor_a = _make_sensor(_start, _n, base=68, noise=5,   trend=0.04)
sensor_b = _make_sensor(_start, _n, base=55, noise=3.5, trend=0.02)

WARNING_THRESHOLD = 78
# Day-45 event marker (epoch-ms)
event_ts = int((_start + timedelta(days=45)).timestamp()) * 1000


# ---------------------------------------------------------------------------
# Chart 1 — dateFormat / dateTickFormat (v1.1.0) + reference lines
# ---------------------------------------------------------------------------
chart_time_scale = dmc.Paper(dmc.Stack([
    dmc.Group([
        dmc.Text("Time-Scale Axis (v1.1.0 dateFormat)", fw=600),
        dmc.Badge("1.1.0", color="teal", variant="light", size="sm"),
    ]),
    dmc.Text(
        "Use scaleType: 'time' with epoch-ms timestamps. "
        "dateFormat controls the tooltip label; dateTickFormat controls axis tick labels. "
        "tickMinStep limits density; tickLabelStyle.angle rotates labels for readability.",
        size="sm", c="dimmed",
    ),
    LineChart(
        id="mc-th-time",
        licenseKey=MUI_KEY,
        height=340,
        series=[
            {
                "data":  sensor_a,
                "label": "Sensor A (°F)",
                "color": "#1976d2",
                "curve": "monotoneX",
                "showMark": False,
                "highlightScope": {"highlight": "series", "fade": "global"},
            },
            {
                "data":  sensor_b,
                "label": "Sensor B (°F)",
                "color": "#7b1fa2",
                "curve": "monotoneX",
                "showMark": False,
                "highlightScope": {"highlight": "series", "fade": "global"},
            },
        ],
        xAxis=[{
            "id":        "mc-th-x",
            "data":      timestamps,
            "scaleType": "time",
            # v1.1.0 built-in date formatting — no JavaScript needed
            "dateFormat":     "MMM d, YYYY",   # tooltip label
            "dateTickFormat": "M/d",            # axis tick labels
            "tickMinStep":    86400 * 1000 * 7, # min 1 week between ticks
            "tickNumber":     10,
            "tickLabelStyle": {"angle": 35, "fontSize": 11, "textAnchor": "start"},
            "height":         70,               # extra space for angled labels
        }],
        yAxis=[{"label": "Temperature (°F)", "min": 48, "max": 85}],
        grid={"horizontal": True},
        axisHighlight={"x": "line"},
        tooltip={"trigger": "axis"},
        margin={"left": 65, "right": 20, "top": 20, "bottom": 90},
        referenceLines=[
            {
                "y":          WARNING_THRESHOLD,
                "label":      "Warning (78°F)",
                "lineStyle":  {"stroke": "#ff9800", "strokeWidth": 2, "strokeDasharray": "5 5"},
                "labelStyle": {"fill": "#ff9800", "fontWeight": "bold"},
                "labelAlign": "end",
            },
            {
                "x":          event_ts,
                "label":      "Calibration",
                "lineStyle":  {"stroke": "#9c27b0", "strokeWidth": 2, "strokeDasharray": "4 4"},
                "labelStyle": {"fill": "#9c27b0"},
                "labelAlign": "start",
            },
        ],
    ),
    dmc.Alert(
        dmc.Code(
            'xAxis=[{"scaleType": "time", "data": epoch_ms, '
            '"dateFormat": "MMM d, YYYY", "dateTickFormat": "M/d", '
            '"tickMinStep": 86400_000 * 7}]'
        ),
        color="blue", variant="light",
    ),
], gap="sm"), p="lg", radius="md", style=GLASS)


# ---------------------------------------------------------------------------
# Chart 2 — axis highlight + click event
# ---------------------------------------------------------------------------
chart_click = dmc.Paper(dmc.Stack([
    dmc.Text("Axis Highlight & Click Events", fw=600),
    dmc.Text(
        "axisHighlight: {'x': 'line'} draws a crosshair; "
        "tooltip: {'trigger': 'axis'} shows all series. "
        "Click any point to capture data via the clickData output prop.",
        size="sm", c="dimmed",
    ),
    LineChart(
        id="mc-th-click",
        licenseKey=MUI_KEY,
        height=300,
        series=[
            {
                "data":  sensor_a,
                "label": "Sensor A",
                "color": "#1976d2",
                "curve": "monotoneX",
                "showMark": True,
                "highlightScope": {"highlight": "item", "fade": "global"},
            },
            {
                "data":  sensor_b,
                "label": "Sensor B",
                "color": "#7b1fa2",
                "curve": "monotoneX",
                "showMark": True,
                "highlightScope": {"highlight": "item", "fade": "global"},
            },
        ],
        xAxis=[{
            "data":      timestamps,
            "scaleType": "time",
            "dateFormat":     "MMM d",
            "dateTickFormat": "M/d",
            "tickMinStep":    86400 * 1000 * 14,
            "tickNumber":     6,
        }],
        yAxis=[{"label": "°F"}],
        grid={"horizontal": True},
        axisHighlight={"x": "line", "y": "line"},
        tooltip={"trigger": "item"},
        margin={"left": 55, "right": 20, "top": 20, "bottom": 50},
    ),
    dmc.Text("Click output:", size="xs", c="dimmed"),
    html.Pre(
        id="mc-th-click-out",
        children="Click a point to see data...",
        style={
            "fontSize": "11px", "margin": 0,
            "padding": "8px 12px", "borderRadius": "6px",
            "background": "light-dark(#f8f9fa, #1a1b1e)",
            "border": "1px solid light-dark(#dee2e6, #373a40)",
        },
    ),
], gap="sm"), p="lg", radius="md", style=GLASS)


component = dmc.Stack([
    dmc.Text("Tick Configuration & Date Formatting", fw=700, size="xl"),
    dmc.Text(
        "Best practices for time-scale axes — epoch-ms data, "
        "built-in date formatting (v1.1.0), angled ticks, reference lines, and click events.",
        size="sm", c="dimmed",
    ),
    chart_time_scale,
    chart_click,
], gap="lg")


# ---------------------------------------------------------------------------
# Callback — click event display
# ---------------------------------------------------------------------------
@callback(
    Output("mc-th-click-out", "children"),
    Input("mc-th-click",      "clickData"),
    prevent_initial_call=True,
)
def show_click(data):
    if not data:
        return "Click a point to see data..."
    return json.dumps(data, indent=2)

Pie Charts

# File: docs/dash_mui_charts/pie_charts.py

import random
import dash_mantine_components as dmc
from dash_mui_charts import PieChart

random.seed(77)

PALETTE = ['#1976d2', '#388e3c', '#f57c00', '#d32f2f', '#7b1fa2', '#00838f', '#c62828', '#4527a0']
GLASS = {
    "background": "light-dark(rgba(255,255,255,0.55), rgba(30,30,30,0.55))",
    "backdropFilter": "blur(16px) saturate(1.8)",
    "WebkitBackdropFilter": "blur(16px) saturate(1.8)",
    "border": "1px solid light-dark(rgba(255,255,255,0.5), rgba(255,255,255,0.08))",
}

market_data = [
    {'id': 0, 'value': 35, 'label': 'Chrome', 'color': '#4285f4'},
    {'id': 1, 'value': 25, 'label': 'Safari', 'color': '#007aff'},
    {'id': 2, 'value': 18, 'label': 'Firefox', 'color': '#ff7139'},
    {'id': 3, 'value': 12, 'label': 'Edge', 'color': '#0078d7'},
    {'id': 4, 'value': 10, 'label': 'Other', 'color': '#9e9e9e'},
]

sales_data = [
    {'id': i, 'value': random.randint(15, 50), 'label': cat}
    for i, cat in enumerate(['Electronics', 'Clothing', 'Food', 'Books', 'Toys'])
]

inner_data = [
    {'id': 0, 'value': 60, 'label': 'Desktop', 'color': '#1565c0'},
    {'id': 1, 'value': 35, 'label': 'Mobile', 'color': '#2e7d32'},
    {'id': 2, 'value': 5, 'label': 'Tablet', 'color': '#e65100'},
]
outer_data = [
    {'id': 0, 'value': 30, 'label': 'Windows', 'color': '#42a5f5'},
    {'id': 1, 'value': 20, 'label': 'macOS', 'color': '#66bb6a'},
    {'id': 2, 'value': 10, 'label': 'Linux', 'color': '#ef5350'},
    {'id': 3, 'value': 20, 'label': 'iOS', 'color': '#ab47bc'},
    {'id': 4, 'value': 15, 'label': 'Android', 'color': '#ffa726'},
    {'id': 5, 'value': 5, 'label': 'iPadOS', 'color': '#26c6da'},
]

component = dmc.Stack([
    dmc.Text("Pie Charts", fw=700, size="xl"),
    dmc.Text("Pie, donut, nested, and gauge-arc variations.", size="sm", c="dimmed"),

    dmc.SimpleGrid(cols={"base": 1, "md": 2}, children=[
        dmc.Paper(
            dmc.Stack([
                dmc.Text("Pie Chart", fw=600),
                dmc.Text("Browser market share with arc labels.", size="sm", c="dimmed"),
                PieChart(id="mc-pie-basic", data=market_data, arcLabel='formattedValue', arcLabelMinAngle=25, colors=PALETTE, height=280),
            ], gap="sm"),
            p="lg", radius="md", style=GLASS,
        ),
        dmc.Paper(
            dmc.Stack([
                dmc.Text("Donut Chart", fw=600),
                dmc.Text("Sales by category with inner radius cutout.", size="sm", c="dimmed"),
                PieChart(id="mc-pie-donut", data=sales_data, innerRadius=60, cornerRadius=4, paddingAngle=2, colors=PALETTE, height=280),
            ], gap="sm"),
            p="lg", radius="md", style=GLASS,
        ),
    ]),

    dmc.Paper(
        dmc.Stack([
            dmc.Text("Nested Concentric Pie", fw=600),
            dmc.Text("Inner ring: device type. Outer ring: OS breakdown.", size="sm", c="dimmed"),
            PieChart(
                id="mc-pie-nested",
                series=[
                    {'data': inner_data, 'innerRadius': 0, 'outerRadius': 70, 'highlightScope': {'fade': 'global', 'highlight': 'item'}},
                    {'data': outer_data, 'innerRadius': 80, 'outerRadius': 110, 'highlightScope': {'fade': 'global', 'highlight': 'item'}},
                ],
                height=300,
            ),
        ], gap="sm"),
        p="lg", radius="md", style=GLASS,
    ),

    dmc.Paper(
        dmc.Stack([
            dmc.Text("Gauge-Style Arc", fw=600),
            dmc.Text("Half-circle gauge using startAngle/endAngle.", size="sm", c="dimmed"),
            dmc.SimpleGrid(cols=2, children=[
                PieChart(
                    id=f"mc-pie-gauge-{i}",
                    data=[
                        {'id': 0, 'value': val, 'label': label, 'color': color},
                        {'id': 1, 'value': 100 - val, 'color': 'light-dark(#e0e0e0, #424242)'},
                    ],
                    startAngle=-90, endAngle=90, innerRadius=50, outerRadius=80, arcLabel='value', height=160,
                )
                for i, (val, label, color) in enumerate([
                    (72, 'CPU', '#1976d2'), (88, 'Disk', '#f57c00'),
                ])
            ]),
        ], gap="sm"),
        p="lg", radius="md", style=GLASS,
    ),
], gap="lg")

Scatter Charts

# File: docs/dash_mui_charts/scatter_charts.py

import random
import dash_mantine_components as dmc
from dash_mui_charts import ScatterChart

random.seed(55)

GLASS = {
    "background": "light-dark(rgba(255,255,255,0.55), rgba(30,30,30,0.55))",
    "backdropFilter": "blur(16px) saturate(1.8)",
    "WebkitBackdropFilter": "blur(16px) saturate(1.8)",
    "border": "1px solid light-dark(rgba(255,255,255,0.5), rgba(255,255,255,0.08))",
}


def make_cluster(cx, cy, n=30, spread=15):
    return [{'x': round(cx + random.gauss(0, spread), 1), 'y': round(cy + random.gauss(0, spread), 1), 'id': i} for i in range(n)]

cluster_a = make_cluster(150, 200, 40)
cluster_b = make_cluster(300, 150, 35)
cluster_c = make_cluster(220, 350, 30)

z_data = [{'x': round(random.uniform(0, 100), 1), 'y': round(random.uniform(0, 100), 1), 'z': round(random.uniform(0, 100), 1), 'id': i} for i in range(60)]

component = dmc.Stack([
    dmc.Text("Scatter Charts", fw=700, size="xl"),
    dmc.Text("Multi-series scatter plots with clustering, z-axis coloring, and voronoi interaction.", size="sm", c="dimmed"),

    dmc.Paper(
        dmc.Stack([
            dmc.Text("Multi-Series Clusters", fw=600),
            dmc.Text("Three distinct clusters with voronoi hover detection.", size="sm", c="dimmed"),
            ScatterChart(
                id="mc-scatter-clusters",
                series=[
                    {'id': 'cluster-a', 'label': 'Group A', 'data': cluster_a, 'color': '#1976d2', 'markerSize': 5},
                    {'id': 'cluster-b', 'label': 'Group B', 'data': cluster_b, 'color': '#388e3c', 'markerSize': 5},
                    {'id': 'cluster-c', 'label': 'Group C', 'data': cluster_c, 'color': '#f57c00', 'markerSize': 5},
                ],
                xAxis=[{'label': 'Feature X', 'min': 50, 'max': 400}],
                yAxis=[{'label': 'Feature Y', 'min': 50, 'max': 450}],
                voronoiMaxRadius=40,
                grid={'horizontal': True, 'vertical': True},
                height=380,
            ),
        ], gap="sm"),
        p="lg", radius="md", style=GLASS,
    ),

    dmc.Paper(
        dmc.Stack([
            dmc.Text("Z-Axis Color Mapping", fw=600),
            dmc.Text("Third dimension mapped to a continuous color scale.", size="sm", c="dimmed"),
            ScatterChart(
                id="mc-scatter-zaxis",
                series=[
                    {'id': 'z-series', 'label': 'Intensity', 'data': z_data, 'markerSize': 7, 'highlightScope': {'highlight': 'item', 'fade': 'global'}},
                ],
                zAxis=[{'colorMap': {'type': 'continuous', 'min': 0, 'max': 100, 'color': ['#e3f2fd', '#1565c0']}}],
                xAxis=[{'label': 'X', 'min': -5, 'max': 105}],
                yAxis=[{'label': 'Y', 'min': -5, 'max': 105}],
                voronoiMaxRadius=25,
                grid={'horizontal': True, 'vertical': True},
                height=380,
            ),
        ], gap="sm"),
        p="lg", radius="md", style=GLASS,
    ),
], gap="lg")

Composite Charts

# File: docs/dash_mui_charts/composite_charts.py

import os
import random
import math
import dash_mantine_components as dmc
from dash_mui_charts import CompositeChart

MUI_KEY = os.getenv('MUI_PRO_API_KEY', '')
random.seed(33)

GLASS = {
    "background": "light-dark(rgba(255,255,255,0.55), rgba(30,30,30,0.55))",
    "backdropFilter": "blur(16px) saturate(1.8)",
    "WebkitBackdropFilter": "blur(16px) saturate(1.8)",
    "border": "1px solid light-dark(rgba(255,255,255,0.5), rgba(255,255,255,0.08))",
}


n = 50
scatter_data = [{'x': i, 'y': round(20 + 0.4 * i + random.gauss(0, 4), 1), 'id': i} for i in range(n)]
trend_line = [round(20 + 0.4 * i, 1) for i in range(n)]

component = dmc.Stack([
    dmc.Text("Composite Charts", fw=700, size="xl"),
    dmc.Text("Layer scatter points and line series on a single chart surface.", size="sm", c="dimmed"),

    dmc.Paper(
        dmc.Stack([
            dmc.Text("Scatter + Trend Line", fw=600),
            dmc.Text("Sensor readings with a linear regression overlay and reference limits.", size="sm", c="dimmed"),
            CompositeChart(
                id="mc-composite-trend", licenseKey=MUI_KEY,
                series=[
                    {'type': 'scatter', 'id': 'readings', 'label': 'Readings', 'data': scatter_data, 'markerSize': 4, 'color': '#1976d2'},
                    {'type': 'line', 'id': 'trend', 'label': 'Trend', 'data': trend_line, 'curve': 'linear', 'showMark': False, 'color': '#ff7043'},
                ],
                xAxis=[{'id': 'x', 'data': list(range(n)), 'scaleType': 'linear', 'label': 'Sample', 'zoom': {'minSpan': 10, 'panning': True}}],
                yAxis=[{'label': 'Value'}],
                referenceLines=[
                    {'y': 35, 'label': 'Upper limit', 'lineStyle': {'stroke': '#d32f2f', 'strokeDasharray': '6 3'}},
                    {'y': 15, 'label': 'Lower limit', 'lineStyle': {'stroke': '#1565c0', 'strokeDasharray': '6 3'}},
                ],
                initialZoom=[{'axisId': 'x', 'start': 0, 'end': 60}],
                showSlider=True, voronoiMaxRadius=20,
                grid={'horizontal': True},
                height=400,
            ),
        ], gap="sm"),
        p="lg", radius="md", style=GLASS,
    ),

    dmc.Paper(
        dmc.Stack([
            dmc.Text("Biaxial Composite", fw=600),
            dmc.Text("Temperature scatter on left axis, humidity line on right axis.", size="sm", c="dimmed"),
            CompositeChart(
                id="mc-composite-biaxial", licenseKey=MUI_KEY,
                series=[
                    {'type': 'scatter', 'id': 'temp', 'label': 'Temperature (°C)',
                     'data': [{'x': i, 'y': round(22 + random.gauss(0, 3), 1), 'id': i} for i in range(24)],
                     'markerSize': 5, 'color': '#ef5350', 'yAxisId': 'left'},
                    {'type': 'line', 'id': 'humidity', 'label': 'Humidity (%)',
                     'data': [round(60 + 15 * math.sin(2 * math.pi * i / 24) + random.uniform(-3, 3), 1) for i in range(24)],
                     'curve': 'natural', 'showMark': False, 'color': '#42a5f5', 'area': True, 'yAxisId': 'right'},
                ],
                xAxis=[{'data': list(range(24)), 'scaleType': 'linear', 'label': 'Hour'}],
                yAxis=[{'id': 'left', 'label': '°C', 'position': 'left'}, {'id': 'right', 'label': '%', 'position': 'right'}],
                grid={'horizontal': True},
                height=350,
            ),
        ], gap="sm"),
        p="lg", radius="md", style=GLASS,
    ),
], gap="lg")

Heatmap Charts

# File: docs/dash_mui_charts/heatmap_charts.py

import os
import random
import dash_mantine_components as dmc
from dash_mui_charts import Heatmap

MUI_KEY = os.getenv('MUI_PRO_API_KEY', '')
random.seed(88)

GLASS = {
    "background": "light-dark(rgba(255,255,255,0.55), rgba(30,30,30,0.55))",
    "backdropFilter": "blur(16px) saturate(1.8)",
    "WebkitBackdropFilter": "blur(16px) saturate(1.8)",
    "border": "1px solid light-dark(rgba(255,255,255,0.5), rgba(255,255,255,0.08))",
}


days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
hours = [f'{h}:00' for h in range(6, 22)]

activity_data = []
for xi, day in enumerate(days):
    for yi, hour in enumerate(hours):
        base = 30 if xi < 5 and 3 <= yi <= 10 else 10
        val = max(0, min(100, base + random.randint(-10, 40)))
        activity_data.append([xi, yi, val])

labels = ['Revenue', 'Traffic', 'Conversions', 'Ad Spend', 'Satisfaction']
corr_data = []
for i in range(len(labels)):
    for j in range(len(labels)):
        val = 1.0 if i == j else round(random.uniform(-0.3, 0.95), 2)
        corr_data.append([i, j, val])

component = dmc.Stack([
    dmc.Text("Heatmap Charts", fw=700, size="xl"),
    dmc.Group([
        dmc.Text("Matrix visualization with continuous and piecewise color scales.", size="sm", c="dimmed"),
        dmc.Badge("Pro Feature", color="violet", variant="light", size="sm"),
    ]),

    dmc.Paper(
        dmc.Stack([
            dmc.Text("Website Activity Heatmap", fw=600),
            dmc.Text("Visitor activity by day and hour. Darker = more active.", size="sm", c="dimmed"),
            Heatmap(
                id="mc-heatmap-activity", licenseKey=MUI_KEY,
                data=activity_data,
                xAxis={'data': days, 'label': 'Day'},
                yAxis={'data': hours, 'label': 'Hour'},
                colorScale={'type': 'continuous', 'min': 0, 'max': 100, 'colors': ['#e3f2fd', '#1565c0']},
                height=400,
            ),
        ], gap="sm"),
        p="lg", radius="md", style=GLASS,
    ),

    dmc.Paper(
        dmc.Stack([
            dmc.Text("Correlation Matrix", fw=600),
            dmc.Text("Business metric correlations with diverging color scale.", size="sm", c="dimmed"),
            Heatmap(
                id="mc-heatmap-corr", licenseKey=MUI_KEY,
                data=corr_data,
                xAxis={'data': labels},
                yAxis={'data': labels},
                colorScale={'type': 'piecewise', 'thresholds': [-0.5, 0, 0.5], 'colors': ['#d32f2f', '#ffcdd2', '#c8e6c9', '#2e7d32']},
                height=350,
            ),
        ], gap="sm"),
        p="lg", radius="md", style=GLASS,
    ),
], gap="lg")

Sparkline Charts

# File: docs/dash_mui_charts/sparkline_charts.py

import random
import dash_mantine_components as dmc
from dash_mui_charts import SparklineChart

random.seed(66)

GLASS = {
    "background": "light-dark(rgba(255,255,255,0.55), rgba(30,30,30,0.55))",
    "backdropFilter": "blur(16px) saturate(1.8)",
    "WebkitBackdropFilter": "blur(16px) saturate(1.8)",
    "border": "1px solid light-dark(rgba(255,255,255,0.5), rgba(255,255,255,0.08))",
}

def spark_data(n=12, base=50, spread=20):
    return [max(0, round(base + random.uniform(-spread, spread), 1)) for _ in range(n)]

revenue_spark = spark_data(12, 60, 15)
users_spark = spark_data(12, 200, 50)
errors_spark = [random.randint(0, 8) for _ in range(12)]
cpu_spark = spark_data(20, 45, 25)

component = dmc.Stack([
    dmc.Text("Sparkline Charts", fw=700, size="xl"),
    dmc.Text("Compact inline charts for dashboards, tables, and KPI cards.", size="sm", c="dimmed"),

    dmc.SimpleGrid(cols={"base": 1, "sm": 2, "md": 4}, children=[
        dmc.Paper(
            dmc.Stack([
                dmc.Text("Revenue", size="sm", c="dimmed"),
                dmc.Group([dmc.Text(f"${sum(revenue_spark):.0f}k", fw=700, size="xl"), dmc.Badge("+12%", color="green", variant="light", size="sm")], justify="space-between"),
                SparklineChart(id="mc-spark-revenue", data=revenue_spark, plotType='line', color='#1976d2', area=True, curve='monotoneX', height=40, showTooltip=True),
            ], gap="xs"),
            p="md", radius="md", style=GLASS,
        ),
        dmc.Paper(
            dmc.Stack([
                dmc.Text("Active Users", size="sm", c="dimmed"),
                dmc.Group([dmc.Text(f"{users_spark[-1]:.0f}", fw=700, size="xl"), dmc.Badge("+8%", color="green", variant="light", size="sm")], justify="space-between"),
                SparklineChart(id="mc-spark-users", data=users_spark, plotType='line', color='#388e3c', area=True, curve='monotoneX', height=40, showTooltip=True),
            ], gap="xs"),
            p="md", radius="md", style=GLASS,
        ),
        dmc.Paper(
            dmc.Stack([
                dmc.Text("Errors", size="sm", c="dimmed"),
                dmc.Group([dmc.Text(f"{errors_spark[-1]}", fw=700, size="xl"), dmc.Badge("-3%", color="red", variant="light", size="sm")], justify="space-between"),
                SparklineChart(id="mc-spark-errors", data=errors_spark, plotType='bar', color='#ef5350', height=40, showTooltip=True),
            ], gap="xs"),
            p="md", radius="md", style=GLASS,
        ),
        dmc.Paper(
            dmc.Stack([
                dmc.Text("CPU Load", size="sm", c="dimmed"),
                dmc.Group([dmc.Text(f"{cpu_spark[-1]:.0f}%", fw=700, size="xl"), dmc.Badge("stable", color="gray", variant="light", size="sm")], justify="space-between"),
                SparklineChart(id="mc-spark-cpu", data=cpu_spark, plotType='line', color='#f57c00', curve='linear', height=40, showTooltip=True),
            ], gap="xs"),
            p="md", radius="md", style=GLASS,
        ),
    ]),

    dmc.Paper(
        dmc.Stack([
            dmc.Text("Sparkline Variations", fw=600),
            dmc.Text("Different plot types, curves, and configurations.", size="sm", c="dimmed"),
            dmc.SimpleGrid(cols=3, children=[
                dmc.Stack([
                    dmc.Text("Line (monotoneX)", size="xs", c="dimmed", ta="center"),
                    SparklineChart(id="mc-spark-v1", data=spark_data(), plotType='line', color='#1976d2', curve='monotoneX', height=60, area=True, showTooltip=True),
                ], gap="xs"),
                dmc.Stack([
                    dmc.Text("Line (step)", size="xs", c="dimmed", ta="center"),
                    SparklineChart(id="mc-spark-v2", data=spark_data(), plotType='line', color='#7b1fa2', curve='step', height=60, showTooltip=True),
                ], gap="xs"),
                dmc.Stack([
                    dmc.Text("Bar", size="xs", c="dimmed", ta="center"),
                    SparklineChart(id="mc-spark-v3", data=spark_data(8, 30, 20), plotType='bar', color='#388e3c', height=60, showTooltip=True),
                ], gap="xs"),
            ]),
        ], gap="sm"),
        p="lg", radius="md", style=GLASS,
    ),
], gap="lg")

Live Trading Chart

Real-time OHLCV candlestick streaming with volume bars, a forecast line with uncertainty bands, and automatic swing-point alert labels. All simulation parameters are controllable at runtime.

FeatureDescription
CandlesticksOHLCV bars with green/red coloring
VolumeOptional volume histogram (bottom panel)
ForecastForward projection with uncertainty shading
AlertsConfigurable via alertProbability (chance per tick) and alertThresholdPct (minimum % move)
Alert colorsalertUpColor / alertDownColor for label styling
Zoom / SliderPro — range slider preview
# File: docs/dash_mui_charts/live_trading.py

"""Live Trading Chart — real-time OHLCV candlestick simulation with swing-point alerts."""
import os
import dash_mantine_components as dmc
from dash import html, callback, Input, Output, State, ctx
from dash_mui_charts import LiveTradingChart

MUI_KEY = os.getenv('MUI_PRO_API_KEY', '')

GLASS = {
    "background": "light-dark(rgba(255,255,255,0.55), rgba(30,30,30,0.55))",
    "backdropFilter": "blur(16px) saturate(1.8)",
    "WebkitBackdropFilter": "blur(16px) saturate(1.8)",
    "border": "1px solid light-dark(rgba(255,255,255,0.5), rgba(255,255,255,0.08))",
}

component = dmc.Stack([
    dmc.Text("Live Trading Chart", fw=700, size="xl"),
    dmc.Text(
        "Real-time candlestick simulation with OHLCV data, volume bars, "
        "forecast line with uncertainty bands, and swing-point alert labels. "
        "Alerts only fire at confirmed local highs and lows — not on every candle.",
        size="sm", c="dimmed",
    ),

    dmc.Paper(dmc.Stack([

        # ── Controls Row 1: Buttons + Toggles ─────────────────────────────
        dmc.Group([
            dmc.Group([
                dmc.Button("Start", id="mc-lt-start", color="green", size="sm"),
                dmc.Button("Stop",  id="mc-lt-stop",  color="yellow", size="sm", variant="outline"),
                dmc.Button("Reset", id="mc-lt-reset", color="red",    size="sm", variant="outline"),
            ], gap="xs"),
            dmc.Group([
                dmc.Switch(id="mc-lt-volume",  label="Volume",       checked=True,  size="sm"),
                dmc.Switch(id="mc-lt-labels",  label="Price Labels", checked=False, size="sm"),
                dmc.Switch(id="mc-lt-slider",  label="Zoom Preview", checked=True,  size="sm"),
            ], gap="md"),
        ], justify="space-between"),

        # ── Controls Row 2: Sliders ────────────────────────────────────────
        dmc.SimpleGrid(cols={"base": 1, "sm": 2, "lg": 4}, children=[
            dmc.Stack([
                dmc.Text("Speed (ms/tick)", size="xs", fw=500),
                dmc.Slider(
                    id="mc-lt-speed", value=200, min=50, max=1000, step=50,
                    marks=[
                        {"value": 50,   "label": "50"},
                        {"value": 200,  "label": "200"},
                        {"value": 500,  "label": "500"},
                        {"value": 1000, "label": "1s"},
                    ],
                ),
            ], gap=4),
            dmc.Stack([
                dmc.Text("Volatility", size="xs", fw=500),
                dmc.Slider(
                    id="mc-lt-volatility", value=2.0, min=0.5, max=8.0, step=0.5,
                    marks=[
                        {"value": 0.5, "label": "0.5"},
                        {"value": 2.0, "label": "2.0"},
                        {"value": 8.0, "label": "8.0"},
                    ],
                ),
            ], gap=4),
            dmc.Stack([
                dmc.Text("Drift", size="xs", fw=500),
                dmc.Slider(
                    id="mc-lt-drift", value=0.1, min=-0.5, max=0.5, step=0.05,
                    marks=[
                        {"value": -0.5, "label": "-0.5"},
                        {"value": 0,    "label": "0"},
                        {"value": 0.5,  "label": "+0.5"},
                    ],
                ),
            ], gap=4),
            dmc.Stack([
                dmc.Text("Window", size="xs", fw=500),
                dmc.Slider(
                    id="mc-lt-window", value=80, min=30, max=200, step=10,
                    marks=[
                        {"value": 30,  "label": "30"},
                        {"value": 80,  "label": "80"},
                        {"value": 200, "label": "200"},
                    ],
                ),
            ], gap=4),
        ]),

        # ── Stats Row ──────────────────────────────────────────────────────
        dmc.Group([
            dmc.Stack([
                dmc.Text("Price",  size="xs", c="dimmed"),
                dmc.Text(id="mc-lt-price",  children="$100.00", fw=700, size="lg"),
            ], gap=0, align="center"),
            dmc.Stack([
                dmc.Text("Ticks",  size="xs", c="dimmed"),
                dmc.Text(id="mc-lt-ticks",  children="0",       fw=700, size="lg"),
            ], gap=0, align="center"),
            dmc.Stack([
                dmc.Text("Alerts", size="xs", c="dimmed"),
                dmc.Text(id="mc-lt-alerts", children="0",       fw=700, size="lg"),
            ], gap=0, align="center"),
            dmc.Stack([
                dmc.Text("Status", size="xs", c="dimmed"),
                dmc.Text(id="mc-lt-status", children="Stopped", fw=700, size="lg", c="dimmed"),
            ], gap=0, align="center"),
        ], gap="xl"),

        # ── Chart ──────────────────────────────────────────────────────────
        LiveTradingChart(
            id="mc-lt-chart",
            licenseKey=MUI_KEY,
            height=520,
            running=False,
            intervalMs=200,
            seed=42,
            windowSize=80,
            forecastSize=20,
            initialPrice=100,
            volatility=0.02,
            drift=0.001,
            forecastVolatility=1.5,
            # Alert tuning — low probability + high threshold keeps labels sparse
            alertProbability=0.03,   # 3% chance per tick (vs default 8%)
            alertThresholdPct=3.0,   # minimum 3% move to qualify
            alertUpColor="#4caf50",
            alertDownColor="#f44336",
            showVolume=True,
            showLabels=False,
            showSlider=True,
            volumeHeightPct=20,
            margin={"left": 75, "right": 30, "top": 20, "bottom": 50},
        ),

        # ── Alert History ──────────────────────────────────────────────────
        dmc.Text("Recent Alerts", fw=600, size="sm"),
        html.Pre(
            id="mc-lt-log",
            children="Alerts will appear here once running...",
            style={
                "fontSize": "11px", "maxHeight": "130px",
                "overflow": "auto", "margin": 0,
                "padding": "8px 12px", "borderRadius": "6px",
                "background": "light-dark(#f8f9fa, #1a1b1e)",
                "border": "1px solid light-dark(#dee2e6, #373a40)",
            },
        ),

    ], gap="md"), p="lg", radius="md", style=GLASS),
], gap="md")


# ── Callbacks ─────────────────────────────────────────────────────────────────

@callback(
    Output("mc-lt-chart", "running"),
    Input("mc-lt-start", "n_clicks"),
    Input("mc-lt-stop",  "n_clicks"),
    prevent_initial_call=True,
)
def toggle_running(_start, _stop):
    return ctx.triggered_id == "mc-lt-start"


@callback(
    Output("mc-lt-chart", "resetTrigger"),
    Input("mc-lt-reset", "n_clicks"),
    prevent_initial_call=True,
)
def reset_chart(n):
    return n or 0


@callback(Output("mc-lt-chart", "intervalMs"),  Input("mc-lt-speed",      "value"))
def set_speed(val):      return val or 200

@callback(Output("mc-lt-chart", "volatility"),  Input("mc-lt-volatility", "value"))
def set_volatility(val): return (val or 2.0) / 100

@callback(Output("mc-lt-chart", "drift"),       Input("mc-lt-drift",      "value"))
def set_drift(val):      return (val or 0) / 100

@callback(Output("mc-lt-chart", "windowSize"),  Input("mc-lt-window",     "value"))
def set_window(val):     return val or 80

@callback(Output("mc-lt-chart", "showVolume"),  Input("mc-lt-volume",     "checked"))
def set_volume(v):       return v if v is not None else True

@callback(Output("mc-lt-chart", "showLabels"),  Input("mc-lt-labels",     "checked"))
def set_labels(v):       return v if v is not None else False

@callback(Output("mc-lt-chart", "showSlider"),  Input("mc-lt-slider",     "checked"))
def set_slider(v):       return v if v is not None else True


@callback(
    Output("mc-lt-price",  "children"),
    Output("mc-lt-price",  "c"),
    Output("mc-lt-ticks",  "children"),
    Output("mc-lt-status", "children"),
    Output("mc-lt-status", "c"),
    Input("mc-lt-chart",   "currentPrice"),
    Input("mc-lt-chart",   "tickCount"),
    State("mc-lt-chart",   "running"),
)
def update_stats(price, ticks, running):
    p = price if price is not None else 100.0
    return (
        f"${p:,.2f}",
        "green" if p >= 100 else "red",
        str(ticks or 0),
        "Running" if running else "Stopped",
        "green" if running else "dimmed",
    )


@callback(
    Output("mc-lt-alerts", "children"),
    Output("mc-lt-log",    "children"),
    Input("mc-lt-chart",   "alertHistory"),
)
def update_alerts(alerts):
    if not alerts:
        return "0", "Alerts will appear here once running..."
    recent = list(reversed(alerts[-15:]))
    lines = [
        f"[Tick {a.get('tick', '?'):>5}]  "
        f"{'UP' if a.get('type') == 'up' else 'DN'}  "
        f"${a.get('price', 0):>8.2f}  ({a.get('message', '')})"
        for a in recent
    ]
    return str(len(alerts)), "\n".join(lines)

LineChart Properties

PropertyTypeDefaultDescription
serieslistRequiredArray of series objects with data, label, color, curve, area, stack
xAxislistNoneX-axis config: data, scaleType, label, zoom (Pro)
yAxislistNoneY-axis config: label, position, min, max
referenceLineslistNoneHorizontal/vertical reference lines
licenseKeystring""MUI Pro license key (for zoom, brush, slider)
initialZoomlistNoneInitial zoom state (Pro)
showSliderboolFalseShow zoom range slider (Pro)
showToolbarboolFalseShow zoom/export toolbar (Pro)
brushConfigdictNoneBrush selection config (Pro)
griddictNoneGrid lines: {horizontal: bool, vertical: bool}
heightint300Chart height in pixels
colorslistNoneCustom color palette
axisHighlightdictNone{x: 'none'/'line'/'band', y: 'none'/'line'}
tooltipdictNone{trigger: 'axis'/'item'/'none'}
clickDatadictOutputClick event data
highlightedItemdictNoneControlled highlight state
dateFormatstringNone1.1.0 — Tooltip date format for scaleType: 'time' (e.g. "MMM d, YYYY")
dateTickFormatstringNone1.1.0 — Axis tick date format for scaleType: 'time' (e.g. "M/d")

PieChart Properties

PropertyTypeDefaultDescription
datalistNoneArray of {id, value, label, color} objects
serieslistNoneMulti-series for nested pies
innerRadiusint0Donut hole radius (>0 = donut)
outerRadiusintNoneOuter radius
cornerRadiusint0Rounded slice corners
paddingAngleint0Gap between slices (degrees)
startAngleint0Arc start angle
endAngleint360Arc end angle
arcLabelstringNone'value', 'label', 'formattedValue'
arcLabelMinAngleint0Min angle to show label
heightint300Chart height

ScatterChart Properties

PropertyTypeDefaultDescription
serieslistRequiredArray of series with data: [{x, y, z?, id}]
zAxislistNoneZ-axis color mapping config
voronoiMaxRadiusintNoneProximity hover radius
xAxislistNoneX-axis config
yAxislistNoneY-axis config
heightint300Chart height

Heatmap Properties (Pro)

PropertyTypeDefaultDescription
datalistRequiredArray of [x_index, y_index, value]
xAxisdictRequired{data: [...], label: "..."}
yAxisdictRequired{data: [...], label: "..."}
colorScaledictRequired{type, min, max, colors} or {type, thresholds, colors}
licenseKeystringRequiredMUI Pro license key
heightint300Chart height

LiveTradingChart Properties

PropertyTypeDefaultDescription
runningboolFalseStart / stop the simulation tick
intervalMsint200Milliseconds between ticks
windowSizeint80Number of visible candles
forecastSizeint20Candles projected ahead
initialPricefloat100Starting price
volatilityfloat0.02Per-tick price volatility (e.g. 0.02 = 2%)
driftfloat0.001Per-tick price drift (positive = upward trend)
forecastVolatilityfloat1.5Uncertainty band width multiplier
seedintNoneRandom seed for reproducibility
showVolumeboolTrueShow volume histogram
showLabelsboolFalseShow price labels on candles
showSliderboolFalseShow zoom range slider (Pro)
volumeHeightPctint20Volume panel height as % of chart height
alertProbabilityfloat0.08Probability of an alert firing per tick (lower = fewer labels)
alertThresholdPctfloat2.0Minimum % price change required to trigger an alert
alertUpColorstring"#4caf50"Label color for upward alert moves
alertDownColorstring"#f44336"Label color for downward alert moves
margindictNoneChart margins {left, right, top, bottom}
licenseKeystring""MUI Pro license key
resetTriggerintNoneIncrement to reset simulation
currentPricefloatOutputCurrent simulated price
tickCountintOutputNumber of ticks elapsed
alertHistorylistOutputArray of {type, tick, price, message} alert objects

Contributing

Contributions welcome! Visit the GitHub repo.

License

MIT License (component). MUI X Pro license required for Pro features.

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: