# Prompt — INFRA-F23: FormItemPage 整页重写 (toggle-aware)

> **角色**：executor（被 plan owner 调用 / 或单独跑）
> **范围**：把 `playground/docs/pages/FormItemPage.vue` 从手写 dual-theme dual-card 范式重写为单 `<FigmaMembersGrid>` + `inject('docsTheme')` 的 F19 范式
>
> ⚠️ **不要 commit / 不要 git add**——dirty 累积到 plan owner 视觉验收通过后 commit
> ⚠️ 完成后 **STOP**，按 §4 报告格式回报
> ⚠️ **不扩范围**：仅改 `playground/docs/pages/FormItemPage.vue`（含 script + template + style 整页重写）+ 跑现有 audit 验证 + 报告。**不改其它 page / 不改组件 / 不改 figma-data / 不改 audit script**

---

## §0 — Plan owner 已定决策

### F22 前置（已落 commit `3376d4a0`）

F22 修了 generator 大小写敏感 bug，FormItem normalized data 现在含正确的派生 theme 字段：
- `figma-data/normalized/docs-figma-members/formitem.ts` 中 32 个 `theme: "dark"` variant + 32 个 `theme: "light"` variant 顶层都有 `theme` 字段
- audit-page-t2-sample FormItem α verdict 已从 N/A → pass
- 因此 `<FigmaMembersGrid>` 现在能正确按 docsTheme filter FormItem variants

### 当前 FormItemPage 违规现状

[`playground/docs/pages/FormItemPage.vue`](../../../playground/docs/pages/FormItemPage.vue) (499 lines) 含以下违反 INFRA-F19 范式：

| 现状 | 违规点 | 行号示例 |
|---|---|---|
| `defineProps<{ isDark: boolean }>()` 旧轨 prop | 不用 `inject('docsTheme')` 新轨 | line ~10 |
| 静态 `themeMembers` 数组写死 4 条 dark/light variants | 不用 figma 真源 generator 输出 | line 67-70 |
| 5 处 `docs-demo-card--dark` modifier 引用 + class | 违反"无 dark/light 并排"硬规则 | line 159, 169, 179, 192, 204, 243, 258 |
| 1 套 dual-theme dual-card grid（line 280-310） | 同上 | line 286 `:class="{ 'member-card--light': member.theme === 'Light', 'docs-demo-card--dark': member.theme === 'Dark' }"` |
| `theme="Dark"` / `theme="Light"` hardcoded 在 demo 实例 | 应跟 docsTheme inject 动态切换 | line 91 / 164 / 174 / 184 / 197 / 209 / 251 / 266 / 296 |
| `.docs-demo-card--dark` CSS rule (line 368+) | 应删 | style 段 |

### F23 目标

改造后 FormItemPage 行为：
- 切 docsTheme = 'dark' → 所有 demo 渲染 dark 版本，FigmaMembersGrid 只显示 dark variants (32 个)
- 切 docsTheme = 'light' → 所有 demo 渲染 light 版本，grid 只显示 light variants (32 个)
- **页面任何位置不出现 dark / light 并排**（硬规则）
- **页面任何位置不写死 `theme="Dark"` / `theme="Light"`**——全部用 `:theme="docsTheme"`

### 范式参考

[`playground/docs/pages/NotificationPage.vue`](../../../playground/docs/pages/NotificationPage.vue) 是 F19 改造完毕的标准范式：

```ts
import { computed, inject, ref, type Ref } from 'vue'
import FigmaMembersGrid from '../components/FigmaMembersGrid.vue'

const docsTheme = inject<Readonly<Ref<'dark' | 'light'>>>('docsTheme', ref('dark'))
const props = withDefaults(defineProps<{ locale?: string }>(), { locale: 'en-US' })
const isZhCN = computed(() => props.locale === 'zh-CN')
```

```vue
<FigmaMembersGrid
  :members="formitemFigmaMembers"
  :component="FormItem"
  :cell-min-width="'100%'"
/>

<!-- 演示实例 -->
<FormItem :theme="docsTheme" type="Label & Input" ... />
```

### 改造文件清单（**不可超出**）

| 文件 | 操作 |
|---|---|
| [`playground/docs/pages/FormItemPage.vue`](../../../playground/docs/pages/FormItemPage.vue) | 整页重写 |

**不动**：
- 任何其它 `playground/docs/pages/*Page.vue` 文件
- `src/canonical/FormItem.vue` / 任何组件
- `figma-data/normalized/docs-figma-members/formitem.ts` (F22 已修)
- `playground/docs/components/FigmaMembersGrid.vue` (F19 已修)
- `playground/docs/DocsShell.vue` (F19 已修)
- `playground/docs/docs.css` (除非 .docs-demo-card--dark 引用全删后无残留依赖)
- `package.json` / `figma-sync/`
- `AGENTS.md` / `mockup-conventions.md`

---

## §1 — 必读输入

按顺序：

1. [`AGENTS.md`](../../../AGENTS.md) — 项目硬规则（特别是"docs site 支持 dark/light theme toggle"段 line 165 起，"page 内不再分 Dark/Light 两 section"硬规则）
2. [`docs/internal/backlog.md`](../backlog.md) INFRA-F19 / F22 / F23 entries 上下文
3. [`playground/docs/pages/FormItemPage.vue`](../../../playground/docs/pages/FormItemPage.vue) — 整文件读一遍把握当前结构
4. [`playground/docs/pages/NotificationPage.vue`](../../../playground/docs/pages/NotificationPage.vue) — F19 范式范例
5. [`playground/docs/pages/RatingPage.vue`](../../../playground/docs/pages/RatingPage.vue) — 另一个 F19 范式参考（含 figma 真源 grid + 自定义 demo 段）
6. [`figma-data/normalized/docs-figma-members/formitem.ts`](../../../figma-data/normalized/docs-figma-members/formitem.ts) — figma 真源派生数据（F22 修后）
7. [`playground/docs/components/FigmaMembersGrid.vue`](../../../playground/docs/components/FigmaMembersGrid.vue) — grid 组件 API

---

## §2 — 任务清单

### 任务 2.1 — 删除 dual-theme 静态数据

- 删 line 67-70 的 `themeMembers` 数组（写死 4 条 dark/light variants）
- 删凡引用此数组的 `v-for` 循环段（line ~280-310）

### 任务 2.2 — 切换到 inject 新轨

- 删 `defineProps<{ isDark: boolean }>()`，改成 `withDefaults(defineProps<{ locale?: string }>(), { locale: 'en-US' })`
- 加 `import { inject, ref, type Ref } from 'vue'`
- 加 `const docsTheme = inject<Readonly<Ref<'dark' | 'light'>>>('docsTheme', ref('dark'))`
- 删 `const darkTheme = computed(...)` 之类基于 props.isDark 的派生（如有）

### 任务 2.3 — 替换所有 demo 实例的 theme prop

把所有 `theme="Dark"` / `theme="Light"` hardcoded 都改成 `:theme="docsTheme"`：
- line ~91 概览段 demo
- line ~164 Label & Input demo
- line ~174 Label & Selector demo
- line ~184 Label & Radio demo
- line ~197 Label & checkbox demo
- line ~209 Label & Switch demo
- line ~251 Layout demo
- line ~266 Long label demo
- line ~296 dual-theme matrix demo（删整段，由 FigmaMembersGrid 替代）

⚠️ 注意：FormItem 的 `theme` prop 接受 `'Dark' | 'Light'`（首字母大写，figma-original case）。`docsTheme` inject 提供 `'dark' | 'light'`（小写）。需要 case 转换：

```vue
<FormItem :theme="docsTheme === 'dark' ? 'Dark' : 'Light'" ... />
```

或加 computed:
```ts
const formItemTheme = computed<'Dark' | 'Light'>(() => docsTheme.value === 'dark' ? 'Dark' : 'Light')
```

后者更可读。**executor 选 computed 路径**——避免每个 demo 实例重复三元表达式。

### 任务 2.4 — 替换 dual-card matrix 段为 FigmaMembersGrid

原 line ~280-310 dual-theme dual-card grid 段（用 `themeMembers` × `statusList` 双循环渲染 dark + light 并排）整段删除，替换为：

```vue
<FigmaMembersGrid
  :members="formitemFigmaMembers"
  :component="FormItem"
  :cell-min-width="'100%'"
/>
```

需要 import：
```ts
import FormItem from '@/src/canonical/FormItem.vue'
import { formitemFigmaMembers } from '@/figma-data/normalized/docs-figma-members/formitem'
import type { FormItemFigmaProps } from '@/figma-data/normalized/docs-figma-members/formitem'
import FigmaMembersGrid from '../components/FigmaMembersGrid.vue'
```

### 任务 2.5 — 删除 docs-demo-card--dark 所有引用

- template 中所有 `class="... docs-demo-card--dark"` 改成 `class="... docs-demo-card"`（删 modifier）
- 5 处 `<article class="member-card docs-demo-card--dark">` 改成单 `<article class="docs-demo-card">`，外层 demo 卡片不应该再 modifier 区分主题
- 删 style 段中 `.docs-demo-card--dark { ... }` 整条 CSS rule（line 368 附近）
- 删 `.member-card--light` 如有

### 任务 2.6 — section 标题去 theme 字眼

如果 section 标题含"Dark Theme Members" / "Light Theme Members" / 或类似 theme-specific 措辞，改成功能名（参考 NotificationPage、RatingPage 的命名习惯）：
- "Family Matrix" / "Member Matrix" / "Figma family overview" 等
- 不写"dark theme" / "light theme" 字眼（page 级单一 toggle 已是上下文）

### 任务 2.7 — themeMembers 数组中相关行删除完整

确保删除：
- `themeMembers` 数组定义（line 67-70）
- 引用该数组的所有 `v-for` 循环
- API rows 中 `theme` 字段如保留要更新 description（不再是 dual-axis，而是 toggle-driven）。具体：line 76 `{ name: 'theme', ... }` 这条 API 描述行**保留**（因为 FormItem 组件本身仍接受 `theme` prop 作为 figma family 的派生轴），但 description 文案适当改造为"由 docs site theme toggle 驱动，不在 page 级硬编码"

### 任务 2.8 — 跑 vue-tsc + 现有 audit 验证

```bash
pnpm exec vue-tsc --noEmit                      # 必 0 errors
pnpm audit:figma-conformance                    # 必 overallPass=true
pnpm audit:docs-site                            # 仅历史 in-review warn 允许
node figma-sync/audit-page-t2-sample.mjs        # FormItem 自身 verdict 不应 regress
pnpm audit:no-hardcoded-design-tokens           # FormItemPage 不应新增 hardcoded（如有改动后引入新 hex/px → STOP）
pnpm audit:icon-fill-currentcolor               # 不动 icon catalog，应不变
```

### 任务 2.9 — STOP 等 plan owner 视觉验收

不要 commit / push / git add。**Plan owner 必须自己跑 dev server 视觉验收**：
- `pnpm dev`
- 访问 docs site，进入 FormItem page
- 切 dark / light toggle，verify：
  - grid 自动 filter（dark 32 / light 32 各 32 variant）
  - 所有 demo 实例（Label & Input / Selector / Radio / etc.）都正确渲染当前 theme
  - 无 dark/light 并排
  - 无 `docs-demo-card--dark` 视觉残留

通过后 plan owner 自己写 retrospection + commit + push。

---

## §3 — 验收清单

- [ ] `defineProps<{ isDark: boolean }>` 改为 `defineProps<{ locale?: string }>` + inject docsTheme
- [ ] 整页**0 处** `docs-demo-card--dark` modifier
- [ ] 整页**0 处** hardcoded `theme="Dark"` / `theme="Light"`（全部 `:theme="..."` 跟 docsTheme）
- [ ] 整页**0 处** dual-theme 并排 grid / dual-card
- [ ] 整页**0 处** 引用 `themeMembers` 数组
- [ ] FigmaMembersGrid 加上 `:members="formitemFigmaMembers"` `:component="FormItem"` `:cell-min-width="'100%'"`
- [ ] vue-tsc 0 errors
- [ ] audit-page-t2-sample FormItem α verdict 仍 pass
- [ ] audit:figma-conformance overallPass=true
- [ ] audit:docs-site 仅历史 in-review warn
- [ ] audit:no-hardcoded-design-tokens FormItemPage finding 数不增（如增需 §4 报告解释）
- [ ] **不动**：其它 page / 组件 / figma-data / audit script / package.json / 任何 docs 真源
- [ ] **未 commit / 未 git add**

---

## §4 — 完成报告

```
## INFRA-F23 FormItemPage 整页重写 完成报告

### 改动文件
- playground/docs/pages/FormItemPage.vue (改 +X/-Y 行)

### §4.X 完整改动清单
[git status --short 全列表]
[如有范围外改动，标 ⚠️ 解释]

### Diff 统计
- 删行：[原 Y 行]
- 新行：[新 X 行]
- 净缩减：[Y - X]（应能压缩，因 dual-theme dual-card 段删除是大头）

### 范式遵循 verify
- [x] inject('docsTheme') 加上
- [x] FigmaMembersGrid 替换 dual-card matrix
- [x] :theme="formItemTheme" 替换所有硬编码
- [x] docs-demo-card--dark 全删
- [x] section 标题去 theme 字眼

### Audit 结果
- vue-tsc: 0 errors
- audit-page-t2-sample FormItem α verdict: pass (dark X / light Y, 与 F22 commit 后一致)
- audit:figma-conformance: overallPass=true
- audit:docs-site: 仅历史 in-review warn
- audit:no-hardcoded-design-tokens FormItemPage 段：[finding 数 before/after]
- audit:icon-fill-currentcolor: 不变

### 未解决项 / blocker
- 无则写"无"
- 如遇 FormItem canonical 组件本身 prop case 不接受小写 → 报告（不擅自改 canonical）

STOP — 等 plan owner dev 视觉验收：dark/light toggle 切换时所有 demo + grid 都正确响应。
通过后 plan owner 自己写 retrospection + commit F23。
```

---

## §5 — 严守约束

- ⚠️ **不要 commit / 不要 git add**——dev 视觉验收必须经过 plan owner 才能落 commit
- ⚠️ §0 文件清单**不可超出**——只改 FormItemPage.vue
- ⚠️ **不动 canonical 组件**：如遇 `theme` prop 大小写不接受小写 'dark' / 'light' → STOP 报告，不擅自改 canonical（应在 prompt §4 列为 blocker）
- ⚠️ **不动 docs.css / docs-shell**（F19 已改完）
- ⚠️ **不动 figma-data**（F22 已改完）
- ⚠️ §4 完成报告**必须含 §4.X 完整改动清单段**
