73 lines
3.7 KiB
Markdown
73 lines
3.7 KiB
Markdown
# 110 — Clicking a legend entry should focus that series, fading the rest
|
|
|
|
## Summary
|
|
|
|
`PanelChart`'s line and pie charts render a recharts `<Legend>`
|
|
(`webapp/src/components/PanelChart.tsx:134`, `:190`) but it's purely
|
|
decorative — clicking an entry does nothing. Bar charts have no
|
|
`<Legend>` at all (`:151-168`), since each bar is its own labeled
|
|
category on the x-axis rather than a separate series.
|
|
|
|
Add click-to-focus: clicking a legend entry marks that series
|
|
"focused"; any focused series stay at full opacity/stroke while every
|
|
other series fades. Clicking the same entry again (or clicking empty
|
|
space in the legend, per whatever recharts exposes) clears focus and
|
|
returns everyone to equal opacity — i.e. "no focused series" means
|
|
"all at the same opacity", not "all faded".
|
|
|
|
## Where
|
|
|
|
- `webapp/src/components/PanelChart.tsx:116-148` — line chart. Series
|
|
are recharts `<Line>` elements keyed by `keys` (from `toLineData`,
|
|
`:60-78`), colored via `COLORS[i % COLORS.length]` (`:140`). Fading
|
|
a line means varying `strokeOpacity` (or swapping `stroke` for a
|
|
`color-mix`'d faded variant) per key based on focus state.
|
|
- `webapp/src/components/PanelChart.tsx:170-193` — pie chart. Slices
|
|
are `<Cell>` elements (`:179-181`) keyed by row index into `rows`
|
|
(from `squashRows`, `:50-57`); fading a slice means varying its
|
|
`fillOpacity`.
|
|
- `webapp/src/components/PanelChart.tsx:134`, `:190` — the two
|
|
`<Legend>` usages. recharts' `<Legend>` takes an `onClick` handler
|
|
on its payload entries (`(entry) => void`, where `entry.dataKey` /
|
|
`entry.value` identifies which series was clicked) — this is the
|
|
hook point rather than building a custom legend from scratch.
|
|
- Bar charts (`:151-168`) have no legend to click, since bars aren't
|
|
named series here — out of scope for this ticket unless the
|
|
direction chosen below turns out to need bar-chart parity (see
|
|
Scope).
|
|
|
|
## Direction
|
|
|
|
- Add focus state as a `Set<string>` (or single nullable string, if
|
|
only one series can be focused at a time — decide during
|
|
implementation) of series keys, local to `PanelChart` via
|
|
`useState`. Reset it when `series` changes identity to avoid stale
|
|
focus surviving a query change onto a chart with different series.
|
|
- Wire the `<Legend>`'s `onClick` to toggle membership in that set.
|
|
- Compute per-series opacity from the set: full opacity if the set is
|
|
empty or the series is a member, faded (e.g. `0.25`) otherwise.
|
|
Thread that into `<Line stroke=...>` / `<Cell fill=...>` via
|
|
`strokeOpacity`/`fillOpacity` rather than swapping the base color,
|
|
so the existing `COLORS` palette and its `color-mix` theming stay
|
|
untouched.
|
|
- The legend entries themselves should visually reflect focus too
|
|
(e.g. dim the faded entries' swatch/text) so it's clear what's
|
|
focused without hunting across the plot — recharts' legend
|
|
`formatter` prop can restyle each entry's label.
|
|
|
|
## Scope
|
|
|
|
- Line and pie charts only, matching where `<Legend>` already
|
|
renders. Bar charts stay as-is — no legend, no per-bar fade — unless
|
|
investigation shows recharts' bar `<Legend>` support is trivial to
|
|
add alongside this; if so, note it as a follow-up rather than
|
|
folding scope creep into this ticket.
|
|
- Out of scope: persisting focus state across re-renders driven by
|
|
polling (`Dashboards.tsx`'s `PanelPreview`, `:46-92`, re-fetches on
|
|
every poll tick) — focus should survive a data refresh as long as
|
|
the series identity (legend key) is unchanged, but there's no need
|
|
to persist it to `localStorage` or across a page reload.
|
|
- Out of scope: multi-select "compare exactly these two series" UX
|
|
beyond simple toggle-membership — keep it to click-to-add/click-to-
|
|
remove from the focused set.
|