bklit-studio-chart-performance
>
Works with
Claude CodeCursorCodex CLIGitHub CopilotGemini CLI
---
name: bklit-studio-chart-performance
description: >
license: MIT
---
# 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.
| Prefer | Avoid |
|--------|--------|
| `transform` / `opacity` for hover (compositor-friendly) | Continuous `d` morphing after enter is done |
| Static `d` once enter finishes | Keeping Motion subscriptions on `d` for the chart's lifetime |
| Enter animation only, then static paths | Re-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`:
| Win | How |
|-----|-----|
| Conditional defs | Only pass `patternDefs` / gradients when a series uses patterns |
| Memo derived data | Colored/mapped data arrays; slice/series lists (`useMemo`, deps: `dataSeed` + design fields that affect color) |
| Memo motion enter | Don'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 body | `memo()` wrapper; pass **primitives** (`chartKey`, `chartSize`, `data`) not whole `ctx` so pan/shell re-renders skip rebuild |
| Disable glow in Studio | `showGlow={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**):
| Check | Slow chart often has | Fast chart often has |
|-------|----------------------|----------------------|
| Shell | Inline render, extra defs | `StudioChartShell` + conditional patterns |
| Series count | Many animated paths | Fewer paths or simpler geometry |
| Hover | Context + full tree re-render | Stable subscribers; hover on `motion.g` / translate |
| Enter | Path `d` wipe per series | Static `d` after enter; transform-only hover |
| Pan | Chart tree rebuilds every frame | `StudioChartRender` memo boundary |
---
## 6. Validation bar
Before opening a PR:
```bash
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)
| Chart | Slug | Status |
|-------|------|--------|
| Pie | `pie-chart` | ✅ Reference (#120) |
| Ring | `ring-chart` | ✅ Aligned to checklist (context split, static paths, `StudioChartRender`, preview memo) |
| Radar / Funnel / Choropleth | various | Partial — run checklist |
| Cartesian / scatter / live-line | various | ✅ #91 decimation + hover batching |
| Sankey | `sankey-chart` | `useTransform` on link stroke — candidate for `useEnterComplete` |
| Gauge | `gauge-chart` | Low priority (single arc) |
---
## Key files
| Area | Path |
|------|------|
| Enter-complete hook | `packages/ui/src/charts/use-enter-complete.ts` |
| Pie reference | `packages/ui/src/charts/pie-slice.tsx`, `pie-context.tsx`, `pie-studio-preview.tsx` |
| Ring | `packages/ui/src/charts/ring.tsx`, `ring-chart.tsx`, `ring-studio-preview.tsx` |
| Pan isolation | `packages/studio/src/components/studio-chart-render.tsx` |
| Registry | `packages/studio/src/lib/registry.tsx` |More General & Other skills
find-skills
vercel-labs/skills
Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.
1.5M
grill-me
mattpocock/skills
A relentless interview to sharpen a plan or design.
972.7k
grill-with-docs
mattpocock/skills
A relentless interview to sharpen a plan or design, which also creates docs (ADR's and glossary) as we go.
828.8k

