feat: KPI / stat tile widget type (#26) #33
Reference in New Issue
Block a user
Delete Branch "ai/issue-26-kpi-tile"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #26
Adds a non-chart dashboard widget: a large value with its label, an optional signed delta versus the previous period, and an optional sparkline. Four tiles (total revenue, open orders, new customers, avg. order value) now sit above the charts,
3x1each.What's in it
components/KpiTile— draws no surface of its own and fills the grid item's, styled from the--dialect-*token layer. Value and delta share one row: stacking them costs a line the tile does not have at its default height of one grid cell. Two new tokens,--dialect-positive/--dialect-negative, carry the delta direction, so it follows the light/dark toggle instead of hardcoding colours.components/SparklineChart— a chrome-free line chart, built from a newDialectTheme.sparklineOptions()so palette and font stay shared with the real charts rather than duplicated.DashboardView— the KPI row is added aty=0and the existing chart widgets shift down one cell. Existing users keep their layout: it is persisted pergs-idinlocalStorage, and no ids changed.Two things worth flagging
The registry registration in the issue is not implemented. #21 (widget registry + picker) is
ai-blocked, so there is nothing to register with yet — the acceptance criterion "addable from the widget picker" is not met. The tiles are wired intoDashboardViewthe same way the chart widgets are; when #21 lands, each becomes oneWidgetDefinitionwith a3x1default size.Values come from the translation bundle, not from a data service — they carry locale-specific formatting (
1,24 Mio. €/€1.24M/1,24 M€). They move to the service in #20, alongside the chart literals that are already there.Verification
./mvnw test— 13 tests green. Two new browserless tests cover value, label and delta rendering (both signs) plus the3x1default size; the existing widget-count assertions were updated for the four extra widgets.Checked in a real browser at
h=1, light and dark: the tile measures exactly its grid item (212x104, no overflow) and both delta colours read against either surface. Two layout bugs surfaced and were fixed there:height: 100%plus content-box padding made the tile 28px taller than its item — it now setsbox-sizing: border-box.sparkline.enableddrops the axes on the initial render, butupdateOptions— how the theme toggle recolours a chart — brings the y-axis labels back, clipped to a smudge at the tile's left edge. They are hidden in CSS, which reaches the chart SVG sinceapex-chart.tsrenders into light DOM.🤖 Generated with Claude Code
https://claude.ai/code/session_0124BiJikbhbiEsNfJxdWM69