# TVU Design System

TVU Design System Vue 3 component library. 1:1 implementation of the TVU Figma design system — tokens, components, and all variant states match the design spec exactly.

## Install

This package is published to **GitHub Packages** (private to `@nancyzeng0210` scope), not the public npm registry. Two steps:

### 1. Configure `.npmrc` (one-time per consumer repo)

Create or append to `.npmrc` at the consumer repo root:

```
@nancyzeng0210:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN
```

`YOUR_GITHUB_TOKEN` = [GitHub Personal Access Token](https://github.com/settings/tokens) with `read:packages` scope.

### 2. Add the package

```bash
pnpm add @nancyzeng0210/tvu-design-system
```

(or `npm install` / `yarn add` — same package.)

After install, a one-time setup hint prints with copy-paste commands for ESLint plugin + CI workflow. For a guided 5-minute walkthrough (Vite + Vue 3 project → render first Button → theme toggle), see [`docs/GETTING_STARTED.md`](docs/GETTING_STARTED.md).

## Setup

```typescript
// main.ts
import { createApp } from 'vue'
import TVUDesignSystem from '@nancyzeng0210/tvu-design-system'
import '@nancyzeng0210/tvu-design-system/style.css'
import App from './App.vue'

createApp(App).use(TVUDesignSystem).mount('#app')
```

## Usage

Import components globally (after `app.use(TVUDesignSystem)`) or locally:

```vue
<script setup lang="ts">
import { Button, Input } from '@nancyzeng0210/tvu-design-system'
import { ref } from 'vue'

const name = ref('')
</script>

<template>
  <Input v-model="name" placeholder="Enter name" />
  <Button canonical-style="filling" canonical-color="green" @click="save">Save</Button>
</template>
```

> **Note**: Since v0.6.0, Button uses the canonical 8-axis API (`canonical-style` + `canonical-color` + `canonical-size` etc.) — the legacy `variant` / `size` props have been removed. See [`docs/MIGRATION_TO_V1.md`](docs/MIGRATION_TO_V1.md) for the full mapping table if you're upgrading.

## Auto-audit (ESLint plugin)

Enable automatic linting of consumer code against TVU rules (`no-hardcoded-color` / `no-inline-svg` / `icon-from-dist` / `no-base-component-import`):

```js
// eslint.config.js (ESLint 9 flat config)
import tvuPlugin from '@nancyzeng0210/tvu-design-system/eslint-plugin'

export default [
  // ...your existing config...
  tvuPlugin.configs.recommended,
]
```

Editor saves and CI lint runs will now auto-trigger the rules. See [`docs/CONSUMER_AUDIT_SETUP.md`](docs/CONSUMER_AUDIT_SETUP.md) for CI workflow templates and mockup audit setup.

## Icons

The design system now keeps icons in a category-first architecture so Vue projects, React projects, and CDN consumers can all share the same source.

### In Vue components

```vue
<script setup lang="ts">
import { Icon } from '@nancyzeng0210/tvu-design-system'
</script>

<template>
  <Icon name="time/clock" />
  <Icon name="setting/skin" />
</template>
```

Legacy aliases such as `clock` still work for backward compatibility, but new usage should prefer `category/name`.

### In other frameworks

Per-category ESM files are published in `dist/icons/esm`:

```ts
import { SettingIcons } from '@nancyzeng0210/tvu-design-system/icons/esm'

const skinSvg = SettingIcons['setting/skin']
```

React projects can use the same assets without pulling in the Vue runtime:

```tsx
import { SettingIcons, TimeIcons } from '@nancyzeng0210/tvu-design-system/icons/esm'

export function HeaderActions() {
  return (
    <div>
      <span dangerouslySetInnerHTML={{ __html: TimeIcons['time/clock'] }} />
      <span dangerouslySetInnerHTML={{ __html: SettingIcons['setting/skin'] }} />
    </div>
  )
}
```

TypeScript declarations are emitted for every category file, so imports such as `@nancyzeng0210/tvu-design-system/icons/esm/setting` and `@nancyzeng0210/tvu-design-system/icons/esm` work in TS-aware React builds without extra declaration shims.

### CDN / static asset usage

Build output also includes raw SVG files plus a manifest:

- `dist/icons/manifest.json`
- `dist/icons/svg/<category>/<file>.svg`
- `dist/icons/esm/<category>.js`
- `dist/icons/esm/<category>.d.ts`

Example static URL shape:

```text
https://cdn.example.com/tvu-design-system/0.1.0/icons/svg/Setting/Skin__1235_3292.svg
```

The manifest keeps the stable code-facing name (`category/name`) mapped to the original SVG asset path.

## Theme switching

Apply `data-theme="light"` to `<html>` to switch to light mode. Default is dark.

```js
document.documentElement.setAttribute('data-theme', 'light')
```

## Components

29 components across foundation / layout / form / feedback / navigation categories. Full props / events / slots documented in the docs site (`pnpm dev` → `http://localhost:5173`).

| # | Component | Purpose |
|---|-----------|---------|
| 1 | `Button` | 按钮（fill / ghost / text 三族 × 6 颜色 × 3 size） |
| 2 | `Badge` | 计数 / 状态点 / 文字徽章 |
| 3 | `Breadcrumb` | 面包屑容器 |
| 4 | `BreadcrumbItem` | 面包屑节点（`Breadcrumb` 子组件） |
| 5 | `InputBoxLine` | 输入框 - 下划线变体 |
| 6 | `InputBoxFilled` | 输入框 - 填充变体 |
| 7 | `CheckBox` | 复选框 |
| 8 | `FormItem` | 表单项容器（label + control + error / helper text） |
| 9 | `InputNumber` | 数字输入框（加减按钮 + 直接输入） |
| 10 | `Notification` | 通知气泡（命令式 API + dynamic mount） |
| 11 | `PromptMessage` | 静态消息条（页面内 inline 提示） |
| 12 | `Pagination` | 分页器 |
| 13 | `Progress` | 进度条 |
| 14 | `Radio` | 单选框 |
| 15 | `Rating` | 评分（5 星） |
| 16 | `Slider` | 滑块 |
| 17 | `Switch` | 开关 |
| 18 | `Table` | 表格 |
| 19 | `TopBar` | 顶栏导航 |
| 20 | `SelectBoxLine` | 下拉选择 - 下划线变体 |
| 21 | `SelectBoxFilled` | 下拉选择 - 填充变体 |
| 22 | `DropDownListSelect` | 下拉列表选择器（多选 + 搜索） |
| 23 | `StepItem` | 步骤节点（`Steps` 子组件） |
| 24 | `Steps` | 步骤条容器 |
| 25 | `Tab` | 单个标签页 |
| 26 | `TabItem` | 标签节点（`TabList` 子组件） |
| 27 | `TabList` | 标签页容器 |
| 28 | `Tooltip` | 气泡提示 |
| 29 | `Icon` | 图标组件（`name="category/name"` 形式） |

In addition to components, `@nancyzeng0210/tvu-design-system` also exports icon helpers (`iconManifest`, `iconRegistry`, `resolveIcon`, `listIconsByCategory`) and pre-built icon constants (`IconAdd` / `IconMinus` / `IconArrowDropdown` / `IconSelected` / `LogoTVU` / `LogoTS`). See [`src/icons/index.ts`](src/icons/index.ts) for the full surface.

## Development

```bash
pnpm dev        # playground dev server at localhost:5173
pnpm test       # run tests
pnpm generate   # regenerate components from figma-data/
pnpm generate:icons-catalog  # regenerate icon manifest + category files from published icons
pnpm build      # build library to dist/
pnpm audit:docs-site  # fail if docs pages cannot honestly claim pixel parity
pnpm audit:figma-conformance  # fail if generated code still diverges from Figma-first rules
```

## Contributors / Local Setup

### Clone + install

```bash
git clone https://github.com/NancyZeng0210/TVU-Design-System.git
cd TVU-Design-System
pnpm install              # install deps + husky pre-commit hooks
```

### AI tooling (optional, recommended for Claude Code users)

The repo ships with project-level Claude Code conventions / hooks / scripts / skills for AI-assisted **Figma → Code** workflows. When `cwd` is in this repo, `.claude/settings.json` auto-activates:
- UserPromptSubmit hook that injects R7-R12 reminder on Figma URL prompts
- 6 project skills (`tvu-design-code` / `tvu-design-mockup` / 4 design-process skills)
- Pre-commit gates (vue-tsc + vitest + visual commit approval)

For **cross-project use** (hook also fires when working in sibling consumer projects), run the one-time global install:

```bash
bash scripts/install-claude-config.sh
```

This idempotent script:
- Copies `.claude/hooks/detect-figma-task.sh` → `~/.claude/hooks/`
- Merges UserPromptSubmit registration into `~/.claude/settings.json` (deduplicates)
- Sets `TVU_DESIGN_SYSTEM_PATH` env var in `~/.zshrc` or `~/.bashrc`

### Key AI-tooling references

| Path | Purpose |
|---|---|
| [`docs/internal/code-conventions.md`](docs/internal/code-conventions.md) | R7-R10 + R12 + 规则适用速查表 (mandatory Figma → Code workflow) |
| [`docs/meta-rules.md`](docs/meta-rules.md) | Meta-rule 触发器 K (enforcement 层级 L1-L5) + L (不确定必 ask) |
| [`scripts/figma-extract-css.py`](scripts/figma-extract-css.py) | Data-driven CSS extraction from Figma MCP (eliminates AI estimation) |
| [`scripts/figma-asset-fetch.py`](scripts/figma-asset-fetch.py) | Figma asset fetch + auto-detect format + save with correct extension |
| [`scripts/visual-diff.py`](scripts/visual-diff.py) | Chrome headless screenshot vs Figma truth — objective diff% (R8 v2 L3) |

Project-shared config lives in `.claude/settings.json` (in git). Personal overrides go in `.claude/settings.local.json` (gitignored).

## Team usage notes

- `.env` is only needed for Figma sync scripts and should not be committed.
- `.env.example` shows the expected variables for local setup.
- If you only want to use the component library, you do not need a Figma token.

## Figma sync

Components are generated from Figma design data. When the design changes:
1. Open Figma + Claude Code
2. Run the extraction scripts to update `figma-data/`
3. Run `pnpm generate`

See `figma-sync/README.md` for details.

## AI handoff

This repository is designed to be continued across Claude, Codex, Cursor, Cline, Copilot, and other AI tools.

- Start from `AGENTS.md` for the cross-AI contract.
- Read `docs/PROJECT_GOAL.md` for product goals and roadmap.
- Read `docs/PROJECT_MAP.md` for data sources, project structure, generation flow, cleanup rules, and Claude/Codex responsibilities.
- Use `docs/internal/_prompts/` for versioned Codex execution prompts.
