# Getting Started — TVU Design System (5 min)

This guide walks you from zero to rendering your first TVU component in a fresh Vue 3 project. ~5 minutes.

For the cross-AI workflow contract (Claude / Codex / Cursor / Cline), see [`AGENTS.md`](../AGENTS.md). For full product goals, see [`docs/PROJECT_GOAL.md`](./PROJECT_GOAL.md).

---

## 1. Create a Vue 3 project

If you already have a Vue 3 + TypeScript project, skip to step 2.

```bash
npm create vite@latest my-app -- --template vue-ts
cd my-app
npm install
```

(Replace `npm` with `pnpm` / `yarn` if preferred — the rest of this guide assumes `pnpm`.)

---

## 2. Install the design system

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

`vue@^3.4.0` is a peer dependency and should already be in your project.

---

## 3. Import token CSS (required)

TVU Design System components rely on CSS variables for colors, spacing, typography, and theme switching. **You must import the bundled stylesheet once**, typically in `main.ts`:

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

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

Without this import, components will render unstyled (no token resolution).

---

## 4. Pick an import mode

You have two options. Both are supported; pick what fits your project.

### Option A — Global registration (simplest)

Register the whole library once; use any component by tag name anywhere:

```typescript
// src/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')
```

Then in any `.vue` file:

```vue
<template>
  <Button color="green" size="M">Save</Button>
</template>
```

### Option B — Per-component import (tree-shake friendly)

Skip `.use(TVUDesignSystem)` and import each component locally:

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

<template>
  <Button color="green" size="M">Save</Button>
</template>
```

Option B keeps your bundle smaller if you only use a few components.

---

## 5. Render your first component — Button

Create `src/App.vue`:

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

function onSave() {
  console.log('saved!')
}
</script>

<template>
  <main style="padding: 32px;">
    <h1>Hello TVU</h1>
    <Button color="green" size="M" @click="onSave">Save</Button>
    <Button color="gray 1" size="M">Cancel</Button>
  </main>
</template>
```

Run the dev server:

```bash
pnpm dev
```

Open `http://localhost:5173` — you should see a green "Save" button and a gray "Cancel" button on a dark background (dark is the default theme).

### Button props (read this before copy-pasting other examples)

The Vue `<Button>` exposes the design axes as **separate props** (this replaced the old combined `variant="fill-green"` string — that prop no longer exists):

| Prop | Values | Default |
|---|---|---|
| `color` | `'green'` · `'gray 1'` · `'red'` · `'orange'` | `'gray 1'` |
| `fill` | `'filling'` · `'ghost'` · `'rimless'` | `'filling'` |
| `size` | `'XS'` · `'S'` · `'M'` · `'L'` | `'M'` |
| `radius` · `fixedWidth` · `icon` · `status` · `theme` | see the docs site Button page | — |

So a green **solid** button is `color="green"` (`filling` is the default — no `fill` needed). A gray **outlined** button needs the `fill` prop: `fill="ghost"`.

Both Vue and React consumers use `fill` — static attribute syntax works directly:

```vue
<!-- ✅ works -->  <Button fill="ghost" color="gray 1" size="M">Cancel</Button>
<!-- ✅ works -->  <Button fill="rimless" color="green" size="M">Link</Button>
```

---

## 6. Toggle the theme

The design system ships with a complete dark / light theme system driven by `data-theme` on `<html>`. Default is dark. Switch to light at runtime:

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

Switch back to dark:

```typescript
document.documentElement.setAttribute('data-theme', 'dark')
```

All component colors, surfaces, borders, and shadows respond automatically — no per-component prop needed.

To make a toggle button:

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

const isDark = ref(true)

function toggleTheme() {
  isDark.value = !isDark.value
  document.documentElement.setAttribute('data-theme', isDark.value ? 'dark' : 'light')
}
</script>

<template>
  <Button fill="ghost" color="gray 1" size="M" @click="toggleTheme">
    Switch to {{ isDark ? 'light' : 'dark' }}
  </Button>
</template>
```

---

## 7. Next steps

- Browse all 29 components and their full props / events / slots in the local docs site: `pnpm dev` in the design system repo → `http://localhost:5173`
- Read [`AGENTS.md`](../AGENTS.md) for the AI-assisted Figma → code workflow if you're using Claude / Codex / Cursor with this library
- See the [`README.md`](../README.md) Icons section for icon usage (`<Icon name="time/clock" />`) including React / CDN consumption modes

---

## 8. Consuming design tokens (JSON / TS)

Beyond `style.css` (CSS variables), the design tokens are also published as structured data so **non-web tools** (native / RN / design tooling / AI agents) and typed TS consumers can read them.

**Typed JS / TS** — resolved values, ergonomic import:

```ts
import { tokens, tokensLight, type TokenName } from '@nancyzeng0210/tvu-design-system/tokens/js'

tokens.palette['color-grey-8'] // '#595959'
tokens.semantic['bg-layer1']   // '#141414' (dark, the default theme)
tokensLight['bg-layer1']       // '#ffffff' (light-theme override)
const name: TokenName = 'sp-m' // union of every token name
```

- `tokens` = resolved **dark** (default theme) values, grouped `palette` / `semantic` / `nonColor`.
- `tokensLight` = flat map of the light-theme overrides (merge over `tokens` when in light mode).
- `TokenName` = union type of all token names.

**Raw DTCG JSON** — for tooling / other languages / design import:

```ts
import tokens from '@nancyzeng0210/tvu-design-system/tokens' with { type: 'json' }
```

The JSON is [DTCG](https://tr.designtokens.org/format/) format: `$type` / `$value` per token, aliases kept as `{group.name}` references, and both themes carried on `$extensions["tvu.mode"]` (`{ dark, light }`). Tooling that resolves references per-mode gets the correct themed value; the TS export above is the pre-resolved convenience layer.

Both come from the single source of truth `src/tokens/variables.css` and are regenerated on every `pnpm build`; a publish-time gate blocks stale exports.

---

## Troubleshooting

| Symptom | Likely cause | Fix |
|---|---|---|
| Components render unstyled | Forgot `import '@nancyzeng0210/tvu-design-system/style.css'` | Add the import to `main.ts` |
| TypeScript "cannot find module" | Vue version < 3.4 | Upgrade `vue` to `^3.4.0` (peer dep) |
| Icons show as empty boxes | Using legacy alias not in catalog | Use `category/name` form (e.g. `time/clock`), not legacy aliases |
| Theme toggle doesn't update colors | Setting attribute on wrong element | Must be `<html>` element (`document.documentElement`), not `<body>` |
