bklit/bklit-ui

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.

First seen Jun 2, 2026

Installation

$ npx skills add bklit/bklit-ui --skill bklit-studio-chart-performance

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from bklit/bklit-ui · top by installs.

npx skills add bklit/bklit-ui

Browse all from bklit/bklit-ui

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 1.6K
License LICENSE
Default branch main
Open issues 3
Status Active

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 5,890 B
  • docs SUMMARY.md 2,679 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 447 installs

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.

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:

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