@box-kite/react

中文文档
2.4.0发布于 2026/11/07MITTypeScriptESM + CJS构建来源已验证近 30 天下载 3654

One React component that takes CSS properties as typed props and generates atomic CSS at runtime — no CSS files, no build step, renders in a Server Component.

原始使用文档
文档目录12 节
  1. The AI-first, fully typed styling library for React
  2. ⚡ Quick start
  3. ✨ Why Box Kite
  4. 🤖 Built for AI agents
  5. 🔒 Typed down to the value
  6. 📐 The scales
  7. 🧱 Components
  8. 🖥️ Server Components
  9. 📦 Packages
  10. 📚 Learn more
  11. 🤝 Contributing
  12. License
Box Kite — every CSS property is a typed prop. The React styling library your AI already knows.

The AI-first, fully typed styling library for React

npm version Tests TypeScript: every value is typed No third-party dependencies AGENTS.md ships in the package MCP server MIT license

Docs · Start with AI · Playground · Showcase · Blog · Releases


Box Kite styles React in TypeScript. Every CSS property is a prop on Box, every value it takes is a type, and the CSS is written for you at runtime — one shared class per value, no stylesheet to import, no class names to invent, no build plugin.

It is built to be written by an AI: the rules and a reference measured from the engine ship inside the package, an MCP server checks a prop bag against the real engine, and the compiler refuses a value the library would not render.

import Button from '@box-kite/react/components/button';
import Flex from '@box-kite/react/components/flex';
import { H2, P } from '@box-kite/react/components/semantics';

export function PlanCard() {
  return (
    <Flex d="column" gap={3} p={6} md={{ p: 8 }} borderRadius={3} shadow="md"
          bgColor="white" theme={{ dark: { bgColor: 'slate-900' } }}>
      <H2 fontSize={20} fontWeight={600}>Pro plan</H2>
      <P color="slate-600">Every value on this card is checked by the compiler.</P>
      <Button hover={{ bgColor: 'indigo-600' }}>Upgrade</Button>
    </Flex>
  );
}

Each prop becomes one shared class: p={6} is padding: 1.5rem, md wraps it in a media query, theme scopes it to the dark subtree, and the same value anywhere else in the app reuses the same rule.

⚡ Quick start

Start a new Vite + React app with a design, a sample page and the agent setup already in it:

npm create @box-kite@latest

Or add it to the app you have:

npm install @box-kite/react

React 18 or newer, and no third-party dependencies: the install is Box Kite and its own engine, nothing else. TypeScript is optional, but it is where the library shines.

✨ Why Box Kite

🤖 AI-first

The package carries its own AGENTS.md, a docs/ folder and a skill, all generated from the prop registry so they can never be a version behind. An MCP server answers mid-task.

🔒 Typed down to the value

Every prop accepts a closed set: palette tokens, scale steps, keywords. A typo is a compile error with a “Did you mean”, not a silently missing style.

🧩 Zero config, zero dependencies

No CSS files, no PostCSS, no bundler plugin, no provider — and no third-party packages in your lockfile. Styles are generated on demand and deduplicated by content.

🖥️ Server Components

Renders in a React Server Component with no 'use client': each rule travels with the markup as a <style> React 19 hoists and dedupes.

♿ Accessible components

Dialog, Menu, Tabs, Combobox, DatePicker, DataGrid and more — each with the ARIA and keyboard of its APG pattern, swept by axe in CI.

🎨 Modern CSS, as props

OKLCH palette, themes, container queries, @starting-style, anchor positioning, view transitions, scroll timelines — and the top layer instead of z-index.

🤖 Built for AI agents

A model's memory of a CSS-in-JS API is usually a memory of a different API — the prop names here collide with Tailwind's and Chakra's while the numbers mean something else. So Box Kite does not rely on what a model remembers:

WhatHow you get it
AGENTS.md + docs/ inside the npm packageAutomatic — node_modules/@box-kite/react/AGENTS.md, with every prop and the CSS it writes
Project wiring (AGENTS.md, CLAUDE.md, MCP)npm create @box-kite@latest -- --agents-only — merges into an existing repo, and updates on a rerun
Skill for Claude Code, Cursor, Codex, Copilot…npx skills add box-kite/box-kite
MCP server — no key, no networkclaude mcp add box-kite -- npx -y @box-kite/mcp (or the stdio config your editor takes)
llms.txt and markdown docsbox-kite.dev/llms.txt — append .md to any docs URL

check_styles runs your props through the real engine. A value the library does not accept writes no rule and no class name — by design, so a typo never emits a broken declaration. The MCP tool makes that visible before anything renders:

✅ p         → .p-4{padding:1rem}
❌ bgColor   does not accept "blue-550" — no rule and no class name were written.
✅ fontSize  → .fontSize-14{font-size:0.875rem}
⚠️ href      an HTML attribute, not a style prop. Written at the top level it typechecks
             and is then dropped — it goes in props={{ "href": … }}.

The dev console is written as a prompt. Each warning says what rendered and the line to write instead, so an agent reading a test run fixes itself:

[box-kite] bgColor="bleu-500" wrote no CSS: bgColor does not take that value, so the prop
           was dropped along with its class. Did you mean "blue-500"?
[box-kite] fontSize={4} is 4px text: fontSize's divider is 16, not the spacing scale's 4,
           so the number is the pixel size. For 16px write fontSize={16}.

And a UI a model writes at runtime is a first-class citizen. catalog() turns every component and every value its props take into JSON Schema — the shape structured output, json-render and A2UI want — and <SpecRenderer> renders what comes back, checking each node against an allow-list you control. toolPart() and a2uiToSpec() read AI SDK, assistant-ui, CopilotKit, AG-UI and A2UI, and <ToolCallCard>, <ApprovalCard>, <Reasoning> and <StreamingText> draw an agent's turn. → Generative UI · Agent components · Interop

🔒 Typed down to the value

Props are not string. Colours are palette tokens (with an optional /opacity), spacing is a scale, keywords are unions — so the editor autocompletes them and the compiler catches the rest:

<Box bgColor="bleu-500" />
//   ~~~~~~~ ts(2820): Type '"bleu-500"' is not assignable… Did you mean '"blue-500"'?

<Box display="flexx" />
//   ~~~~~~~ ts(2820): … Did you mean '"flex"'?

<Box opacity={50} />
//   ~~~~~~~ ts(2322): Type '50' is not assignable to type '0 | 1 | 0.1 | 0.2 | …'

<Button variant="primaryy">Save</Button>
//      ~~~~~~~ ts(2322): a component's variants are typed too

<Box css={{ mixBlendMod: 'multiply' }} />
//          ~~~~~~~~~~~ ts(2561): … Did you mean to write 'mixBlendMode'?
  • Hover a prop, see its CSS. Every prop's JSDoc carries an example such as p={4} → padding: 1rem — generated by running the engine, so the editor can never teach a scale the library stopped using.
  • Your own tokens join the types. Box.extend() adds variables, props and values; one declare module makes them autocomplete like the built-ins. Box.components() variants are typed the same way.
  • The escape hatch is typed too. css={{ … }} is checked against csstype and still compiles to a shared class — never a style attribute.

📐 The scales

The one thing worth learning by heart — the divider is per prop:

PropScaleExample
p, m, gap, width, borderRadius÷4 (quarter rem)p={4} → 1rem (16px)
fontSize÷16fontSize={14} → 0.875rem (14px)
b (border width), lineHeightpxb={1} → 1px
animationDuration, transitionDelay…mstransitionDuration={150} → 150ms
colourstokens + /opacitybgColor="blue-500/40" → color-mix(…)

Three conventions follow from "every visual value is a prop": the element comes from the component (<Flex>, <Button>, <H1>, <Path>), HTML attributes go in props (<Link props={{ href: '/about' }}>), and there is no style={{ }}.

🧱 Components

Every component is a Box underneath — same props, same theming, same variants — and each is its own entry point, so a Textbox never pulls the DataGrid into your bundle.

AreaComponents
Layout & contentFlex, Grid, H1–H6, P, Link, Nav…, List, Svg + every SVG element, Icon, Skeleton
FormsButton, Textbox, Checkbox, Switch, RadioGroup, Combobox, Slider, Form
DatesDateField, Calendar, DatePicker, TimeZoneSelect — over a zone-safe date module
OverlaysDialog, Popover, Menu, Tooltip, Toaster — in the top layer, no portal, no z-index
DisclosureTabs, Accordion, Progress
Data & dashboardsDataGrid (sort, filter, group, edit, paste, virtualized), DashboardGrid, Sparkline, Gauge, ChartContainer
AIToolCallCard, ApprovalCard, Reasoning, StreamingText, markdownComponents, SpecRenderer

The behaviour behind them ships on its own as @box-kite/react/a11y — focus return, roving focus, dismissal and controllable state — for the widgets you build yourself.

🖥️ Server Components

// app/page.tsx — a Server Component. No 'use client', no provider, no CSS import.
import Flex from '@box-kite/react/components/flex';
import { H1 } from '@box-kite/react/components/semantics';

export default function Page() {
  return (
    <Flex d="column" gap={2} p={6}>
      <H1 fontSize={24}>Rendered on the server</H1>
    </Flex>
  );
}

The react-server export condition resolves to a hook-free build of Box; each rule comes back as a <style href precedence> element that React 19 hoists into <head> and dedupes, so it is stream-safe and the cascade is held by @layer, not by element order. → How it works · measured against CSS modules · a whole Next.js app

📦 Packages

PackageWhat it is
@box-kite/reactBox, every component and hook; depends on @box-kite/core and nothing else
@box-kite/corethe styling engine with no framework and no dependencies — createStyleEngine().classNames(props) (example)
@box-kite/mcpthe MCP server: docs search, props, components, rules and check_styles
@box-kite/createnpm create @box-kite — a Vite + React app with a design and the agent setup

📚 Learn more

🤝 Contributing

Issues and pull requests are welcome — start with CONTRIBUTING.md, which covers the architecture and the framework-free core boundary. Questions go to SUPPORT.md, vulnerabilities to SECURITY.md.

If Box Kite saves you time, a ⭐ on GitHub helps other people find it.

License

MIT © Maxim Procopenco

版本与发布记录

@box-kite/react 共发布 27 个版本,首次发布于 2026/08/25;过去 12 个月发布了 27 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
2.4.0latest2026/11/071 天前
2.3.12026/11/061 天前
2.3.02026/11/044 天前
2.2.182026/11/044 天前
2.2.172026/11/034 天前
2.2.162026/11/035 天前

关于 @box-kite/react 的常见问题

@box-kite/react 是什么?

One React component that takes CSS properties as typed props and generates atomic CSS at runtime — no CSS files, no build step, renders in a Server Component.

如何安装 @box-kite/react?

在项目目录运行 npm install @box-kite/react,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:react(>=18.0.0)、react-dom(>=18.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@box-kite/react 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@box-kite/react 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@box-kite/react 可以商用吗?

@box-kite/react 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@box-kite/react 的下载量有多少?

根据 npm 官方下载统计,@box-kite/react 在 2026/10/09 – 2026/11/07 这 30 天内被下载 3,654 次,日均约 122 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@box-kite/react 还在维护吗?

最新版本 2.4.0 发布于 2026/11/07(1 天前);至今共发布 27 个版本,其中过去 12 个月发布了 27 个;首次发布于 2026/08/25。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。