{"spec_id":"dashboard-metrics-tiles","library":"plotly","language":"python","code":"\"\"\" anyplot.ai\ndashboard-metrics-tiles: Real-Time Dashboard Tiles\nLibrary: plotly 6.7.0 | Python 3.13.13\nQuality: 84/100 | Updated: 2026-05-21\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport plotly.graph_objects as go\nfrom plotly.subplots import make_subplots\n\n\n# Theme tokens\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nELEVATED_BG = \"#FFFDF6\" if THEME == \"light\" else \"#242420\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\n\n# Sparkline fill alpha: brighter in dark mode to compensate for blending\nFILL_ALPHA = 0.15 if THEME == \"light\" else 0.28\n\n# Data - 6 metric tiles for a 3x2 dashboard layout\nnp.random.seed(42)\n\nmetrics = [\n    {\n        \"name\": \"CPU Usage\",\n        \"value\": 45,\n        \"unit\": \"%\",\n        \"history\": 30 + np.cumsum(np.random.randn(30) * 2),\n        \"change\": -5.2,\n        \"status\": \"good\",\n        \"higher_is_bad\": True,\n    },\n    {\n        \"name\": \"Memory\",\n        \"value\": 72,\n        \"unit\": \"%\",\n        \"history\": 60 + np.cumsum(np.random.randn(30) * 1.5),\n        \"change\": 8.3,\n        \"status\": \"warning\",\n        \"higher_is_bad\": True,\n    },\n    {\n        \"name\": \"Response Time\",\n        \"value\": 120,\n        \"unit\": \"ms\",\n        \"history\": 100 + np.cumsum(np.random.randn(30) * 5),\n        \"change\": -15.4,\n        \"status\": \"good\",\n        \"higher_is_bad\": True,\n    },\n    {\n        \"name\": \"Requests/sec\",\n        \"value\": 1250,\n        \"unit\": \"\",\n        \"history\": 1000 + np.cumsum(np.random.randn(30) * 50),\n        \"change\": 12.7,\n        \"status\": \"good\",\n        \"higher_is_bad\": False,\n    },\n    {\n        \"name\": \"Error Rate\",\n        \"value\": 2.3,\n        \"unit\": \"%\",\n        \"history\": 1 + np.abs(np.cumsum(np.random.randn(30) * 0.3)),\n        \"change\": 45.0,\n        \"status\": \"critical\",\n        \"higher_is_bad\": True,\n    },\n    {\n        \"name\": \"Disk I/O\",\n        \"value\": 85,\n        \"unit\": \"MB/s\",\n        \"history\": 70 + np.cumsum(np.random.randn(30) * 3),\n        \"change\": -2.1,\n        \"status\": \"good\",\n        \"higher_is_bad\": False,\n    },\n]\n\n# Normalize history for sparklines\nfor m in metrics:\n    hist = np.array(m[\"history\"])\n    m[\"history_norm\"] = (hist - hist.min()) / (hist.max() - hist.min() + 1e-6)\n\n# Status config: color + shape symbol (CVD-safe: shape encodes status independently of color)\nstatus_colors = {\"good\": \"#22c55e\", \"warning\": \"#f59e0b\", \"critical\": \"#ef4444\"}\n# Shape symbols provide non-color differentiation for CVD viewers\nstatus_symbols = {\"good\": \"✓\", \"warning\": \"⚠\", \"critical\": \"✕\"}\n# Border thickness further reinforces status via shape/size cue\nstatus_border_widths = {\"good\": 1, \"warning\": 2, \"critical\": 3}\n\n# Grid layout: 3 columns x 2 rows\nn_cols, n_rows = 3, 2\n\n# Create subplots - indicator type for metric tiles\nfig = make_subplots(\n    rows=n_rows,\n    cols=n_cols,\n    horizontal_spacing=0.08,\n    vertical_spacing=0.12,\n    specs=[[{\"type\": \"indicator\"} for _ in range(n_cols)] for _ in range(n_rows)],\n)\n\n# Add indicator tiles\nfor idx, metric in enumerate(metrics):\n    row = idx // n_cols + 1\n    col = idx % n_cols + 1\n\n    # Delta colors respect direction semantics (decrease is good for CPU, bad for throughput)\n    if metric[\"higher_is_bad\"]:\n        delta_increasing_color = \"#ef4444\"\n        delta_decreasing_color = \"#22c55e\"\n    else:\n        delta_increasing_color = \"#22c55e\"\n        delta_decreasing_color = \"#ef4444\"\n\n    # Include status symbol in label — provides shape cue independent of color for CVD viewers\n    label_with_symbol = f\"{status_symbols[metric['status']]}  {metric['name']}\"\n\n    fig.add_trace(\n        go.Indicator(\n            mode=\"number+delta\",\n            value=metric[\"value\"],\n            number=dict(font=dict(size=48, color=status_colors[metric[\"status\"]]), suffix=metric[\"unit\"]),\n            delta=dict(\n                reference=metric[\"value\"] / (1 + metric[\"change\"] / 100),\n                relative=True,\n                valueformat=\".1%\",\n                font=dict(size=20),\n                increasing=dict(color=delta_increasing_color, symbol=\"▲\"),\n                decreasing=dict(color=delta_decreasing_color, symbol=\"▼\"),\n            ),\n            title=dict(text=label_with_symbol, font=dict(size=22, color=INK)),\n        ),\n        row=row,\n        col=col,\n    )\n\n# Add sparklines as scatter traces with custom axes\nfor idx, metric in enumerate(metrics):\n    row = idx // n_cols + 1\n    col = idx % n_cols + 1\n\n    if row == 1:\n        y_domain = [0.55, 0.95]\n    else:\n        y_domain = [0.05, 0.45]\n\n    if col == 1:\n        x_domain = [0.0, 0.28]\n    elif col == 2:\n        x_domain = [0.36, 0.64]\n    else:\n        x_domain = [0.72, 1.0]\n\n    axis_num = idx + 2\n    x_axis = f\"x{axis_num}\"\n    y_axis = f\"y{axis_num}\"\n\n    x_spark = list(range(len(metric[\"history_norm\"])))\n    y_spark = metric[\"history_norm\"].tolist()\n\n    hex_color = status_colors[metric[\"status\"]]\n    r, g, b = int(hex_color[1:3], 16), int(hex_color[3:5], 16), int(hex_color[5:7], 16)\n\n    fig.add_trace(\n        go.Scatter(\n            x=x_spark,\n            y=y_spark,\n            mode=\"lines\",\n            line=dict(color=hex_color, width=3),\n            fill=\"tozeroy\",\n            fillcolor=f\"rgba({r}, {g}, {b}, {FILL_ALPHA})\",\n            showlegend=False,\n            hoverinfo=\"skip\",\n            xaxis=x_axis,\n            yaxis=y_axis,\n        )\n    )\n\n    sparkline_height = 0.12\n    fig.update_layout(\n        **{\n            f\"xaxis{axis_num}\": dict(\n                domain=[x_domain[0] + 0.02, x_domain[1] - 0.02],\n                range=[0, len(x_spark) - 1],\n                showticklabels=False,\n                showgrid=False,\n                zeroline=False,\n                showline=False,\n                anchor=y_axis,\n            ),\n            f\"yaxis{axis_num}\": dict(\n                domain=[y_domain[0] - 0.02, y_domain[0] + sparkline_height],\n                range=[-0.1, 1.1],\n                showticklabels=False,\n                showgrid=False,\n                zeroline=False,\n                showline=False,\n                anchor=x_axis,\n            ),\n        }\n    )\n\n# Add tile backgrounds with status-aware borders (thickness = additional shape cue for CVD)\nfor idx, metric in enumerate(metrics):\n    row = idx // n_cols + 1\n    col = idx % n_cols + 1\n\n    if row == 1:\n        y_domain = [0.52, 1.0]\n    else:\n        y_domain = [0.0, 0.48]\n\n    if col == 1:\n        x_domain = [0.0, 0.30]\n    elif col == 2:\n        x_domain = [0.35, 0.65]\n    else:\n        x_domain = [0.70, 1.0]\n\n    border_width = status_border_widths[metric[\"status\"]]\n    status_color = status_colors[metric[\"status\"]]\n\n    # Tile fill\n    fig.add_shape(\n        type=\"rect\",\n        xref=\"paper\",\n        yref=\"paper\",\n        x0=x_domain[0],\n        y0=y_domain[0],\n        x1=x_domain[1],\n        y1=y_domain[1],\n        fillcolor=ELEVATED_BG,\n        line=dict(color=status_color, width=border_width),\n        layer=\"below\",\n    )\n\n    # Status accent bar along the top edge of each tile (position cue + color cue)\n    bar_height = 0.012\n    fig.add_shape(\n        type=\"rect\",\n        xref=\"paper\",\n        yref=\"paper\",\n        x0=x_domain[0],\n        y0=y_domain[1] - bar_height,\n        x1=x_domain[1],\n        y1=y_domain[1],\n        fillcolor=status_color,\n        line=dict(width=0),\n        layer=\"above\",\n    )\n\n# Title annotation\nfig.add_annotation(\n    text=\"dashboard-metrics-tiles · python · plotly · anyplot.ai\",\n    x=0.5,\n    y=1.06,\n    xref=\"paper\",\n    yref=\"paper\",\n    showarrow=False,\n    font=dict(size=18, color=INK, family=\"Arial\"),\n    xanchor=\"center\",\n    yanchor=\"top\",\n)\n\n# Layout\nfig.update_layout(autosize=False, paper_bgcolor=PAGE_BG, margin=dict(l=40, r=40, t=80, b=40), showlegend=False)\n\n# Save\nfig.write_image(f\"plot-{THEME}.png\", width=800, height=450, scale=4)\nfig.write_html(f\"plot-{THEME}.html\", include_plotlyjs=\"cdn\")\n"}