# Spark Design

现代化 React 设计系统，支持双维度主题（颜色 theme + 布局 scale），5 种内置布局风格，提供 Basic 基础组件与 Chat 对话流组件，可扩展颜色主题。

**当前版本**：`0.4.9`（[CLI 快速上手](docs/getting-started-cli.md) / [NPM 快速上手](docs/getting-started.md)）

> 🌟 **纯新手？** 查看 [CLI 快速上手指南](docs/getting-started-cli.md)，一步步带你跑起来！

> 以下为**安装与使用说明**；仓库结构、开发脚本与贡献方式见文末 [仓库与开发](#仓库与开发)。

## 特性

- **双维度主题**：`data-theme`（颜色）+ `data-style`（布局），独立切换
- **5 种布局风格**：neutral / compact / soft / sharp / dense
- **官方起始 preset**：Mint / Parchment
- **CSS 变量驱动**：覆盖颜色和 scale token 即可定制
- **图标系统可替换**：通过 `IconsProvider` 接 Remix、Lucide 或自定义图标库
- **Tailwind 友好**：类名与设计 token 映射，无硬编码色值
- **组件分层**：Basic 原子组件 + Chat 对话组件，开箱即用
- **AI 友好契约**：`agent-manifest.json` + token ontology + component selection guide 让 agent 按 intent、states、a11y、composition 和 anti-patterns 选择组件
- **可复制 Agent Recipes**：安装、页面组合、AI 工作流、组件维护和审查都有提示词模板
- **同构维护流程**：registry、CLI、showcase、docs、P2/P3 与发布门禁保持一致

## 两种使用方式

| 方式 | 适用场景 | 命令 |
|------|----------|------|
| **npm 安装** | 直接引用、不改源码 | `npm install sparkdesign` |
| **CLI 按需引入** | 复制源码到项目、可自由修改 | `npx sparkdesign init` → `npx sparkdesign add button` |

**发布模型**：`sparkdesign` 是唯一发布到 npm 的包。CLI 不是第二个独立 npm 包，而是根包中的 `bin` 入口；因此用户侧既可以 `npm install sparkdesign`，也可以直接 `npx sparkdesign@latest add button`。

### 风格控制模型

不管你用哪种接入方式，真正决定项目风格的都是三层：

- **colors**：颜色 token，决定品牌色、背景、边框、语义色
- **scale**：布局 token，决定间距、圆角、字号和密度
- **icons**：图标系统，决定视觉语言

`mint` / `parchment` 只是官方提供的两套 starter preset，更适合当起点和 showcase 示例，而不是长期绑定的唯一主题心智。

### 接入后你实际拿到什么

**CLI 模式**

- `components.json`：记录默认 `appearance / theme / style`
- `src/sparkdesign-tokens.css` 或注入后的 `src/index.css`：预设好的颜色和 scale token，可直接改
- `src/components/ui/...`：复制出来的组件源码，可直接改
- `src/lib/utils.ts`：组件依赖的工具函数

**npm 安装模式**

- 预编译样式：`import 'sparkdesign/style'`
- token 入口：`import 'sparkdesign/theme.css'` / `import 'sparkdesign/scale.css'`
- 运行时入口：`ThemeStyleProvider`、`IconsProvider`

也就是说：

- **CLI** 更适合“拿到文件后自己改”
- **npm** 更适合“先跑起来，再通过 token 和 icon 覆盖”

---

## 安装（npm 包）

```bash
npm install sparkdesign
```

**依赖**：需自行安装 `react`、`react-dom`（>=18）。

### 按需引入（CLI，推荐）

若希望**将组件源码复制到项目中**并自由修改，可使用 CLI：

```bash
npx sparkdesign init                    # 初始化 components.json、tokens、utils
npx sparkdesign add button tooltip      # 添加组件到 src/components/ui/
npx sparkdesign list                    # 列出可用组件
npx sparkdesign diff button             # 对比本地与注册表差异
```

详见 [docs/cli/on-demand-import.md](docs/cli/on-demand-import.md)。

---

## 快速开始

三步即可在项目中使用组件，**无需配置 Tailwind**：

```tsx
// 1. 引入样式（必做）
import 'sparkdesign/style'

// 2. 按需引入组件与类型
import { Button } from 'sparkdesign'
import type { ButtonProps } from 'sparkdesign'

// 3. 在根节点设置主题与布局（可选，不设则使用默认 light + neutral）
function App() {
  return (
    <div data-theme="light" data-style="neutral">
      <Button variant="primary" size="md">点击</Button>
    </div>
  )
}
```

**样式引入方式**（三选一，推荐方式 A）：

| 方式 | 用法 | 说明 |
|------|------|------|
| **A** | `import 'sparkdesign/style'` | **推荐**。预编译完整样式（Tailwind 工具类 + 设计 token），无需配置 Tailwind |
| **B** | `import 'sparkdesign/theme.css'`<br>`import 'sparkdesign/scale.css'` | 仅引入设计 token，适合已有 Tailwind 4 项目自行扫描组件并覆盖变量（需在消费者 CSS 中 `@source` 指向本包） |
| **C** | 只引入组件、不引入样式 | 需在项目中自行提供与设计 token 同名的 CSS 变量，否则组件无样式 |

> **Markdown 数学公式**：若使用 `MarkdownBody` 组件且需要渲染 KaTeX 数学公式，额外引入：
> `import 'sparkdesign/katex.css'`

自定义主题时，请**先**引入设计系统样式，**再**引入你的覆盖 CSS，变量覆盖才会生效。

---

## 设计系统用法

### 1. 引入样式（必做）

样式引入的三种方式见上方「快速开始」表格。

- **方式 A**（推荐）：`import 'sparkdesign/style'` 包含预编译的 Tailwind 工具类 + theme/scale 设计 token，消费者项目**不需要安装或配置 Tailwind**。
- **方式 B**（Tailwind 用户）：仅引入 token 文件，消费者需在自己的 CSS 中 `@source` 指向本包以扫描组件中使用的 Tailwind 类名：

```css
/* 消费者 CSS（已有 Tailwind 4 的项目）*/
@import "tailwindcss";
@source "../node_modules/sparkdesign/dist";
@import "sparkdesign/theme.css";
@import "sparkdesign/scale.css";
```

约定：自定义主题时，**先**引入设计系统样式，**再**引入你的覆盖 CSS。

### 2. 颜色主题（theme）

通过 `data-theme` 切换颜色主题，作用于主色、背景、边框、语义色等。

| 主题   | 说明     |
|--------|----------|
| `light` | Mint 亮色（默认） |
| `dark`  | Mint 暗色 |
| `light-parchment` | Parchment 亮色 |
| `dark-parchment` | Parchment 暗色 |

```tsx
// 在根节点或任意父节点设置
<div data-theme="dark">
  <Button variant="primary">按钮</Button>
</div>
```

```html
<!-- 或直接挂在 body -->
<body data-theme="dark">
```

如果你使用 React，`ThemeStyleProvider` 还支持按三维组合主题：

- `appearance`: `light | dark`
- `theme`: `mint | parchment | 自定义对象`
- `style`: `neutral | compact | soft | sharp | dense`

例如 `appearance="dark" theme="parchment" style="soft"` 会得到 `data-theme="dark-parchment"` 与 `data-style="soft"`。主题对应的 CSS 变量定义在 **theme.css**（如 `--color-primary`、`--color-bg-container` 等）。自定义主题见下文「自定义 theme / scale」。

### 3. 布局风格（scale）

通过 `data-style` 切换布局尺度，作用于间距、圆角、字号等。

| 风格      | 描述           | 特点           |
|-----------|----------------|----------------|
| `neutral` | 平衡的标准     | 默认，简洁直观 |
| `compact` | 优化效率       | 更窄间距，紧凑 |
| `soft`    | 舒适至上       | 大圆角、宽松间距 |
| `sharp`   | 几何精度       | 直角、利落线条 |
| `dense`   | 信息密集       | 最小留白       |

```tsx
<div data-style="soft">
  <Button>按钮</Button>
</div>
```

布局变量定义在 **scale.css**（如 `--spacing-*`、`--radius-*`、`--font-size-*`）。可组合使用：

```tsx
<div data-theme="dark" data-style="soft">
  {/* 暗色 + 柔和布局 */}
</div>
```

### 4. 真正决定风格的三件事

- **颜色变量**：决定品牌色、背景、边框、语义色
- **scale 变量**：决定间距、圆角、字号和组件密度
- **图标系统**：决定视觉语言和产品气质

官方 `mint` / `parchment` 只是两套 starter preset。无论你用整包还是 CLI，长期稳定的定制入口都应该是 token + icons，而不是依赖 preset 名称本身。

### 5. 自定义 theme / scale

在**先引入设计系统样式之后**，用你自己的 CSS 覆盖变量即可。

**选择器约定**：

- `:root` — 覆盖默认
- `[data-theme="主题名"]` — 颜色主题（自定义名称）
- `[data-style="风格名"]` — 布局风格（自定义名称）

```css
/* 自定义颜色主题 */
[data-theme="my-brand"] {
  --color-primary: #3B82F6;
  --color-primary-hover: #2563EB;
}

/* 自定义布局风格 */
[data-style="custom"] {
  --spacing-4: 20px;
  --radius-md: 8px;
}
```

完整变量说明见 [主题自定义指南](docs/guides/theme-customization.md)（颜色 `--color-*`、间距 `--spacing-*`、圆角 `--radius-*`、字号 `--font-size-*` 等）。

### 6. Portal 浮层与主题一致

DropdownMenu、Tooltip 等会挂到 `body`，不会继承局部容器的 `data-theme` / `data-style`。两种做法：

- **做法 A**：把 `data-theme`、`data-style` 设到 `<html>` 或 `<body>`，全局一致。
- **做法 B**：用 `ThemeStyleProvider` 包裹应用，浮层会使用同一主题/风格：

```tsx
import { ThemeStyleProvider, Button, DropdownMenu } from 'sparkdesign'

function App() {
  const appearance = 'dark'
  const theme = 'mint'
  const style = 'soft'
  return (
    <ThemeStyleProvider appearance={appearance} theme={theme} style={style}>
      <div data-theme="dark" data-style={style}>
        <Button>打开</Button>
        <DropdownMenu>...</DropdownMenu>
      </div>
    </ThemeStyleProvider>
  )
}
```

## 组件使用

组件与类型均从主入口按需引入，用法见上方「快速开始」。示例：

```tsx
import 'sparkdesign/style'
import { Button } from 'sparkdesign'
import type { ButtonProps } from 'sparkdesign'

function App() {
  return (
    <div data-theme="light" data-style="neutral">
      <Button variant="primary" size="md">Click me</Button>
    </div>
  )
}
```

## 组件概览

| 分层 | 说明 | 示例 |
|------|------|------|
| **Basic** | 原子级 UI 组件 | Button, IconButton, Tooltip, Select, DropdownMenu, Tabs, Toast, Tag, Progress, Avatar, Table, Slider, Pagination, Collapse, Resizable, Scrollbar, Skeleton, Spinner, Kbd, EllipsisText, Switch, Toggle, ToggleGroup, RadioGroup, AlertDialog, OptionList … |
| **Chat** | 对话流相关组件 | ChatInput, SendButton, Request, Response, FileCard, FileAttachment, ImageAttachment, FolderButton, ReasoningStep, ToolInvocationCard, PermissionCard, MarkdownBody, GenerationStatusBar, ThinkingIndicator, ImageGenerating, RelatedPrompts, SuggestionPart, SidebarMenu … |

完整导出见 [src/components/index.ts](src/components/index.ts)。图标通过 `IconsProvider` / `useIcon` 注入，默认推荐 Remix，也可替换为 Lucide 等，见 [图标自定义说明](docs/guides/icons-customization.md)。

## 文档（仓库内）

| 文档 | 说明 |
|------|------|
| [NPM 快速上手](docs/getting-started.md) | 整包引入、ThemeStyleProvider、Portal 主题继承 |
| [CLI 快速上手](docs/getting-started-cli.md) | `npx sparkdesign init / add` 入门 |
| [组件入库文档](docs/guides/component-development.md) | 组件与 Showcase 规范 |
| [图标自定义说明](docs/guides/icons-customization.md) | IconsProvider / Remix 默认示例 / 替换为 Lucide 等 |
| [CLI 按需引入方案](docs/cli/on-demand-import.md) | CLI 架构与按需引入说明 |
| [Component Lifecycle SOP](docs/sop/component-lifecycle.md) | 组件从开发到发布的固定流程 |
| [Theme Lifecycle SOP](docs/sop/theme-lifecycle.md) | preset / token / ThemeStyleProvider 维护流程 |
| [Release Checklist](docs/sop/release-checklist.md) | 发布前后检查单 |

---

## 仓库与开发

以下内容面向**参与仓库开发**的贡献者；仅使用本包时可忽略。

### 组件展示（Showcase）

本仓库内 **apps/showcase** 提供所有组件的演示与 Props 文档：

```bash
cd apps/showcase && npm install && npm run dev
```

### 项目脚本

| 脚本 | 说明 |
|------|------|
| `npm run dev` | 设计系统开发服务器 |
| `npm run build` | 生产构建：Vite 输出 JS → @tailwindcss/cli 预编译 CSS → tsc 类型声明 |
| `npm run build:css` | 仅重新生成预编译 CSS（`dist/sparkdesign.css`） |
| `npm run preview` | 预览构建产物 |
| `cd apps/showcase && npm run dev` | 组件展示站点 |

### 目录结构

```
src/
├── index.css       # dev 模式 CSS 入口
├── lib.css         # 库构建 CSS 入口（@tailwindcss/cli）
├── tokens/         # theme.css、scale.css
├── components/     # basic/、chat/
└── lib/            # 工具与 ThemeStyleProvider
```

### 技术栈与规范

- React 19 + TypeScript + Vite 7；Tailwind CSS 4；Radix UI、Framer Motion
- 项目哲学与 GEB 协议：[AGENTS.md](https://github.com/nicepkg/spark-design/blob/master/AGENTS.md)

---

*"Keep the map aligned with the terrain."*
