# SoybeanUI Docs English LLM-friendly documentation bundle for the SoybeanUI docs site. ## Chart Demos - Page URL: /chart - Markdown URL: /chart.md - Description: shadcn-styled chart demos built with TanStack Charts and SoybeanUI theme tokens. # Charts These charts render directly with [TanStack Charts](https://tanstack.com/charts), following the same usage as the [shadcn chart collection](https://tanstack.com/charts/catalog/collections/shadcn). SoybeanUI **no longer ships a dedicated chart wrapper package** — TanStack Charts is already a framework-agnostic chart grammar, and using it directly lets you follow the official upgrade path without being locked into an extra abstraction. ## How theming works The demos bridge the theme with a lightweight `ChartContainer` + `chartConfig`: - `chartConfig` maps each series field to `{ label, color }`; - colors come from the theme tokens `hsl(var(--chart-1..5))`, and `ChartContainer` injects them as `--color-` CSS custom properties on the wrapper; - marks reference `var(--color-)`, so colors follow light/dark theme changes automatically. `ChartContainer` is only a config → CSS-variable styling bridge with **no chart logic**; treat it as a small component you can copy into your own project. TanStack Charts' built-in axes, grid, tooltip, and legend do the rest. ## Demos Pick a chart type in the sidebar (or the cards below) to see live demos and copyable source. ## Installation - Page URL: /chart/installation - Markdown URL: /chart/installation.md - Description: Install TanStack Charts and wire it into a SoybeanUI project. # Installation Charts are powered by [TanStack Charts](https://tanstack.com/charts). Install it directly (the Vue adapter ships in the same package): ```bash pnpm add @tanstack/charts ``` ## Import what you need - Cartesian charts (bar/line/area/scatter): `defineChart`, `barY`, `lineY`, `areaY`, `dot`, and more from `@tanstack/charts`; - scales: `@tanstack/charts/scales/band`, `@tanstack/charts/scales/linear`, `@tanstack/charts/scales/point`; - the Vue component: `Chart` from `@tanstack/charts/vue`; - tooltip: `tooltip` from `@tanstack/charts/tooltip`; - polar (donut): `pie`, `polar`, `radialArc` from `@tanstack/charts/polar`. The polar entry is an opt-in subpath — when not imported, the package keeps a Cartesian-sized footprint. ## Theme colors Make sure the SoybeanUI theme is available (`@soybeanjs/ui/styles.css` or the UnoCSS preset) so tokens like `--chart-1..5` exist and the demo colors follow light/dark mode. ## Quick Start - Page URL: /chart/quick-start - Markdown URL: /chart/quick-start.md - Description: Describe a chart with defineChart, render it with the Vue Chart component, and wire in SoybeanUI theme colors. # Quick Start TanStack Charts uses a declarative grammar: describe marks, scales, color, and tooltip with `defineChart`, then render it with the Vue `` component. ## 1. Define the series config ```ts const chartConfig = { desktop: { label: 'Desktop', color: 'hsl(var(--chart-1))' } } satisfies ChartConfig; ``` ## 2. Describe the chart ```ts import { barY, defineChart } from '@tanstack/charts'; import { scaleBand } from '@tanstack/charts/scales/band'; import { scaleLinear } from '@tanstack/charts/scales/linear'; import { tooltip } from '@tanstack/charts/tooltip'; const chart = defineChart({ marks: [ barY(chartData, { x: 'month', y: 'desktop', fill: 'var(--color-desktop)' }) ], scales: { x: { scale: () => scaleBand().padding(0.16) }, y: { scale: scaleLinear, nice: true, grid: true } }, tooltip }); ``` ## 3. Render ```vue ``` `ChartContainer` exposes `chartConfig.desktop.color` as `--color-desktop`, so `var(--color-desktop)` resolves in the marks and follows the theme. For multiple series, hand the color domain to `color.range` (see the grouped bar demo). ## SoybeanUI CLI - Page URL: /cli - Markdown URL: /cli.md - Description: sbean is the command-line tool for SoybeanUI. It helps you initialize projects, add components, and manage your UI configuration. # SoybeanUI CLI `sbean` is the command-line tool for SoybeanUI. It helps you initialize projects, add components, and manage your UI configuration. ## Installation ```bash pnpm add -D sbean ``` Or run directly: ```bash npx sbean init ``` ## Commands ### `sbean init` Initialize a new SoybeanUI project or add configuration to an existing one. ```bash sbean init [options] ``` | Option | Description | Default | | ----------------------- | --------------------------------------------------------------------------- | -------------------------------------------- | | `-m, --monorepo` | Use monorepo (pnpm workspaces) structure | `false` | | `--ui-dir ` | Component output directory | `src/ui` (single) / `packages/ui` (monorepo) | | `--size ` | Component size: xs / sm / md / lg / xl / 2xl | `md` | | `--style ``` ### Option 2: Using Compact Components (Data-driven) For stable structures with data-driven scenarios, offering more concise code: ```vue ``` > Compact components are managed by the headless layer for data iteration and default content rendering, letting you accomplish common tasks with less code. ## Theme configuration SoybeanUI supports flexible theming. You can configure the global theme using the `ConfigProvider` component: ```vue ``` ## RTL configuration SoybeanUI components support direction switching through `SConfigProvider`. Set `dir="rtl"` at the app root when your product needs right-to-left layouts: ```vue ``` For component-level details and configuration boundaries, see the [ConfigProvider documentation](/components/config-provider). ## First example Let’s create a simple example to verify your installation: ```vue ``` ## FAQ ### Styles are not applied? 1. Make sure you imported the stylesheet: `import '@soybeanjs/ui/styles.css'` 2. Check the browser console for errors ### TypeScript type errors? 1. Make sure you installed the latest version of `@soybeanjs/ui` 2. Check the type-related configuration in `tsconfig.json` 3. Restart the TypeScript server ### Components are not auto-imported? 1. Make sure `unplugin-vue-components` is configured correctly 2. Verify your `vite.config.ts` configuration 3. Restart the dev server ### Issues when using with Nuxt? 1. Make sure you are using Nuxt 4 2. Verify the module configuration in `nuxt.config.ts` 3. Clear the `.nuxt` cache directory and restart ## Next steps Now that you’ve installed SoybeanUI, you can: 1. Browse the [Component docs](/components) to see all available components 2. Read the [Theme configuration](../theming) docs to customize theming 3. Visit [GitHub](https://github.com/soybeanjs/soybean-ui) for source code and examples Enjoy! If you run into any issues, feel free to open an issue on GitHub. ## Skills - Page URL: /overview/skills - Markdown URL: /overview/skills.md - Description: Install SoybeanUI skills to give AI coding agents deep knowledge of components, theming, headless composition patterns, and generated references. # Skills > Install SoybeanUI skills to give AI coding agents deep knowledge of components, theming, headless composition patterns, and generated references. ## What are Skills? Skills are structured knowledge files for AI coding agents. They package library-specific guidance, workflows, and references so an agent can load the right context when a task matches. Unlike MCP servers, skills do not provide live tools. They provide curated instructions and references directly in the model context. SoybeanUI currently ships two public skills: - **soybean-ui** - styled package usage, theming, docs navigation, and generated component references - **soybean-headless** - headless primitives, Compact patterns, composition guidance, and shared component references ## What the SoybeanUI skills cover The bundled skills help agents answer tasks such as: - when to choose `@soybeanjs/ui` versus `@soybeanjs/headless` - how to set up theming, locale, and direction - how to use component APIs and generated references efficiently - how to compose headless primitives into custom-styled wrappers - how to navigate the docs and generated references without loading the whole site ## Usage ### Skills CLI The easiest installation path is the `skills` CLI: ```bash npx skills add soybeanjs/soybean-ui/skills ``` You can target a specific agent: ```bash npx skills add soybeanjs/soybean-ui/skills --agent cursor npx skills add soybeanjs/soybean-ui/skills --agent claude-code ``` Or install globally so the skills are available across projects: ```bash npx skills add soybeanjs/soybean-ui/skills --global ``` Installing the package adds both `soybean-ui` and `soybean-headless`. ### Skills URL If your tool supports direct skill URLs, you can point it at the public GitHub skill directory. For the styled UI skill: ```text https://github.com/soybeanjs/soybean-ui/tree/main/skills/skills/soybean-ui ``` For the headless skill: ```text https://github.com/soybeanjs/soybean-ui/tree/main/skills/skills/soybean-headless ``` ### Claude Code Claude Code can install an individual skill directly from the GitHub directory: ```bash claude skill add https://github.com/soybeanjs/soybean-ui/tree/main/skills/skills/soybean-ui claude skill add https://github.com/soybeanjs/soybean-ui/tree/main/skills/skills/soybean-headless ``` The repository also ships Claude marketplace metadata inside the published skills package. ### Other AI tools Any tool that supports GitHub-hosted skill folders or custom instruction directories can use the same sources. - **SoybeanUI skill entry**: https://github.com/soybeanjs/soybean-ui/tree/main/skills/skills/soybean-ui/SKILL.md - **SoybeanUI skill directory**: https://github.com/soybeanjs/soybean-ui/tree/main/skills/skills/soybean-ui - **SoybeanHeadless skill entry**: https://github.com/soybeanjs/soybean-ui/tree/main/skills/skills/soybean-headless/SKILL.md - **SoybeanHeadless skill directory**: https://github.com/soybeanjs/soybean-ui/tree/main/skills/skills/soybean-headless ## Practical recommendations 1. Install the full `@soybeanjs/ui-skills` package when you work with both styled and headless packages. 2. Use `soybean-ui` when you need component usage, theming, and docs navigation help. 3. Use `soybean-headless` when you need composition guidance or custom-styled wrapper patterns. 4. Keep `llms.txt` as a complementary source when you need docs-wide context instead of packaged skill context. ## Related pages - [Introduction](/overview/introduction) - [Quick Start](/overview/quick-start) - [Theming](/overview/theming) - [LLMs.txt](/overview/llms) - [Components](/components) ## Theming - Page URL: /overview/theming - Markdown URL: /overview/theming.md - Description: SoybeanUI ships a three-layer theme engine: a static palette layer, a semantic token layer and a literal layer. Configure it through SConfigProvider, or drive the engine directly when you need the CSS yourself. # Theming ## Overview Soybean UI provides a flexible theming system that allows you to customize the appearance of components to match your application's design requirements. You can easily adjust colors, radius and global size settings. Open the [theme editor](/theme-editor) to change every option against a live gallery of components — the panel there is the same `SThemeCustomizer` an application embeds for its users. `SThemeCustomizer` takes a `ui` slot map (plus `class`) so a host can restyle the shell: `:ui="{ root: 'w-full h-[70vh]' }"` fills a sidebar instead of using the default fixed box. ## How the theme is built The theme is **one static palette table plus one dynamic alias table**: 1. **Palette layer** (26 built-in palettes × 11 levels) is emitted as naked channels — `--zinc-100: 240 4.8% 95.9%` — once, and never changes with the theme; 2. **Semantic layer** holds every design token as a _reference_ into that table — `--background: var(--zinc-50)` — and is regenerated on every theme change. A theme switch is a reference swap, not a colour computation; 3. **Literal layer** carries the values that are not colours: dimension (`--size`), the radius ladder (`--radius` … `--radius-4xl`), the spacing grid unit (`--spacing-unit`), layering (`--z-layout` … `--z-max`), line widths and font families. Token names follow shadcn and are **unprefixed**: `--background`, `--card` / `--popover` (+ `-foreground`), `--primary`, `--secondary`, `--muted`, `--accent`, `--destructive` / `--success` / `--warning` / `--info` (+ `-foreground`), `--border`, `--input`, `--ring`, `--carbon`, `--chart-1` … `--chart-5`, the eight `--sidebar-*` tokens, plus our own `--mask` (the modal scrim, concentration in `--mask-alpha`). Pressed states are no longer separate tokens — compose them with an alpha modifier on the fill (`active:bg-primary/90`). The palette layer is **static**, which is what keeps a theme switch cheap: the semantic layer only ever swaps references, so switching never recomputes a colour. The engine does **not** measure anything else — every token's level is declared in the token contract, and readability is the theme author's responsibility. `text-2xs`-style utilities, the spacing grid and the radius ladder are all declared values; check your pairs in the [theme editor](/theme-editor) (or with `axe`) rather than relying on the engine to correct them. A token is consumed as a **channel wrapped in a function**: `hsl(var(--primary) / 0.5)`. Writing the bare `var(--primary)` as a colour silently fails (a channel triple is not a colour). Utility classes (`bg-card`, `text-muted-foreground`, `border-input`) already do the wrapping for you, and are the recommended way; when JavaScript needs the actual colour, use `resolveTokenColor` rather than string-building from the variables. ## Theme configuration Pass a theme object to `SConfigProvider` at the root of your application: ```vue ``` | Option | Type | Default | What it does | | :-------------- | :--------------------------------------------------------------------------------- | :---------- | :--------------------------------------------------------------------------------------------------------------- | | `base` | a neutral palette key (`slate` / `mist` / `gray` / `zinc` / `neutral` / `stone` …) | `'zinc'` | The palette every neutral token reads (surfaces, text, borders). | | `primary` | any palette key (26 built-ins, neutral or chromatic) | `'indigo'` | The brand palette: `primary`, `ring`, `chart-1…5` and the `primary` role ramp follow it. | | `feedback` | `classic` / `vivid` / `subtle` / `modern` / `professional` | `'classic'` | Which palettes back the four status roles (`destructive` / `success` / `warning` / `info`). | | `surfaceStyle` | `'layered'` / `'flat'` | `'layered'` | `layered` tints the page so raised surfaces read above it; `flat` keeps every surface at the mode extreme. | | `size` | `xs` / `sm` / `md` / `lg` / `xl` / `2xl`, or a length (`'15px'` / `'0.95rem'`) | `'md'` | The root font size — the density knob: every rem-based token scales with it. | | `radius` | `2xs` … `2xl`, or a length | `'md'` | The radius **seed**: the seven rungs are `calc(var(--radius) * k)`, so changing the seed moves the whole ladder. | | `spacing` | `compact` / `default` / `relaxed` / `spacious`, or a multiplier (0 < k ≤ 4) | `'default'` | The spacing grid unit (`--spacing-unit`): padding, margin and gap utilities are coefficients on it. | | `borderOpacity` | number (0 – 1) | `1` | Scales the decorative hairline alpha (`--border-alpha` / `--input-alpha`). Not applied to `--mask-alpha`. | | `overrides` | `{ light?: { [token]: TokenOverride }, dark?: … }` | — | Per-mode token overrides — the sharpest tool; see below. May include `token.*` refs. | | `preset` | an inline `{ light, dark }` colour set, or `{ name }` referencing a stored preset | — | A reusable colour set; resolved into `overrides` before the engine runs. | | `prefix` | `false` / a string | `false` | Namespaces every variable (`--acme-background`). Set it only when the page hosts another design system. | | `format` | `'hsl'` / `'oklch'` | `'hsl'` | The palette layer's channel format (the semantic layer only holds references, so it does not care). | | `darkSelector` | `'class'` / `'media'` / a selector | `'class'` | How dark mode is expressed in the emitted CSS (`.dark` by default). | | `styleTarget` | `'html'` / `':root'` | `':root'` | Where the light block is attached. | `SConfigProvider` also takes `persistTheme` (read/write the theme envelope in `localStorage`), `themeConfig` (the envelope injected during SSR), `presetProvider` (resolve a stored preset name on the server), `nonce` and `isServer`. ## Custom color tokens (`overrides`) `overrides` replaces individual tokens per mode. It has the highest priority — it is applied on top of the derived base / primary / feedback / sidebar tokens (chart colours are derived from `primary` and can be overridden per token too): ```vue ``` Keys are the **token names** (`background`, `card-foreground`, `sidebar-ring`, …) — the same names the utility classes use, in kebab case. An override value takes one of five forms (the `TokenOverride` type): a palette level reference (`stone.950`), a simple key (`white` / `black`), an `hsl(...)` / `oklch(...)` colour in CSS Color 4 syntax (with an optional `/ `), or a **token reference** `token.${name}` (e.g. `ring: 'token.primary'` — the map copies the target token's value at resolve time; colour values land before references). Colour components always carry a `%` — `hsl(238.732 83.529% 66.667%)`, `oklch(60% 0.2 250)` — never the unitless spelling (it must stay the same shape as the palette layer's channels). Raw channel triples (`0 0% 100%`) and hex / `rgb()` are outside the type — the former are format-ambiguous, and for the latter convert first with `colord(...).toHslString()` / `toOklchString()`. **A complete colour is encoded into the theme format's channels** (a token is consumed as `hsl(var(--soybean-x) / )`, so a complete colour would invalidate every declaration): `border: 'oklch(100% 0 0 / 0.1)'` puts the channels into `--border` and the `0.1` into `--border-alpha`. An alpha written into a token that has no companion variable is dropped (use the `/N` utility modifier for transparency). A value that is neither a valid reference nor parseable (`transparent` / `inherit` / an unknown palette / **a self-reference such as `primary: 'token.primary'`** / `token.ghost` / a cyclic `token.*` chain) is **ignored**, and the token keeps its nominal value; so is a key that is not a token — a stale or hand-written key can neither reach the stylesheet nor break it. **Notes and caveats:** - **Light and dark are independent.** An override applies to the mode you put it in: `dark` keeps its own declared levels rather than being derived from `light`. Write both sides when you want both. - **An override is applied verbatim.** It is not measured, corrected or reported — the engine has no opinion about readability (nothing walks a level on your behalf since decision #26). - **Overrides are per token, not per role.** To recolour the whole brand, change `primary` (the palette) rather than every token that reads it. - **The engine is a pure function.** Nothing here touches the DOM: the provider resolves the map, emits the alias block and patches its own `