bklit-studio-chart-performance

v2026.09.24

Reusable Studio chart performance audit and fix workflow. Use when a chart feels sluggish in /studio (pan, slider ticks, legend hover) but siblings like pie-chart feel fine.

GitHub
Install command
npx skhub add bklit/bklit-studio-chart-performance
Markdown
SKILL.md

Studio chart performance

Use when a chart feels sluggish in Studio but similar charts (e.g. pie-chart) are fine.

One-line rule

Keep enter animation on paths if you need it, then drop Motion path subscriptions and isolate hover so Studio slider and legend updates don't replay expensive arc/path math across every series every frame.


1. Find what re-renders on every interaction

Studio updates displayState on every slider tick and on legend/slice hover. Trace:

  • Does hover live in the same context as data, scales, and animation config?
  • Does the preview recreate children (data.map, pattern defs, motion props) every render?
  • Does the chart remount unnecessarily (key tied to motion signature vs manual replay)?

Pattern: Split context like cartesian / pie charts — stable slice (data, geometry, animation config) vs hover slice (hoveredIndex, tooltip). Consumers that don't need hover use only the stable hook (usePieStable, useRingStable, useChartStable, …).

Studio pan: Wrap chart render in StudioChartRender (packages/studio/src/components/studio-chart-render.tsx) so camera pan / FPS counter parent updates skip the chart tree when render props are unchanged.


2. Treat SVG path d animation as expensive

Animating d with Motion / useTransform + d3 arc (or similar) runs layout + paint every frame, per series.

PreferAvoid
transform / opacity for hover (compositor-friendly)Continuous d morphing after enter is done
Static d once enter finishesKeeping Motion subscriptions on d for the chart's lifetime
Enter animation only, then static pathsRe-running enter path math on unrelated prop changes

Pattern: useMountProgress for enter → when progress ≥ 1 (useEnterComplete), render static paths and only animate hover with x/y/opacity/scale on a motion.g wrapper (not per-path scale on motion.path).

Shared hook: packages/ui/src/charts/use-enter-complete.ts


3. Memoize chart shell context

Unmemoized provider values force all children to reconcile on every parent render.

  • Memoize the stable context object with explicit deps (data, arcs/radii, dimensions, callbacks).
  • Memoize hover context on hoveredIndex + stable setHoveredIndex (useCallback in chart shell).
  • Match isLoaded to ring/cartesian: useEffect + timeout, not a lazy useState initializer.

Reference: pie-context.tsx, ring-context.tsx, chart-context.tsx, PieChartCore / RingChartCore useMemo on provider value.


4. Studio preview–specific wins

Chart-agnostic; apply in packages/studio/src/components/charts/*-studio*.tsx:

WinHow
Conditional defsOnly pass patternDefs / gradients when a series uses patterns
Memo derived dataColored/mapped data arrays; slice/series lists (useMemo, deps: dataSeed + design fields that affect color)
Memo motion enterDon't call getStudioMotionEnterProps inline; useMemo with motion-only deps (not full state)
Memo legend hover{ hoveredIndex, setHoveredIndex } in useMemo — already in studio-legend-hover.tsx
Memo chart bodymemo() wrapper; pass primitives (chartKey, chartSize, data) not whole ctx so pan/shell re-renders skip rebuild
Disable glow in StudioshowGlow={false} on series components

Reference: pie-studio-preview.tsx, ring-studio-preview.tsx


5. Compare against a “fast” sibling in Studio

Diff the slow chart against one that feels smooth in the same editor (usually pie-chart):

CheckSlow chart often hasFast chart often has
ShellInline render, extra defsStudioChartShell + conditional patterns
Series countMany animated pathsFewer paths or simpler geometry
HoverContext + full tree re-renderStable subscribers; hover on motion.g / translate
EnterPath d wipe per seriesStatic d after enter; transform-only hover
PanChart tree rebuilds every frameStudioChartRender memo boundary

6. Validation bar

Before opening a PR:

pnpm lint
pnpm --filter @bklitui/ui check-types
pnpm --filter @bklitui/studio check-types
# scoped production build when touching studio/web

Manual /studio?chart=<slug>:

  • Enter animation
  • Hover / legend sync
  • Drag geometry sliders (no unnecessary remount)
  • Canvas pan (space + drag) after enter — FPS near pie-chart baseline
  • Pattern/gradient mode if supported

Chart status (bklit-ui)

ChartSlugStatus
Piepie-chart✅ Reference (#120)
Ringring-chart✅ Aligned to checklist (context split, static paths, StudioChartRender, preview memo)
Radar / Funnel / ChoroplethvariousPartial — run checklist
Cartesian / scatter / live-linevarious✅ #91 decimation + hover batching
Sankeysankey-chartuseTransform on link stroke — candidate for useEnterComplete
Gaugegauge-chartLow priority (single arc)

Key files

AreaPath
Enter-complete hookpackages/ui/src/charts/use-enter-complete.ts
Pie referencepackages/ui/src/charts/pie-slice.tsx, pie-context.tsx, pie-studio-preview.tsx
Ringpackages/ui/src/charts/ring.tsx, ring-chart.tsx, ring-studio-preview.tsx
Pan isolationpackages/studio/src/components/studio-chart-render.tsx
Registrypackages/studio/src/lib/registry.tsx
Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.24

Published

Sep 24, 2026

Category

Uncategorized

License

MIT

Source path

.agents/skills/bklit-studio-chart-performance

Default branch

main

Latest commit

0dfdfc5

Tree SHA

4fdc3ed