fix(charts): align legend swatches with series colors#110
Conversation
Legend color indicators could drift from the bars/lines they label:
- ChartLegendContent drew swatches at full opacity, so series rendered
with fillOpacity (plan-vs-actual "running"/"forecast", the daily/global
"Today (est.)" ghost bar) showed a legend dot in a visibly different
shade — especially obvious on the greyscale chart palette. The swatch
now mirrors the series' fill/stroke opacity and falls back to the
configured --color-{key} token when Recharts omits a payload color.
- daily-by-user and global-metrics used the raw Recharts <Legend>, which
styles swatches/labels differently from every other chart. They now use
the shared ChartLegend + ChartLegendContent for consistent, config-driven
swatches.
Note: chart.tsx was previously not conforming to the repo Prettier config
(no semicolons); the format-on-edit hook normalized the whole file.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
|
There was a problem hiding this comment.
Pull request overview
This PR improves chart legend consistency and accuracy by ensuring legend swatches better match the visual styling of their corresponding series (especially when opacity is used), and by standardizing legend rendering across Claude charts.
Changes:
- Update
ChartLegendContentto mirror series opacity and prefer payload-provided colors for legend swatches. - Switch
daily-by-userandglobal-metricscharts from raw Recharts<Legend>to the sharedChartLegend/ChartLegendContent. - Reformat
chart.tsxto conform to the repository’s Prettier output (semicolon normalization).
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/components/ui/chart.tsx | Adjusts shared chart legend rendering (swatch color/opacity) and applies formatting normalization. |
| src/components/claude/global-metrics-client.tsx | Replaces raw Recharts legend usage with shared chart legend components for consistent styling. |
| src/components/claude/daily-by-user-chart.tsx | Replaces raw Recharts legend usage with shared chart legend components and minor formatting cleanup. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Recharts hands us (the Bar fill / Line stroke), and fall back to the | ||
| // configured `--color-{key}` token so the indicator can never drift | ||
| // from the chart even if the payload color is missing. | ||
| const swatchColor = item.color ?? itemConfig?.color; |
The "Billed" bar turns red (var(--destructive)) on months where actual spend exceeds the plan, via per-<Cell> fills. Recharts derives each legend entry's color from its <Bar>'s fill and ignores Cell overrides, so the red never appeared in the legend — leaving viewers with an unexplained red bar. Wrap ChartLegendContent so an "Over budget" swatch is appended, but only when at least one month actually breaches its plan.
Legend color indicators could drift from the bars/lines they label:
ChartLegendContent drew swatches at full opacity, so series rendered
with fillOpacity (plan-vs-actual "running"/"forecast", the daily/global
"Today (est.)" ghost bar) showed a legend dot in a visibly different
shade — especially obvious on the greyscale chart palette. The swatch
now mirrors the series' fill/stroke opacity and falls back to the
configured --color-{key} token when Recharts omits a payload color.
daily-by-user and global-metrics used the raw Recharts , which
styles swatches/labels differently from every other chart. They now use
the shared ChartLegend + ChartLegendContent for consistent, config-driven
swatches.
Note: chart.tsx was previously not conforming to the repo Prettier config
(no semicolons); the format-on-edit hook normalized the whole file.