feat(ui): interactive kit charts — hover, highlight, context menu (DASH-2)#146
Merged
Conversation
Adds a shared interaction scaffold to the kit chart SVG renderer (DASH-2) so every registered kind (line/area/bar/pie/donut/scatter/funnel) gets: - Hover/focus tooltip showing the datum's label + formatted value. - Highlight: the active mark emphasises, the rest de-emphasise — driven by a single `.obe-chart-mark` scaffold, not per-kind duplication. - A context menu (right-click AND keyboard) with Copy value + Change chart kind (via the registry). Change-kind is hidden when the chart is read-only / page-locked / group-locked; Copy value stays everywhere. - Keyboard access: data marks are focusable, focus drives the tooltip, and Enter / Space / Menu open the context menu at the datum. `ChartRenderArgs` grows additively with OPTIONAL `interactions`, `block`, `editor`, `width`, `height`; a kind wraps each datum in the new `<Mark>`, which no-ops without a live interaction context — so the static export, provider-less viewer, and existing/serialized charts render unchanged. DB drill (filter source DB to hovered group) is intentionally skipped: the seam isn't clean — `aggregateDbSeries` drops the raw group key, NavigationContext isn't reachable provider-safely, and view filters are persistent mutations with no navigation-time injection. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KFk2T9k3p7ghCjdzMfkA5w
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
- Tooltip no longer escapes the plot at the top edge: it flips below the mark (`.obe-chart-tooltip-below`) when the datum is within ~1 row of the top (max bar / top scatter point / funnel row 1). - a11y: the chart svg is `role="group"` (was `role="img"`) so the now interactive `role="button"` marks and their `label: value` names stay exposed to assistive tech, while the aria-label keeps the accessible name. - Test: the additive-contract test now covers line/area, asserting the true invariant — zero `.obe-chart-mark` wrappers in the no-context path while the always-shipped invisible `.obe-chart-dot` hit circles remain. - Polish: menu icons h-3.5→h-4 (product idiom), menu-anchor left clamped with pctIn like the tooltip, and a forced-colors focus outline on `.obe-chart-mark:focus-visible`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KFk2T9k3p7ghCjdzMfkA5w
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds interactivity to the kit chart SVG renderer across all 7 kinds. Board: DASH-2 (Epic: Dashboards). Builds on the DASH-1 registry + DASH-3 data source.
How (shared scaffold, not per-kind)
A
ChartInteractionContext+ a<Mark datum={{key,label,value}} at={{x,y}}>wrapper carry all behavior; each kind's only change is tagging its datum SVG with<Mark>. All tooltip/highlight/menu logic lives once inChartBlock. With no live context (static export, provider-less viewer, unit tests)Markreturns children unchanged → byte-identical SVG..obe-chart-plotwrapper, positioned by SVG-coord→percentage, showinglabel+ formatted value.aria-hidden(the focused mark'saria-labelannounces it).is-active(brightness + stroke ring; line/scatter surface a dot); othersis-dim(0.32 opacity). Shared CSS, every kind benefits.DropdownMenuanchored at the datum — same menu for right-click and keyboard. Copy value (everywhere, incl. read-only/present) + Change chart kind (radio overchartKinds(), writes thekindprop) gated on!readOnly && !pageLocked && !groupLocked(hidden in viewer/exports/locked groups).ChartRenderArgsadditions (all optional, additive)interactions?({markProps}),block?,editor?,width?,height?. The 7 built-ins never read these directly (they use<Mark>); they exist so a future custom kind drawing outside<Mark>can wire its own handlers. Existing kinds + serialized charts render byte-identically.Accessibility
Each mark is
tabIndex=0,role="button",aria-haspopup="menu",aria-label="{label}: {value}"; focus (not just mouse) drives tooltip+highlight; menu via Enter/Space/ContextMenu key + right-click; focus returns to the datum on close.Scope note
DB-drill ("filter source DB to this group") skipped — the seam is unclean (
aggregateDbSeriesreturns only{value,labels}so the raw group key is lost;useNavigationthrows provider-less; view filters are persistentupdateViewmutations with no navigation-time injection). Reported rather than half-implemented; candidate follow-up. No new chart KINDS (that's DASH-5).Tests / verify
New
chartsInteractive.test.tsx(20): focusable labelled marks + tooltip/highlight + menu (Enter + right-click) + Copy + read-only-gated Change-kind + the additive-contract test (a kind rendered with only{value,labels,palette}produces no.obe-chart-mark).pnpm verifyexit 0;@book.dev/ui111 files / 1015 tests pass.For the design reviewer (no screenshot — app stand-up is disproportionate)
At rest: identical to before. On hover/focus: a popover-styled tooltip (bordered,
--popoverbg, soft shadow, muted label + bold tabular value) above the datum; the mark brightens with a thin foreground stroke ring (line/scatter gain a filled dot); other marks fade to ~32%. Right-click/Enter opens a dropdown at the datum: header "label: value", separator, "Copy value", and (when editable) a "Change chart kind" submenu of the registered kinds.