Skip to content

moooon

Motir

Vibe your whole project. Bring an idea — Motir's three AI layers plan it, track it, and ship it, end to end. You're looking at Motir, built in Motir.

  • Vibe Project
  • Open Source
  • AI Agent
  • AI Loop
1
requests
0
upvotes
145
planned
1,361
shipped

Motir · Work items

MOTIR-250Done

4.6.2 Reusable token-aware SVG chart primitives in components/ui/ (line/area + grouped bar + axis/grid/legend; a11y data-table fallback) — the viz Story 6.3 reuses

Estimate: 32m · Depends on: 4.6.1

The foundational, reusable chart layer — built once here, consumed by the burndown (4.6.5), the velocity (4.6.6), AND Story 6.3 dashboards ("Charts reuse the viz from Epic 4"). It is design-gated UI, so it carries the 4.6.1 design in dependsOn and is seeded blocked until that lands (Principle #13).

Decision (baked in per the no-shortcut rule): hand-rolled token-aware SVG, not a charting library. The design system routes ALL colour through --el-* and ALL shape through element-semantic tokens (CLAUDE.md); a third-party lib (Recharts / Chart.js / nivo) ships its own styling that bypasses the swap layer, pulls ~80–120 kB for two charts, and fights the a11y model. Two small charts do not earn that. So this subtask builds lightweight SVG primitives that consume the design tokens directly — the durable shape, and the one Epic 6.3 extends.

Build (in components/ui/charts/ or components/ui/):

  • A shared chart frame — responsive SVG viewBox, the X/Y axes + tick labels, gridlines, and a margin/scale helper (a tiny linear-scale util; do NOT add d3). Colour via --el-* (the series tokens 4.6.1 specifies), shape via element shape tokens.
  • A LineChart / area primitive — multiple series, including a STEP-interpolated series (for the burndown actual) and a straight guideline series, with optional point markers (the scope-change markers) and a "now" reference line.
  • A grouped BarChart primitive — N categories × 2 bars (committed/completed) + an optional average reference line.
  • A ChartLegend + the a11y fallback: every chart renders a visible text legend, role="img" + aria-label/aria-describedby summarising the series, and a visually-hidden (or toggle-revealed) <table> of the underlying data — so the chart is conveyed as text+number, never colour/shape alone (finding #35). Charts take data as plain typed props (series arrays + labels); they are PURE presentational components (no fetching, no service imports), unit-testable in isolation and previewable on a specimen//tokens-style page.

Acceptance criteria

  • components/ui exports a LineChart (multi-series, supports a step series + a straight guideline + a reference line + point markers) and a grouped BarChart (paired bars + average reference), plus a shared chart frame (axes/ticks/gridlines) and ChartLegend, matching design/reports/charts.mock.html.
  • Colour comes ONLY from --el-* (the 4.6.1 series tokens, added to globals.css Tier 3 if missing); shape from element shape tokens; no Tier-0 --color-*, no raw rounded-*/p-* for surface shape (motir-core/CLAUDE.md).
  • Each chart is a11y-complete: a visible text legend + axis labels, role="img" with an aria-label/aria-describedby summary, and a data-table fallback conveying every series as text+number (finding #35); colour/shape never the sole signal.
  • The charts are PURE components (typed data props in, SVG out — no data fetching, no service imports); component tests render each with sample data + assert the a11y fallback table; no charting library is added to package.json.
  • The primitive is generic enough for Story 6.3 to reuse (documented in design-notes.md / a short component doc) — not hard-coded to sprints.

Context refs

  • design/reports/charts.mock.html + design/reports/design-notes.md (4.6.1) — the chart visual language + the --el-* series tokens to consume
  • components/ui/* (the existing primitive conventions — props/variants/exports) + the /tokens specimen route pattern (1.0.5) to add a chart specimen
  • app/globals.css Tier-3 --el-* + the element-shape tokens; motir-core/CLAUDE.md (colour via --el-*, shape via element tokens)
  • Story 6.3 (dashboards & reports) — the downstream consumer to keep the API generic for; findings #35 (read as text), #54 (use the palette)