# Sakani UI > Sakani UI (`@sakaniui/react`) is an open-source, token-driven React design system with Figma parity and a Liquid Glass surface layer. Components are accessible, themed with CSS variables, and re-theme for dark mode and glass surfaces without per-component code. Install: `npm install @sakaniui/react`, then import `@sakaniui/react/tokens.css` and `@sakaniui/react/style.css` once. Read the agent guide first: it explains why components behave as they do and what to do when nothing fits. Machine-readable contract (every component, prop, required prop, enum value and token): https://www.sakaniui.com/manifest.json, also shipped as `@sakaniui/react/manifest.json`. MCP server: `npx -y -p @sakaniui/react sakaniui-mcp` (tools: search_components, get_component, list_components, get_tokens, check_usage, get_guide). See https://www.sakaniui.com/docs/ai. --- # Sakani UI — guide for AI agents You are building with `@sakaniui/react`. This file is the *why* behind the system: what each piece is for, when it is the wrong choice, and what to do when nothing fits. Props and types are in the shipped `.d.ts` files; live examples are at https://www.sakaniui.com/docs. Read this file first, then open a component's docs page for its props. Full machine-readable index: https://www.sakaniui.com/llms.txt (and `/llms-full.txt`). **The contract:** `@sakaniui/react/manifest.json` (also https://www.sakaniui.com/manifest.json) lists every exported component and block with its import path, props, types, enum values, defaults, which props are *required*, and every design token. It is generated from the TypeScript source on each build, so it is always in step with the installed version. Prefer it over guessing a prop name: ```ts import manifest from '@sakaniui/react/manifest.json'; const button = manifest.components.find((c) => c.name === 'Button'); // props[], contract.requiredProps ``` Editors can query the same data through the bundled MCP server (`npx -y -p @sakaniui/react sakaniui-mcp`): `get_component`, `check_usage`, `get_tokens`, `get_guide`. If it is connected, call `check_usage` on every component you write. If a prop, value or token is not in the manifest, it does not exist. If `contract.requiresAccessibleName` is true, the required `aria-label` / alt prop is the only thing that names the control. Do not drop it. --- ## 1. Setup you must get right ```tsx import '@sakaniui/react/tokens.css'; // design tokens (CSS variables) — once, at the app root import '@sakaniui/react/style.css'; // component styles — once import { Button, Card } from '@sakaniui/react'; ``` - **Both CSS imports are required.** Without `tokens.css` every component renders unstyled or black-and-white, because every colour, space, radius and shadow is a CSS variable defined there. - **Dark mode is a class.** Put `className="dark"` on any container; everything inside re-themes. Do not write per-component dark styles. - **Surface is a second axis, independent of light/dark:** `data-surface="solid" | "glass" | "liquid"` on a container. Components inside adapt. See §4. ## 2. Principles (apply these when a case is not covered) 1. **Tokens, never literals.** Colours, spacing, radius, shadows come from `var(--color-…)`, `var(--space-…)`, `var(--radius-…)`. A hex value in your code will not follow dark mode, glass surfaces or future theme changes. If you need a colour that has no token, pick the nearest semantic token and say so; do not invent a hex. 2. **Semantic roles over raw values.** Use `--color-fg-default / -muted / -subtle`, `--color-bg-surface / -canvas / -subtle`, `--color-border-subtle / -default / -focus`, `--color-accent-*`. The role says what the colour is *for*, which is what survives a re-theme. 3. **One primary action per view.** A single filled `primary` Button marks the thing the user most likely wants. Two filled buttons compete and make neither primary. Put the second action in `secondary` or `outline`, the third in `ghost`. 4. **Use the component, don't restyle a `