The registry now covers every shadcn/ui component except chart, form (see the sibling issue), and two composition-only items. chart is the largest remaining gap and the only one that needs a dependency decision, so it is filed rather than built.
What upstream is
shadcn's chart.tsx is a thin wrapper over Recharts: a ChartContainer that injects CSS variables from a ChartConfig (--color-<key> per series), plus ChartTooltip, ChartTooltipContent, ChartLegend and ChartLegendContent. There is no chart drawing code of its own — the value is entirely the theming bridge and the tooltip/legend recipes.
Why it is not a straight port
The registry's standing rule is that recipes are shadcn's, ported verbatim, and every item is source you own with no runtime dependency beyond @llui/dom + @llui/components. chart breaks that in a way none of the other 82 items do:
- It needs a charting library. Recharts is React-only, so a port has to pick a different one (or draw SVG directly), and at that point the class recipes are the only thing left of upstream — the component's actual behaviour would be an LLui invention wearing a shadcn name.
- There is no LLui machine to skin. Every other skin sits on a
@llui/components machine that owns state, keyboard and ARIA. A chart has real interaction (hover, focus, keyboard traversal of series, an accessible table fallback) and none of it exists yet.
So this is two decisions, not one:
- Draw with what? Options, roughly in increasing cost: hand-rolled SVG for a small set of chart types (line, area, bar, pie) — no dependency, full control, most work; a framework-agnostic library that returns DOM/SVG; or a
foreign() seam around an existing library, as @llui/lexical does for Lexical.
- Is there a
chart MACHINE? If charts get keyboard traversal and an accessible fallback — and they should — that belongs in @llui/components, not in a copied recipe.
Suggested scope for a first pass
Deliberately narrow, to get the theming bridge landed without committing to a charting engine:
ChartContainer + the ChartConfig → --color-<key> bridge, which is the genuinely portable part and is what makes a chart match the app's theme in both light and dark.
ChartTooltipContent / ChartLegendContent recipes, ported verbatim — they are ordinary surfaces and need no library.
- A demo section drawing one chart type with plain SVG, to prove the bridge.
That gives consumers the theming and the surfaces, and leaves the engine choice open.
Definition of done
Notes
scripts/test/registry-attrs.test.ts has a MACHINE_OF map with a vacuity check — a new skin with no machine must be listed there with [], or the test fails rather than silently skipping it.
The registry now covers every shadcn/ui component except
chart,form(see the sibling issue), and two composition-only items.chartis the largest remaining gap and the only one that needs a dependency decision, so it is filed rather than built.What upstream is
shadcn's
chart.tsxis a thin wrapper over Recharts: aChartContainerthat injects CSS variables from aChartConfig(--color-<key>per series), plusChartTooltip,ChartTooltipContent,ChartLegendandChartLegendContent. There is no chart drawing code of its own — the value is entirely the theming bridge and the tooltip/legend recipes.Why it is not a straight port
The registry's standing rule is that recipes are shadcn's, ported verbatim, and every item is source you own with no runtime dependency beyond
@llui/dom+@llui/components.chartbreaks that in a way none of the other 82 items do:@llui/componentsmachine that owns state, keyboard and ARIA. A chart has real interaction (hover, focus, keyboard traversal of series, an accessible table fallback) and none of it exists yet.So this is two decisions, not one:
foreign()seam around an existing library, as@llui/lexicaldoes for Lexical.chartMACHINE? If charts get keyboard traversal and an accessible fallback — and they should — that belongs in@llui/components, not in a copied recipe.Suggested scope for a first pass
Deliberately narrow, to get the theming bridge landed without committing to a charting engine:
ChartContainer+ theChartConfig→--color-<key>bridge, which is the genuinely portable part and is what makes a chart match the app's theme in both light and dark.ChartTooltipContent/ChartLegendContentrecipes, ported verbatim — they are ordinary surfaces and need no library.That gives consumers the theming and the surfaces, and leaves the engine choice open.
Definition of done
docs/adr/)registry/llui/ui/chart.tswith the container + tooltip/legend recipesregistry.json, copied intoexamples/registry-demo, and RENDERED there — the sync test requires the copy, and rendering is what has caught every skin bug so farscripts/test/registry-attrs.test.ts(a recipe may not name an attribute its machine never publishes) and the Tailwind dead-class guard<svg>is unreadable to a screen readerNotes
scripts/test/registry-attrs.test.tshas aMACHINE_OFmap with a vacuity check — a new skin with no machine must be listed there with[], or the test fails rather than silently skipping it.