# P10 — DropDownListSelect color fails 调研笔记

> 生成时间：2026-05-22（P9.1 闭环后）
> 来源：`figma-data/normalized/render-verification.report.json` 全表扫描
> 目的：拆分 pickup §3 P10 「~120 per-status border/fill 状态色」成 dispatchable sub-prompts

---

## 总体数字

Dropdown 总 color-related fail = **142 个 field**（rootBorderHex / rootFillHex / textFillHex 三类），跨 Radio / Multi / Operation / Selected types。

按根因聚类：

| Sub | 根因 | 影响 field | 工具 / 风险 |
|---|---|---:|---|
| **P10a** | verifier schema gap — `rootBorderHex` 在无 `border-width` 时仍读 `computed border-color`（= currentColor = text 色）| **~83** | verifier rule 升级（不动 src/），最安全最大杠杆 |
| **P10b** | hover background 缺失 | ~26 | CSS 1 行 `.dropdown-item:hover { background: var(--green-bg) }`，medium 风险 |
| **P10c** | type-aware checked/active 文字色逻辑（Radio checked=brand，Multi checked=default）| ~22 | Vue template + CSS 改 class 绑定，higher 风险，必须 plan owner 小颗粒 |
| 其他 | scattered 单点 / fill direction 反向 | ~11 | 跟 P10b/c 一起清扫 |

合计：83 + 26 + 22 + 11 ≈ 142，与 verifier 数字吻合。

---

## P10a 详情 — rootBorderHex spurious (verifier B 应归类)

### 模式

| 数量 | exp | act | state context |
|---:|---|---|---|
| 22 | None | #f8f8f8 (dark default text) | Dark, Disabled=No, default 状态 |
| 22 | None | #141414 (light default text) | Light, Disabled=No |
| 12 | None | #595959 (dark disabled text) | Dark, Disabled=Yes |
| 12 | None | #cccccc (light disabled text) | Light, Disabled=Yes |
| 8 | None | #299f45 (brand light) | Light, Checked=Yes Active=Yes |
| 7 | None | #2fb54e (brand dark) | Dark, Checked=Yes Active=Yes |

**总 83**，全部 `exp=None`（Figma 无 stroke），`act=current text color`。

### 根因实证

`src/canonical/DropDownListSelect.vue` `.dropdown-item` CSS **未声明任何 `border-*` 属性**。但 verifier 通过 `getComputedStyle(...).borderColor` 读取，CSS 规范：未显式设置 `border-color` 时 fallback = `currentColor`。所以 verifier 报的 `actual` 一直跟踪文字色变化（default / disabled / active 时颜色都对得上）。

**这不是 visual drift**——浏览器渲染时 `border-width: 0`（默认），用户看不到任何边框。Figma 也确认无 stroke。当前 verifier 算法 false positive。

### 同类先例

`docs/internal/divergences/input-html-leaf-no-flex-children-2026-05-21.md`：HTML `<input>` void element gap 92 fail 同样登记为 divergence，verifier 加 `PASS_BY_MODE_SKIP` 规则。本案适用同样模式。

### 推荐修法（P10a）

升级 `figma-data/normalized/render-verification.report.json` 的 verifier 脚本（疑似在 `scripts/` 下），加规则：

```
若 entry actual rootBorderWidth === 0 (or computed border-width === 0) 且 expected stroke = none/empty，则 rootBorderHex 字段记 PASS_BY_MODE_SKIP，不算 FAIL。
```

副产物：登记新 divergence `dropdown-item-no-border-currentcolor-noise-2026-05-22.md`，引 CSS spec 链接 + verifier rule 改动 commit。

预期：FAIL 501 → ~418，field A 1021 → ~938。**最大单次 cleanup，零视觉风险**。

---

## P10b 详情 — hover background missing

### 模式

| 数量 | exp | act | state context |
|---:|---|---|---|
| 13 | #0b2b13 (dark green-bg) | None | Dark, Hover={Yes,No 混合}, Disabled={Yes,No} |
| 13 | #f1fbf3 (light green-bg) | None | Light, 同上 |

### 待澄清

13 个 dark 条目 hover 混 Yes/No 是反常的——Disabled=Yes 也应该没有 hover bg。需要 plan owner 在小颗粒 prompt 前再 split 一次：

- Hover=Yes Disabled=No → 应加 hover bg（CSS 1 行）
- Hover=Yes Disabled=Yes → divergence？Figma 不应在 disabled 加 hover bg
- Hover=No → ❓为什么出现在 fail 里？可能 verifier 在 active 状态独立检查 rootFillHex

需要再跑一次 sub-cluster 才能拆 P10b prompt。

---

## P10c 详情 — type-aware checked/active text color

### 模式

| 数量 | exp | act | state context | 解读 |
|---:|---|---|---|---|
| 7 | #2fb54e (brand dark) | #f8f8f8 (default text) | Dark, Radio/Selected, Checked=Yes Active=No | Radio checked → 应 brand 文字，代码默认色 |
| 7 | #299f45 (brand light) | #141414 | Light 同上 | 同上 |
| 4 | #f8f8f8 (default) | #2fb54e (brand) | Dark, Multi, Checked=Yes Active=Yes | Multi 不应 brand 文字（check 图标已选中），代码错给 brand |
| 4 | #141414 (default) | #299f45 | Light 同上 | 同上 |
| 3 | #2fb54e | #595959 (disabled text) | Dark, Radio Checked=Yes Disabled=Yes | Radio checked + disabled 优先级冲突 |

### 根因实证

`src/canonical/DropDownListSelect.vue`：

- Template line 48-51：class 绑定 `dropdown-item--active` 来自 `item.active` prop，**未绑** `dropdown-item--checked` from `item.checked`
- CSS line 99-102：`.dropdown-item--active { color: var(--brand) }` 不区分 type，所有 type 走同一规则
- Type=Multi 的 visual contract 是 check icon 表达选中，text 保持 default color

### 修法（template + CSS 协同）

1. Template 加 type-aware class：`'dropdown-item--checked': item.checked && type !== 'Multi'`
2. CSS：`.dropdown-item--checked { color: var(--brand) }`，并验证 disabled 优先级（disabled 应覆盖 checked）
3. Multi 保持 check icon 表达，无文字色变化

风险点：与 `.dropdown-item--active` 共存语义可能重复（用户拍板：active 概念是否还需要？还是合并到 checked）。

### 待澄清（必须用户拍板）

- Type=Selected 在 Figma 里是什么？code 没有 'Selected' 这个 ListType union member（[line 5](../../../src/canonical/DropDownListSelect.vue#L5) `'Radio' | 'Multi' | 'Operation List' | 'Sort By'`），但 verifier report 出现。是 axis-impl-map 漏对齐？需查 `figma-data/normalized/axis-implementation-map.json`

---

## 推荐执行顺序

1. **P10a 先做**——verifier rule 升级，~83 cleanup，零视觉风险，最大杠杆
2. **P10c 用户澄清后**——type-aware logic，待答 "Selected" type 问题 + active/checked 语义合并问题
3. **P10b 最后**——sub-cluster 完再拆，~26 cleanup

---

## 不在 P10 范围

- InputBox rootHeight XL 40→100 (80 fail) — Deferred 在 pickup 中
- InputBox rootGap (92 fail) — 已 divergence (`input-html-leaf-no-flex-children-2026-05-21`)
- Select multi-select rootPadding (P11)
- Input XL textarea rootPadding.bottom (P12)
