mcpField
B
bklit-ui-migrate

bklit-ui-migrate

github.com/bklitDevelopment1.8k83 installsUpdated today
Repository

About bklit-ui-migrate

A skill for guiding migrations from Recharts and TanStack Charts to Bklit UI chart components. It inventories and classifies charts before conversion, maps props and data, and preserves charts that are poor migration candidates.

Key features

  1. 01Chart inventory and classification
  2. 02Component and prop mapping references
  3. 03Bklit registry installation guidance
  4. 04One-file-at-a-time conversion workflow
  5. 05Rules for preserving unsupported charts

Use cases

  1. 01Assessing chart migration scope in a project
  2. 02Converting compatible Recharts components
  3. 03Moving tiny charts to Bklit sparklines

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/bklit/bklit-ui --skill bklit-ui-migrate

After installing, type/bklit-ui-migratein Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

evals/
evals.json
evals/files/bar-layout-vertical/
package.json
evals/files/bar-layout-vertical/components/
browser-share.tsx
evals/files/donut-pie-center/
package.json
evals/files/donut-pie-center/components/
plan-mix.tsx
evals/files/line-multi-series/
package.json
evals/files/line-multi-series/components/
traffic-chart.tsx
evals/files/radar-normalize/
package.json
evals/files/radar-normalize/components/
skills-radar.tsx
evals/files/recharts-tiny/
package.json
evals/files/recharts-tiny/components/
kpi-sparklines.tsx
evals/files/scatter-numeric-x/
package.json
evals/files/scatter-numeric-x/components/
height-weight.tsx
evals/files/shadcn-area-interactive/
package.json
evals/files/shadcn-area-interactive/components/
chart-area-interactive.tsx
evals/files/shadcn-area-interactive/components/ui/
chart.tsx
evals/files/shadcn-stacked-bar/
package.json
evals/files/shadcn-stacked-bar/components/
chart-bar-stacked.tsx
evals/files/shadcn-stacked-bar/components/ui/
chart.tsx
evals/files/tanstack-sparkline/
package.json
evals/files/tanstack-sparkline/components/
revenue-kpi.tsx
evals/files/treemap-keep/
package.json
evals/files/treemap-keep/components/
monthly-bars.tsx
storage-treemap.tsx
references/
component-map.md
examples.md
prop-map.md
shadcn-chart.md
tanstack-charts.md
rules/
gaps.md

Details

From the project README

Recharts / TanStack Charts → Bklit UI migration

Bklit charts are shadcn registry components: npx shadcn@latest add @bklit/<slug> copies source into the user's project and the code imports it from their own alias, e.g. @/components/charts/line-chart. Never import from @bklitui/ui/charts — that is bklit's private monorepo package.

Work through the steps in order. Do not start rewriting before the inventory (step 1) and classification (step 2) have been shown to the user.

References

FileUse it for
references/component-map.mdRecharts component → bklit export, registry slug, import path
references/prop-map.mdProp-by-prop mapping, units, defaults
references/shadcn-chart.mdChartContainer / ChartConfig / ChartTooltipContent / ChartLegendContent, var(--color-*), full before/after
references/examples.mdBefore/after: multi-line, stacked bar, horizontal bar, donut, radar, gradient area, tiny line/area/bar → sparklines, TanStack KPI sparkline
references/tanstack-charts.mdTanStack Charts (@tanstack/charts): marks → sparklines (well covered) and full charts (high-level only)
rules/gaps.mdFeatures with no bklit prop — workaround or keep Recharts (Incorrect/Correct)
scripts/detect-recharts.mjsZero-dependency inventory + classification (Recharts, shadcn wrapper, TanStack Charts, tiny charts → sparkline)

Docs for each chart: https://bklit.com/docs/components/<slug>.

Ground rules

  1. Never invent props. If a Recharts prop has no row in prop-map.md, it is a gap — read rules/gaps.md. bklit has no tickFormatter on XAxis, no domain on YAxis, no stackId, no layout, no connectNulls, no syncId.
  2. Line / Area / Composed / Scatter are time-series charts. x values must be Dates (or ISO strings / epoch ms). Categorical x → BarChart or a workaround. Tiny charts are sparklines. One series, no axes / grid / legend, rendered small → LineSparkline / AreaSparkline / BarSparkline from @bklit/sparkline (x is row order, so no dates needed). Do not rebuild them with LineChart + hidden chrome.
  3. Preserve data, colours and labels. Same series, same colours (resolved from ChartConfig), same human labels in tooltip and legend.
  4. One file at a time, typecheck after each.
  5. Ask before any "needs workaround" conversion — it changes how the chart looks or reads.
  6. Leave "keep Recharts" charts untouched. A partial migration is a valid outcome.

Step 1 — Detect and inventory

Run the detector from the project root (Node ≥ 18, no install):

node <skill-dir>/scripts/detect-recharts.mjs . --format=table   # human table
node <skill-dir>/scripts/detect-recharts.mjs .                  # full JSON

It walks source files (skipping node_modules, .next, dist, build, dot-dirs), finds recharts imports (named or import * as RechartsPrimitive), shadcn wrapper imports and @tanstack/charts imports (each defineChart(...) is one chart with "library": "@tanstack/charts"), and reports per file: components used, each chart root with line number, notable props (stackId, layout="vertical", syncId, XAxis type="number", Treemap, LabelList, ErrorBar, custom shape/content, Brush, …), the proposed bklit target, slugs to install, and a classification. Charts it reads as sparklines carry "sparkline": true and target @bklit/sparkline; axis-less charts of unknown size get a note suggesting it. shadcnWrappers[].importedBy lists who still imports components/ui/chart.tsx. It never throws; unreadable paths go in errors.

The script is a heuristic (it cannot see data values or axes built in helper functions). Open every listed file and confirm before presenting. Show the user a table:

FileRecharts / shadcn componentsChart typebklit targetClass
components/chart-area-interactive.tsx:51AreaChart, Area, CartesianGrid, XAxis, ChartContainer, ChartTooltip(Content), ChartLegend(Content)Area (stacked)AreaChartneeds workaround
components/storage-treemap.tsx:25Treemap, Tooltip, ResponsiveContainerTreemap—keep Recharts

Also check components.json: confirm the @bklit registry ("registries": { "@bklit": "https://ui.bklit.com/r/{name}.json" }) and note aliases.components — it decides the import prefix (default @/components → files land in components/charts/).

Step 2 — Classify and confirm

For every chart, state one of:

  • Clean — every component and prop maps (see component-map.md, prop-map.md). Data may still need a reshape (pie, radar, radial, ring).
  • Needs workaround — convertible with a compromise. Typical: categorical or numeric x on a time-series chart, Area stackId, multiple bar stack groups, fixed YAxis domain, negative bar values, x tickFormatter/angled ticks, LabelList, syncId, Brush (bklit's brush is not shipped in any registry item), ReferenceLine/ReferenceDot, null gaps, nested pies.
  • Keep on Recharts — Treemap, ErrorBar, Customized, custom shape/node renderers, ZAxis bubbles, layout="vertical" on non-bar charts.
  • Keep on TanStack Charts (keep-tanstack) — definitions using marks bklit has no mapping for (dot, cell, rect, text, ruleY, hexagon, facet, …). Full lineY / areaY / barY charts are needs-workaround (high-level mapping only); sparkline definitions are clean. See tanstack-charts.md.
  • Sparklines — a Tooltip (or TanStack tooltip) on a tiny chart is needs-workaround: sparklines have none, so the value moves next to the chart via useSparklineHover.

Give the reason for each non-clean chart (quote the prop) and the proposed workaround from rules/gaps.md. Ask the user which workaround charts to convert and how (e.g. overlap vs cumulative areas). Convert clean charts without further questions unless the user asked to review each.

Step 3 — Install the bklit items

Install only what the confirmed charts need, using the project's package runner:

npx shadcn@latest add @bklit/line-chart @bklit/bar-chart @bklit/y-axis @bklit/legend
# pnpm dlx shadcn@latest add …   |   bunx --bun shadcn@latest add …
Needed forSlug
tiny LineChart / AreaChart / BarChart, TanStack lineY / areaY / barY sparklinessparkline (LineSparkline, AreaSparkline, BarSparkline, useSparklineHover; no grid/axes/tooltip pulled in)
LineChart / AreaChart / BarChart / ComposedChart / ScatterChartline-chart / area-chart / bar-chart / composed-chart / scatter-chart (each brings grid, chart-tooltip; time charts bring x-axis; bar brings BarXAxis/BarYAxis)
PieChart / RadarChart / ring (RadialBarChart) / one-value gaugepie-chart / radar-chart / ring-chart / gauge-chart
FunnelChart / Sankey / SunburstChartfunnel-chart / sankey-chart / sunburst-chart
any visible value YAxisy-axis (not bundled with line/area/bar)
Legendlegend
ReferenceAreareference-area
ReferenceDot / event markersmarkers

shadcn adds bklit's CSS variables (--chart-line-primary, --chart-grid, --chart-crosshair, tooltip colours, …) to the global stylesheet but does not overwrite existing variables, so the user's --chart-1 … --chart-5 stay as they are. Confirm the files landed where aliases.components says before writing imports.

Step 4 — Convert one file at a time

For each chart:

  1. Reshape data.
    • Time charts: make row[xDataKey] a Date. Bare "2024-04-01" strings parse as UTC midnight (shows the previous day west of UTC) → new Date(\${d}T00:00:00`). Sort by x. Set xDataKeywhen the key is not"date"(bar default"name"`).
    • Series-level data (<Scatter data>, <Line data>) → merge into the root data.
    • Pie: { label, value, color? }[]. Radar: metrics {key,label}[] + data {label, color?, values}[] normalised 0–100. Ring: { label, value, maxValue, color? }[]. Funnel: { label, value, color? }[]. Sankey: unchanged.
  2. Map components and props with component-map.md and prop-map.md. Highlights that are easy to get wrong:
    • ResponsiveContainer → delete; size with aspectRatio (default "2 / 1") or className="h-[300px]".
    • layout="vertical" → BarChart orientation="horizontal" (inverted naming) + BarYAxis.
    • All bars share one stackId → root stacked.
    • type="monotone" → curve={curveMonotoneX} from @visx/curve. Recharts' default curve is linear; bklit Line defaults to curveNatural, Area to curveMonotoneX.
    • dot → showMarkers/markers; activeDot → ChartTooltip showDots/dotSize.
    • isAnimationActive={false} → animate={false} on the series (root animationDuration, default 1100 ms).
    • Bar radius → lineCap (default "round"; "butt" for square Recharts bars; a number for px).
    • paddingAngle (deg) → padAngle (rad); pie angles: rad = (90 − deg) · π / 180.
    • YAxis tickFormatter → formatValue; domain → none.
    • Tooltip → ChartTooltip with rows={(point) => [...]} for labels/formatting (row order = series child order), content={({ point, index }) => …} for full control, cursor={false} → showCrosshair={false}.
    • Legend → <Legend items> from @/components/charts/legend, rendered outside the chart root.
    • margin: same shape, but bklit defaults to 40 on every side because axis labels live in the margin.
    • Sparklines (prop-map.md → "Tiny charts"): stroke/fill → color, type="monotone" → curve="monotone" (a string), margin → padding, radius → barRadius, isAnimationActive={false} → animate={false}, ResponsiveContainer → omit width, Tooltip → useSparklineHover + your own value. Import from @/components/charts/sparkline.
    • TanStack Charts: replace defineChart(...) and the <Chart definition> element; mark channels become props (y → dataKey, stroke → color, curve → curve, y-scale domain → yDomain, margin → padding, ariaLabel → aria-label, svgAnimation / motion() → animate). Details: tanstack-charts.md.
  3. Preserve colours and labels from ChartConfig (shadcn). Every var(--color-<key>) must become the config's colour (e.g. var(--chart-1)) — those variables only exist inside ChartContainer. Labels go to rows and Legend items. Details: shadcn-chart.md.
  4. Keep the component's public API (name, props, exports) so call sites do not change.
  5. Add "use client" if the file passes functions (rows, content, formatValue) and is not already a client component.

Step 5 — Rewrite imports (watch for collisions)

Import each piece from the file the registry installed:

import { Line, LineChart } from "@/components/charts/line-chart";
import { Grid } from "@/components/charts/grid";
import { XAxis } from "@/components/charts/x-axis";
import { YAxis } from "@/components/charts/y-axis";
import { ChartTooltip } from "@/components/charts/tooltip";
import { Legend, LegendItem, LegendLabel, LegendMarker } from "@/components/charts/legend";
import { AreaSparkline, BarSparkline, LineSparkline, useSparklineHover } from "@/components/charts/sparkline";

Remove the file's recharts and @/components/ui/chart imports once nothing in it uses them. Names collide across libraries — ChartTooltip, ChartLegend (shadcn wrapper) and LineChart, Line, Area, Bar, XAxis, YAxis, Legend, ReferenceArea, PieChart, … (Recharts). In a file that still renders a kept Recharts chart, alias one side:

import { Treemap, Tooltip as RechartsTooltip } from "recharts";
import { ChartTooltip as BklitChartTooltip } from "@/components/charts/tooltip";

The registry's legend item export is LegendItem (the docs' LegendItemComponent alias exists only in bklit's monorepo barrel).

Step 6 — Remove the old code only when unused

  • Delete components/ui/chart.tsx only when no file imports it: re-run the detector (shadcnWrappers[].importedBy empty) and search the repo (rg "ui/chart"), including stories, tests and docs.
  • Remove the recharts dependency only when the detector reports no recharts imports left (no kept charts) and rg "from ['\"]recharts" is empty. Use the project's package manager (npm uninstall recharts, pnpm remove recharts, …).
  • Remove @tanstack/charts only when the detector reports no @tanstack/charts imports left and rg "@tanstack/charts" is empty.
  • If any chart is kept on Recharts or TanStack Charts, keep that dependency and say so in the summary.

Step 7 — Verify

  1. Typecheck and lint after each file, then build: npx tsc --noEmit (or the project's typecheck script), the project's lint script, then build.
  2. Visual comparison: run the dev server and compare each converted chart with the original (screenshots before/after, light and dark mode). Check: series count and colours, labels in tooltip and legend, x labels/dates (UTC shift), y range, stacking, sizing, hover, empty state.
  3. Expected, acceptable differences to call out: bklit's enter animation, dashed/edge-faded grid, crosshair + date pill tooltip, fixed "MMM d" x labels, rounded bars by default.
  4. Re-run the detector and report what is left on Recharts and why.

Finish

Summarise for the user: charts converted (file → bklit chart), workarounds applied, charts kept on Recharts with reasons, items installed, files/dependencies removed, and verification results.

For restyling the migrated charts (palette, tokens, typography, motion), hand off to the bklit-ui-design skill; for general bklit composition questions use the bklit-ui skill.

Comments

Markdown supported