feat(Sparkline): compact activity bar sparkline - #401
Conversation
Generalizes waggleline's activity-timeline sparkline: pre-bucketed SparklinePoint data (the host owns date math), bars scaled to the series max with zero-value stubs, and optional onSelect turning bars into toggle buttons for bucket filtering. Brand-orange hardcodes become primary tokens; the too-little-signal auto-hide heuristic is left to hosts.
Deploying ui with
|
| Latest commit: |
ae48fb0
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://8538a718.ui-6d0.pages.dev |
| Branch Preview URL: | https://feat-sparkline.ui-6d0.pages.dev |
There was a problem hiding this comment.
Pull request overview
Adds a new lightweight Sparkline component to the design system to support compact “activity-over-time” bar strips (including optional selection) and exposes it via the package entrypoints.
Changes:
- Introduces
Sparklinecomponent with read-only and selectable (toggle button) modes plus accessibility labels/tooltips. - Adds unit tests and Storybook stories for the new component.
- Exports the new component from
src/index.tsand includes it in the tsup build entry map.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tsup.config.ts | Adds Sparkline to the build entrypoints. |
| src/index.ts | Re-exports Sparkline from the library root. |
| src/components/Sparkline/Sparkline.tsx | Implements the compact bar sparkline component (rendering + selection behavior). |
| src/components/Sparkline/Sparkline.test.tsx | Adds unit tests covering scaling, accessible names, and selection toggling. |
| src/components/Sparkline/Sparkline.stories.tsx | Adds Storybook stories and seeded demo data for visual review. |
| src/components/Sparkline/index.ts | Provides the component/type barrel export. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…ates, safelist - Interactive bars get the library's focus-visible ring treatment so keyboard users can see which day is focused - Story data anchors to a fixed date instead of DateTime.now(), keeping labels/keys stable for visual baselines - Bar sizing/gap/hover-tint classes added to both Tailwind 3 safelist twins
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Suppressed comments (2)
Previously missed (1) — in code that hasn't changed since the last review.
src/components/Sparkline/Sparkline.tsx:82
- Computing
maxviaMath.max(1, ...data.map(...))spreads the full dataset into function arguments, which can throw for large arrays (too many arguments) and is slower than a simple reduce. Usingreduceavoids argument-length limits and keeps this safe as a generic primitive.
const max = React.useMemo(
() => Math.max(1, ...data.map((d) => d.value)),
[data]
);
src/tailwind-preset.ts:609
focus-visible:ring-offset-1is already safelisted earlier (src/tailwind-preset.ts:559), so this duplicate entry can be removed to keep the safelist DRY.
'hover:bg-muted-foreground/20',
'focus-visible:ring-offset-1',
…:ring-offset-1 already exist in the TS preset (kept in the CJS twin, whose base list lacks them)
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
src/components/Sparkline/Sparkline.tsx:153
- Add an explicit
displayNamefor thisforwardRefcomponent. Most components in this repo set it (e.g.Button.displayName = 'Button'insrc/components/Button/Button.tsx:186), which improves React DevTools output and error messages.
);
Generalizes waggleline's activity-timeline sparkline into the design system's lightweight charting primitive — the "too small for DataVis" gap.
What it does
formatValuefor units)onSelect, bars becomearia-pressedtoggle buttons for filtering the view to one bucket (click again to clear); omit it for a read-only strip{ key, label?, value }[]) — the host owns date math, so weeks/hours/anything works, not just dayslabel, adjustableheight, primary-token colors; stacked tracks make a compact multi-metric overviewScreenshots
Stacked read-only tracks (Calls / Emails / Meetings, 30 days):
Provenance
Generalized from
waggleline/app/imports/ui/components/activity-timeline/TimelineSparkline.tsx: theTimelineItemcoupling and 30-day bucketing move to the host, brand-orange hardcodes become primary tokens, and the "hide when too little signal" heuristic is left to hosts (it was a product decision, not a component one).Testing
aria-pressed, track label,formatValue, key fallback)typecheck/lint/format/rtl:scanclean; combined batch suite 651/651