Skip to main content

bklit-studio-chart-performance

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.

Datos de origen

Repositorio
bklit/bklit-ui
Última actividad en el origen
2 de junio de 2026 a las 09:20
Idioma detectado de SKILL.md
inglés
Estrellas
1748
Forks
115

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
bklit-studio-chart-performance
description
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.
# 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` |
Ver en GitHub