Public: anyone can read this; the crew can change it.

The sparkline helper draws a day with no data as a gap, not a zero #3244

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

`src/web/studio/kpi_row.ts` now exports `daySpark(days: readonly (number | null)[], label: string): Html | null`. A `null` day breaks the line instead of being drawn as a zero. Each run of numbers is its own `<polyline>` inside one `<svg class="kpi-spark">`, and a run of one day is a `<circle r="1.5" fill="currentColor">`. All the runs share one y-scale, which tops out at the largest known value.…

shipped production is serving it deploy e36361f

opened this

src/web/studio/kpi_row.ts now exports daySpark(days: readonly (number | null)[], label: string): Html | null. A null day breaks the line instead of being drawn as a zero. Each run of numbers is its own <polyline> inside one <svg class="kpi-spark">, and a run of one day is a <circle r="1.5" fill="currentColor">. All the runs share one y-scale, which tops out at the largest known value. A series that is empty or all null returns null, so no svg is drawn. Non-finite values also count as missing. The label is escaped with escapeHtml.

  • Existing sparklines unchanged: the point math and the <svg> wrapper moved into two small helpers, at and svg, that spark and daySpark both use. A new test pins the full markup of visitorsSpark and sparkline, and the W/H box is untouched.
  • Design system: no class, colour literal or style= was added, and docs/design/baseline.json is not edited. test/design-lint.test.ts passes, along with home-kpi-row, home-kpis and the type check.
  • Where the issue contradicts itself: it asks for [1, null, 3, 4] to give two polylines, but also says a run of one day is a dot. I kept the dot rule, so [1, null, 3, 4] gives one dot and one polyline, and the test says so. [1, 2, null, 3, 4] gives the two polylines. Both tests check the expected points, worked by hand in the test file, and that nothing is drawn at the zero line.
  • Return type: the issue gives the type as Html, but it also says an all-null series returns nothing, so the type is Html | null. A tile's extra slot already takes null.
  • Not done: no caller uses daySpark yet. Switching the visitors tile over is the other half of #3202.

test/kpi-spark.test.ts fails without the change (it can't import daySpark) and passes with it. Try it with bun test test/kpi-spark.test.ts.

🤖 Generated with Claude Code

Closes #3238

commented

src/web/studio/kpi_row.ts now exports daySpark(days: readonly (number | null)[], label: string): Html | null. A null day breaks the line instead of being drawn as a zero. Each run of numbers is its own <polyline> inside one <svg class="kpi-spark">, and a run of one day is a <circle r="1.5" fill="currentColor">. All the runs share one y-scale, which tops out at the largest known value. A series that is empty or all null returns null, so no svg is drawn. Non-finite values also count as missing. The label is escaped with escapeHtml.

  • Existing sparklines unchanged: the point math and the <svg> wrapper moved into two small helpers, at and svg, that spark and daySpark both use. A new test pins the full markup of visitorsSpark and sparkline, and the W/H box is untouched.
  • Design system: no class, colour literal or style= was added, and docs/design/baseline.json is not edited. test/design-lint.test.ts passes, along with home-kpi-row, home-kpis and the type check.
  • Where the issue contradicts itself: it asks for [1, null, 3, 4] to give two polylines, but also says a run of one day is a dot. I kept the dot rule, so [1, null, 3, 4] gives one dot and one polyline, and the test says so. [1, 2, null, 3, 4] gives the two polylines. Both tests check the expected points, worked by hand in the test file, and that nothing is drawn at the zero line.
  • Return type: the issue gives the type as Html, but it also says an all-null series returns nothing, so the type is Html | null. A tile's extra slot already takes null.
  • Not done: no caller uses daySpark yet. Switching the visitors tile over is the other half of #3202.

test/kpi-spark.test.ts fails without the change (it can't import daySpark) and passes with it. Try it with bun test test/kpi-spark.test.ts.

🤖 Generated with Claude Code

Approved

Matches #3238 as scoped: daySpark breaks the line at null or non-finite days, draws a lone day as a dot, returns null for no data, escapes the label, and reuses .kpi-spark, currentColor and attributes only (no class, colour, style, or baseline edit). The shared at/svg helpers leave visitorsSpark and sparkline byte-identical, and a test pins that. The dot rule over the issue contradictory [1,null,3,4] example is the right call and is explained. No page or script is touched, so there is no JS-off, keyboard or 360px concern; the svg keeps role=img and an aria-label. Two things next: 1) switch the visitors tile to daySpark (the other half of #3202) so it is reachable on the page, since it has no caller today; 2) spark still interpolates its label unescaped; pass it through escapeHtml too or have svg do it once.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs