@teamix-evo/mcp 0.4.0 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +64 -16
- package/dist/cli.js.map +1 -1
- package/dist/data/adr/0001-three-layer-alignment.md +11 -11
- package/dist/data/adr/0005-ui-no-variant.md +4 -4
- package/dist/data/adr/0006-ui-upgrade-no-baseline.md +6 -6
- package/dist/data/adr/0010-design-default-and-variants.md +1 -1
- package/dist/data/adr/0019-project-upgrade-flow.md +13 -13
- package/dist/data/adr/0021-semantic-color-api-unification.md +127 -0
- package/dist/data/adr/0022-preferences-css-boundary.md +75 -0
- package/dist/data/adr/0023-cursor-pointer-explicit-in-component-source.md +70 -0
- package/dist/data/adr/0024-scoped-css-radix-state-conflict.md +99 -0
- package/dist/data/adr/0025-component-props-explicit-declaration.md +145 -0
- package/dist/data/adr/0026-component-level-token-alias.md +107 -0
- package/dist/data/adr/0027-component-visual-token-alignment.md +127 -0
- package/dist/data/adr/0028-ui-component-categorization.md +112 -0
- package/dist/data/adr/0029-input-split-and-prefix-suffix-removal.md +68 -0
- package/dist/data/adr/0030-skill-uni-manager-uplift.md +56 -0
- package/dist/data/adr/0031-skill-templates-decoupling.md +77 -0
- package/dist/data/adr/0032-opentrek-v4.1-brand-token-alignment.md +129 -0
- package/dist/data/adr/0033-entry-skill-global-only-scope.md +64 -0
- package/dist/data/adr/0034-skills-cli-verb-alignment.md +61 -0
- package/dist/data/adr/0035-skills-update-scope-and-lock-gates.md +69 -0
- package/dist/data/adr/0036-ui-v2-shadcn-baseline-rebuild.md +146 -0
- package/dist/data/adr/0037-filter-bar-composable-architecture.md +426 -0
- package/dist/data/adr/0038-create-agents-md-skill-trigger-fallback.md +99 -0
- package/dist/data/adr/0040-component-source-layer-upgrade-flow.md +104 -0
- package/dist/data/adr/README.md +41 -28
- package/dist/index.js +64 -16
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 0001. UI 组件研发三层对齐:能力 = shadcn ∪ antd / 理念 = design / 工程 = shadcn
|
|
2
2
|
|
|
3
|
-
- **Status**:
|
|
3
|
+
- **Status**: Superseded by [0036](./0036-ui-v2-shadcn-baseline-rebuild.md)
|
|
4
4
|
- **Date**: 2026-05-15
|
|
5
5
|
- **Region**: 0001–0099 工程哲学
|
|
6
6
|
- **Related ADR**: [0005 UI 包不分 variant](0005-ui-no-variant.md) / [0014 ui/biz-ui/templates 三层](0014-ui-biz-ui-templates-tier.md)(本 ADR 在三个粒度上落实)
|
|
@@ -15,21 +15,21 @@ teamix-evo 的 ui 包面对一个上游生态的取舍问题:**shadcn/ui** 与 *
|
|
|
15
15
|
|
|
16
16
|
## Options Considered
|
|
17
17
|
|
|
18
|
-
| 选项
|
|
19
|
-
|
|
|
20
|
-
| 全盘对齐 shadcn
|
|
21
|
-
| 全盘对齐 antd
|
|
22
|
-
| **三层切分对齐(本决策)** | 各取所长,覆盖最广
|
|
18
|
+
| 选项 | 优点 | 缺点 |
|
|
19
|
+
| ------------------------ | ------------------------ | --------------------------------------------------------------- |
|
|
20
|
+
| 全盘对齐 shadcn | 工程一致、生态成熟 | antd 用户惯用的能力(loading / icon prop / shape / block 等)缺失 |
|
|
21
|
+
| 全盘对齐 antd | 能力完整、中后台用户熟悉 | 工程笨重(less + ConfigProvider 运行时主题),与源码注入模式不兼容 |
|
|
22
|
+
| **三层切分对齐(本决策)** | 各取所长,覆盖最广 | 每新增组件需做并集对照表(维护成本) |
|
|
23
23
|
|
|
24
24
|
## Decision
|
|
25
25
|
|
|
26
26
|
UI 组件研发的对齐规则按三层切分,**任何冲突时三层切分优先于其它细则**:
|
|
27
27
|
|
|
28
|
-
| 维度
|
|
29
|
-
|
|
|
30
|
-
| **能力 / 功能**
|
|
31
|
-
| **设计理念**
|
|
32
|
-
| **代码实现 / 部署 / 规范** | **shadcn**
|
|
28
|
+
| 维度 | 对齐对象 | 含义 |
|
|
29
|
+
| -------------------------- | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
30
|
+
| **能力 / 功能** | **shadcn ∪ antd 的合集** | shadcn 缺什么、antd 有什么,补;反之亦然。**做并集,不做交集** |
|
|
31
|
+
| **设计理念** | **`@teamix-evo/design` 的 OpenTrek 体系** | 视觉 / 间距 / 圆角 / 字号 / 阴影 / 动效 / 交互预期 / AI 生成纪律全部走 design,**不参照 antd 视觉,也不参照 shadcn 视觉** |
|
|
32
|
+
| **代码实现 / 部署 / 规范** | **shadcn** | 文件结构、源码注入分发、cva 范式、forwardRef + Slot、TypeScript 写法、命名风格、registryDependencies 思想全部对齐 shadcn,**不照搬 antd 的运行时主题 / less / 样式封装方式** |
|
|
33
33
|
|
|
34
34
|
简记:**能力做并集,理念跟 design,工程跟 shadcn**。
|
|
35
35
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 0005. UI 包不分 variant,所有视觉差异通过 design tokens 实现
|
|
2
2
|
|
|
3
|
-
- **Status**:
|
|
3
|
+
- **Status**: Superseded by [0036](./0036-ui-v2-shadcn-baseline-rebuild.md)
|
|
4
4
|
- **Date**: 2026-05-14
|
|
5
5
|
- **Region**: 0100–0999 协议与工具
|
|
6
6
|
- **Related ADR**: [0001 三层对齐](0001-three-layer-alignment.md) / [0006 UI 升级机制无 baseline](0006-ui-upgrade-no-baseline.md) / [0010 design 默认+变体](0010-design-default-and-variants.md) / [0014 ui/biz-ui/templates 三层](0014-ui-biz-ui-templates-tier.md)
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
|
|
25
25
|
## Options Considered
|
|
26
26
|
|
|
27
|
-
| 选项
|
|
28
|
-
|
|
|
29
|
-
| UI 按 variant 切分
|
|
27
|
+
| 选项 | 优点 | 缺点 |
|
|
28
|
+
| ------------------------------------ | -------------------------------------------------- | ------------------------------------------------------- |
|
|
29
|
+
| UI 按 variant 切分 | 单 variant 内组件可深度定制视觉 | 维护成本随 variant 数量线性增长;同步问题 |
|
|
30
30
|
| **UI 不分 variant,靠 token(本决策)** | 一套组件吃所有 variant;切换 variant 仅改 design 包 | 强依赖 semantic 命名稳定;variant 间语义集合必须严格对齐 |
|
|
31
31
|
|
|
32
32
|
## Decision
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 0006. UI 升级机制不预埋 baseline,依靠 AI + skill 做语义合并
|
|
2
2
|
|
|
3
|
-
- **Status**:
|
|
3
|
+
- **Status**: Superseded by [0036](./0036-ui-v2-shadcn-baseline-rebuild.md)
|
|
4
4
|
- **Date**: 2026-05-14
|
|
5
5
|
- **Region**: 0100–0999 协议与工具
|
|
6
6
|
- **Related ADR**: [0003 资源升级三态语义](0003-update-strategy-tri-state.md) / [0005 UI 包不分 variant](0005-ui-no-variant.md) / [0013 Skills source-mirror 模型](0013-skills-source-mirror.md)(skills upgrade 同型动作:同样无 baseline,靠语义合并 + skill 引导)
|
|
@@ -20,11 +20,11 @@ UI 包采用源码注入分发(`teamix-evo ui add <id>` 把组件源码写到业
|
|
|
20
20
|
|
|
21
21
|
## Options Considered
|
|
22
22
|
|
|
23
|
-
| 选项
|
|
24
|
-
|
|
|
25
|
-
| 三方合并 + baseline
|
|
26
|
-
| 完全覆盖
|
|
27
|
-
| **AI 语义合并 + skill 引导(本决策)** | 不污染、简化、AI 兜底语义判断 | 比三方合并精确度差,大改时仍需人介入
|
|
23
|
+
| 选项 | 优点 | 缺点 |
|
|
24
|
+
| ------------------------------------ | ----------------------------- | ---------------------------------------------------------------- |
|
|
25
|
+
| 三方合并 + baseline | 精确 | baseline 必须随 ui add 一起落地到业务项目(污染),且需历史快照管理 |
|
|
26
|
+
| 完全覆盖 | 简单 | 丢用户定制 |
|
|
27
|
+
| **AI 语义合并 + skill 引导(本决策)** | 不污染、简化、AI 兜底语义判断 | 比三方合并精确度差,大改时仍需人介入 |
|
|
28
28
|
|
|
29
29
|
## Decision
|
|
30
30
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 0010. `@teamix-evo/design` 采用 `default + variants/<name>/` 模型,工程默认与业务变体彻底解耦
|
|
2
2
|
|
|
3
|
-
- **Status**:
|
|
3
|
+
- **Status**: Superseded by [0036](./0036-ui-v2-shadcn-baseline-rebuild.md)
|
|
4
4
|
- **Date**: 2026-05-18
|
|
5
5
|
- **Region**: 0100–0999 协议与工具
|
|
6
6
|
- **Related ADR**: [0001 三层对齐](0001-three-layer-alignment.md) / [0005 UI 不分 variant](0005-ui-no-variant.md) / [0007 治理文档放根](0007-governance-docs-at-root.md) / [0008 ESLint 视觉规则 warn 基线](0008-eslint-visual-rules-warn-baseline.md) / [0014 ui/biz-ui/templates 三层](0014-ui-biz-ui-templates-tier.md)
|
|
@@ -134,19 +134,19 @@ design 包改 token 名(如 `--color-fg-muted` → `--color-text-muted`),`design
|
|
|
134
134
|
|
|
135
135
|
## Implementation status
|
|
136
136
|
|
|
137
|
-
- **本 ADR
|
|
138
|
-
-
|
|
139
|
-
-
|
|
140
|
-
1. lock schema v2 + migration
|
|
141
|
-
2. snapshot 模块 + `restore`
|
|
142
|
-
3. managed-region
|
|
143
|
-
4. `
|
|
144
|
-
5. `teamix-evo init
|
|
145
|
-
6. `teamix-evo update` orchestrator
|
|
146
|
-
7. `
|
|
147
|
-
8. token rename hint 写入 + skill `teamix-evo-upgrade`
|
|
148
|
-
9. W1.4 tokens
|
|
149
|
-
10. 文档站 5 命令导引 +
|
|
137
|
+
- **本 ADR**:方向锁定 + **D1 全量落地完成(v0.8 发版批次)**
|
|
138
|
+
- **当前版本**:v0.8 发版周期
|
|
139
|
+
- **拆解任务**:
|
|
140
|
+
1. ✅ lock schema v2 + migration(`project-config-schema-v2`)
|
|
141
|
+
2. ✅ snapshot 模块 + `restore` 命令(`snapshot-module` + `restore-command`)
|
|
142
|
+
3. ✅ managed-region 解析器(`registry-split-managed-regions`)
|
|
143
|
+
4. ✅ `tokens update` 真实现 + 三态分流(`tokens-update-tristate-dispatch`)
|
|
144
|
+
5. ✅ `teamix-evo init`(已有工程接入;6 类冲突 + wizard + partial 恢复)
|
|
145
|
+
6. ✅ `teamix-evo update` orchestrator(`add-update-command`)
|
|
146
|
+
7. ✅ `teamix-evo switch` + variant migration(`cli-switch-command`)
|
|
147
|
+
8. ✅ token rename hint 写入 + skill `teamix-evo-upgrade`(`tokens-rename-hint` + `skills-add-upgrade-skill`)
|
|
148
|
+
9. ✅ W1.4 tokens 提层兼容迁移(`cli-init-tokens-migrate`)
|
|
149
|
+
10. ✅ 文档站 5 命令导引 + TrekClaw e2e example(`packages/docs/docs/cli/index.md` + `example-trekclaw.md`)
|
|
150
150
|
|
|
151
151
|
## Source
|
|
152
152
|
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# 0021. 语义色 API 统一治理(双 prop:`variant`(形态) + `color`(颜色))
|
|
2
|
+
|
|
3
|
+
- **Status**: Accepted
|
|
4
|
+
- **Date**: 2026-05-29
|
|
5
|
+
- **Region**: 0001–0099 工程哲学
|
|
6
|
+
- **Related ADR**: [0005](./0005-ui-no-variant.md) ui 不感知 variant / [0010](./0010-design-default-and-variants.md) design default-and-variants / [0008](./0008-eslint-visual-rules-warn-baseline.md) eslint visual rules
|
|
7
|
+
|
|
8
|
+
## Context
|
|
9
|
+
|
|
10
|
+
`@teamix-evo/ui` 在 antd ∪ shadcn 并集策略下逐步落地 ~90 个组件。引入"语义色"能力时,各组件按各自源头沿用了不同的 prop 名与枚举值,出现两类不一致:
|
|
11
|
+
|
|
12
|
+
**一、prop 名混用(5 种)**
|
|
13
|
+
|
|
14
|
+
| 当前 prop 名 | 出处 | 组件示例 |
|
|
15
|
+
| ------------ | ---------------- | ----------------------------------------------- |
|
|
16
|
+
| `color` | antd | Tag / PageHeaderDataItem / Timeline |
|
|
17
|
+
| `type` | antd | Typography Text / Alert / Notification |
|
|
18
|
+
| `status` | antd | Result / Progress / Steps / Upload / TimePicker |
|
|
19
|
+
| `tone` | shadcn / Polaris | Spinner / Icon |
|
|
20
|
+
| `variant` | shadcn | Button / Badge |
|
|
21
|
+
|
|
22
|
+
**二、"错误"语义同义词(5 种)**
|
|
23
|
+
|
|
24
|
+
| 字面值 | 出处 | 底层 token |
|
|
25
|
+
| ----------------------- | ---------------------------------------------------------- | --------------------------- |
|
|
26
|
+
| `error` | antd Tag/Alert/Result/Notification/Steps/Upload/TimePicker | `--destructive`(API 层翻译) |
|
|
27
|
+
| `danger` | antd Typography Text | `--destructive` |
|
|
28
|
+
| `exception` | antd Progress | `--destructive` |
|
|
29
|
+
| `destructive` | shadcn Button/Badge/Spinner/Icon | `--destructive`(直对) |
|
|
30
|
+
| `secondary`(语义"次级") | antd Typography Text | `--muted` |
|
|
31
|
+
|
|
32
|
+
**底层 token 只有一套** —— shadcn 命名(`--destructive` / `--muted` / `--success` / `--warning`,**没有** `--error` / `--info` / `--danger` / `--exception`)。这意味着 antd 命名的字面值在 className 层一律要做"业务话术 → token 字面值"的翻译,引入了不必要的认知层。
|
|
33
|
+
|
|
34
|
+
**关于 prop 命名 `tone` 的回退**:本 ADR 初版(2026-05-29 上午)曾采用 Polaris 的 `tone`,落地一轮后发现:`tone` 在业界几乎是 Polaris 孤本(MUI / antd / Mantine / Chakra 主流派均用 `color`,shadcn 用 `variant`),且不在 antd 消费方的认知词典内。**本次正式版回退到 `color`** —— 它是业界最大公约数,对 antd 用户零迁移成本,字面值仍走 shadcn token(`destructive` / `muted`)以保持与底层 OpenTrek tokens 单一权威源对齐。
|
|
35
|
+
|
|
36
|
+
## Options Considered
|
|
37
|
+
|
|
38
|
+
| 选项 | 优点 | 缺点 |
|
|
39
|
+
| ----------------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------- |
|
|
40
|
+
| A. 单 `variant` 笛卡尔展开(纯 shadcn) | 与 shadcn Button/Badge 完全同构 | `outline-success` / `solid-destructive` / ... 笛卡尔积爆炸,Tag/Icon/Timeline 形态 ⊥ 颜色场景 API 体验差 |
|
|
41
|
+
| B. **`variant`(形态) + `color`(颜色) 双 prop(本 ADR 采纳)** | 形态轴与颜色轴正交;`color` 是业界最大公约数;字面值仍走 token | Spinner/Icon 已落地 `tone` 需要二次改名(范围已知,小) |
|
|
42
|
+
| C. 保留 `tone`(初版 ADR) | Spinner/Icon 不动 | Polaris 孤本,与 shadcn 基线 prop 命名习惯不一致(shadcn 一律 `variant`,扩展派一律 `color`) |
|
|
43
|
+
| D. 全仓 antd 风:`type` / `color` 双轨 | 与 antd 消费习惯零摩擦 | 字面值脱离 token 单一权威;`destructive` 表达"破坏性操作"是 shadcn 视觉语义,优于 antd 偏运行态的 `error` |
|
|
44
|
+
|
|
45
|
+
## Decision
|
|
46
|
+
|
|
47
|
+
### 一、prop 二分:`variant`(形态) + `color`(颜色)
|
|
48
|
+
|
|
49
|
+
| 作用面 | prop 名 | 取值 | 适用组件 |
|
|
50
|
+
| ------ | ------------- | ------------------------------------------ | ------------------------------------------------------------------ |
|
|
51
|
+
| 形态 | **`variant`** | `solid` / `outline` / `ghost` 等(组件自定) | 形态决定整体外观档位的组件:Button / Badge / Tag / Alert |
|
|
52
|
+
| 颜色 | **`color`** | 6 档标准枚举(见下) | 所有需要语义色的组件:Tag / Icon / Spinner / Timeline / Alert / ... |
|
|
53
|
+
|
|
54
|
+
形态 ⊥ 颜色,正交组合。例:`<Tag variant="outline" color="success">` / `<Alert variant="solid" color="warning">`。组件若不需要形态轴(如 Icon / Spinner),仅暴露 `color`。
|
|
55
|
+
|
|
56
|
+
**业务状态机** prop(`status`,如 Upload `status="uploading|done|error"`、Result `status`)不属于本 ADR 治理范围 —— 它表达业务状态不表达视觉颜色,各组件按行业惯例自然落地。但若某 `status` 取值仅作用于颜色(如 Progress `status="exception"` 只是变红,无状态机语义),则统一并入 `color="destructive"`。
|
|
57
|
+
|
|
58
|
+
### 二、`color` 标准 6 档枚举
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
default | muted | primary | success | warning | destructive
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
- 字面值与 OpenTrek tokens 一一对应:`text-foreground` / `text-muted-foreground` / `text-primary` / `text-success` / `text-warning` / `text-destructive`
|
|
65
|
+
- **不收 `info`**:见 ADR 0010 与决策记忆「语义色标准档位不包含 info 色」 —— Tag/Alert 等组件中信息类展示用 `primary` 表达,或通过 typography 层级区分。如确需信息色,在 design 哲学层单独论证,不进基础 token 集
|
|
66
|
+
- **不收 `error` / `danger` / `exception`**:统一 `destructive`(对齐 shadcn 与 token)
|
|
67
|
+
- **不收 `secondary`** 作为颜色枚举:统一 `muted`(对齐 token `--muted`)
|
|
68
|
+
- **填充背景类组件可省略 `muted`** —— 实色背景下 `default` 本身就是次级灰,无 `muted` 区分点(如 Tag、PageHeaderDataItem 实施为 5 档)
|
|
69
|
+
|
|
70
|
+
### 三、ESLint 规则配套
|
|
71
|
+
|
|
72
|
+
新增 `teamix-evo/no-antd-color-alias`(packages/eslint-config),禁用以下字面值:
|
|
73
|
+
|
|
74
|
+
- `error` / `danger` / `exception`(在 `color` / `tone` / `type` 上下文)
|
|
75
|
+
- `secondary` 作为颜色枚举(在 typography 上下文)
|
|
76
|
+
- `info`(在 `color` 上下文,与 token 集裁剪联动)
|
|
77
|
+
|
|
78
|
+
并禁用 prop 名 `tone` / `type` / `color` 的混用 —— 颜色一律 `color`。
|
|
79
|
+
|
|
80
|
+
## Consequences
|
|
81
|
+
|
|
82
|
+
- **Positive**:
|
|
83
|
+
- prop 命名取业界最大公约数(MUI/antd/Mantine/Chakra 皆用 `color`),antd 消费方零迁移成本
|
|
84
|
+
- 字面值与底层 OpenTrek tokens 直接对应,无认知翻译层
|
|
85
|
+
- 形态 ⊥ 颜色的双 prop 设计满足 Tag/Alert 等组件"outline + success"的真实组合需求,无 shadcn 单 `variant` 的笛卡尔积爆炸问题
|
|
86
|
+
- ESLint 可执行,新组件强制走规范
|
|
87
|
+
- **Negative**:
|
|
88
|
+
- 7 个组件 break change(Icon / Spinner / Tag / PageHeaderDataItem / Timeline / Typography Text / Alert / Notification),走 changeset major + migration guide
|
|
89
|
+
- 砍 `info` 后 Alert / Notification 的"提示"色档位需用 `primary` 或层级表达,与 antd Alert 4 档(info/success/warning/error)有一档差异
|
|
90
|
+
- **Trade-off**:
|
|
91
|
+
- 放弃 shadcn `variant` 单 prop 的极简,换取形态/颜色正交的实用主义(社区扩展 shadcn 的主流路径)
|
|
92
|
+
- 放弃 antd `type`/`color` 双轨与 `error` 字面值的零迁移,换取与底层 token 的单一权威源对齐
|
|
93
|
+
|
|
94
|
+
## Source
|
|
95
|
+
|
|
96
|
+
- 触发对话:Icon v0.1 API 收敛后,与 Tag 的 `color="error"` 不对齐讨论(2026-05-29 上午)
|
|
97
|
+
- 二次回退触发:用户对 `tone` 命名的业界流行度质疑(2026-05-29 下午)—— 实测 `tone` 仅 Polaris 一家,业界主流是 `color` / `variant`,本 ADR 据此从 `tone` 回退到 `color`
|
|
98
|
+
- 关联记忆:`shadcn基线项目语义色双prop命名决策` / `语义色标准档位不包含info色的决策` / `shadcn 新组件代码规范`
|
|
99
|
+
- 关联组件:Icon / Spinner / Button / Badge / Tag(本 ADR 立项前已落地的混合命名,本次统一)
|
|
100
|
+
|
|
101
|
+
## Addendum: Tag `status` 8 档枚举(2026-06)
|
|
102
|
+
|
|
103
|
+
Tag 在原 `variant`(形态) + `color`(语义色 5 档)正交体系基础上,新增 `variant='status'` 形态 + `status` prop 表达**业务状态机**轴(参考 teamix-pro `@ali/teamix-status-tag` 与 antd Upload/Result 的 `status` prop 习惯)。
|
|
104
|
+
|
|
105
|
+
**8 档命名与 token 映射**
|
|
106
|
+
|
|
107
|
+
| `status` | 中文 | 底层 token | 默认图标(`showIcon`) |
|
|
108
|
+
| --------- | ------ | ---------------------------- | ------------------------------ |
|
|
109
|
+
| `default` | 默认 | `--color-muted-foreground` | `Circle` |
|
|
110
|
+
| `success` | 成功 | `--color-success` | `CheckCircle2` |
|
|
111
|
+
| `running` | 运行中 | `--color-primary` | `PlayCircle` |
|
|
112
|
+
| `error` | 失败 | `--color-destructive` | `XCircle` |
|
|
113
|
+
| `warning` | 提醒 | `--color-warning` | `AlertCircle` |
|
|
114
|
+
| `pause` | 暂停 | `--color-muted-foreground` | `PauseCircle` |
|
|
115
|
+
| `loading` | 加载中 | `--color-muted-foreground` | `Loader2`(自带 `animate-spin`) |
|
|
116
|
+
| `help` | 帮助 | **新增 `--color-help`** 4 档 | `HelpCircle` |
|
|
117
|
+
|
|
118
|
+
**与本 ADR 主体的关系**
|
|
119
|
+
|
|
120
|
+
- `status` 是**业务状态机轴**(本 ADR §一明确不治理),非颜色枚举 —— 8 档名称直接采纳运行态业务话术(`running` / `pause` / `loading`),**不与 `color` 5 档同名约束**
|
|
121
|
+
- 例外:`status='error'` 与 `color='destructive'` 在底层共用 `--color-destructive` token —— 业务状态机轴允许用 `error` 字面值(antd 习惯,运行态自然语义),颜色轴仍只接受 `destructive`(本 ADR 主体规则不变)
|
|
122
|
+
- `status='running'` 与 `color='primary'` 共用 `--color-primary` —— 同理,语义独立但底层映射对齐
|
|
123
|
+
- `variant='status'` 与 `color` / `palette` / 自定义 `icon` **互斥**:状态形态由 `status` 闭环驱动颜色与图标,无外部颜色注入
|
|
124
|
+
|
|
125
|
+
**Token 增量**
|
|
126
|
+
|
|
127
|
+
仅 `--color-help` 一档新增(双变体 OpenTrek + uni-manager 同步),其余 token 均已存在。详见同期 changeset `tag-status-variant`。
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# 0022. preferences.css 边界约束:仅承载 shadcn 装机偏好,禁止组件级 utility / token alias
|
|
2
|
+
|
|
3
|
+
- **Status**: Superseded by [ADR 0023](0023-cursor-pointer-explicit-in-component-source.md)(2026-06-01)
|
|
4
|
+
- **Date**: 2026-05-31
|
|
5
|
+
- **Region**: 0100–0999 协议与工具
|
|
6
|
+
- **Related ADR**: [ADR 0020](0020-design-to-tokens-skill-fusion.md)(§8 preferences.css 归属决策)
|
|
7
|
+
|
|
8
|
+
> **本 ADR 已被 [ADR 0023](0023-cursor-pointer-explicit-in-component-source.md) 取代**:`preferences.css` 文件已整体删除,可交互元素的 `cursor: pointer` 改为组件源码内显式声明,`<input type="search">` 原生 clear 屏蔽规则下沉到各 globals.css 模板。原 ADR 0022 关于"preferences.css 边界"的约束因文件不复存在而失效。
|
|
9
|
+
|
|
10
|
+
## Context
|
|
11
|
+
|
|
12
|
+
[ADR 0020 §8](0020-design-to-tokens-skill-fusion.md) 把 `preferences.css` 从 tokens 包搬到了 `packages/ui/src/preferences.css`,并明确它"随 `ui init` 装机,生命周期与 UI 组件绑定"。但该 ADR 只规定了**文件归属**,没有规定**文件内容边界**。
|
|
13
|
+
|
|
14
|
+
实操中出现了把本不属于 preferences 范畴的内容塞进来的冲动:
|
|
15
|
+
|
|
16
|
+
- **组件级 utility**:当某个组件需要消费 `var(--xxx)` token 又被 `no-arbitrary-tw-value` lint 拦截时,有人会在 preferences.css 里 `@utility rounded-btn { border-radius: var(--radius-button); }` 给组件造一个 first-class Tailwind utility 名
|
|
17
|
+
- **token alias**:把组件级 token 重命名暴露成另一个名字方便 cva 引用
|
|
18
|
+
|
|
19
|
+
这两类内容会把 preferences.css 慢慢变成"杂物间",侵蚀其单一职责。更严重的是,它们让消费方业务工程在 `ui init` 装机时被动接收了**不属于"偏好"概念的样式工件**,违反"装机内容用户可理解 / 可拒绝"的最小惊讶原则。
|
|
20
|
+
|
|
21
|
+
且这类越权写法掩盖了**真正应该做的事**:对于消费 token 的视觉属性(圆角 / 颜色 / 间距 等),优先用 **Tailwind v4 标准 namespace** 对应的 utility(`rounded-sm/md/lg/xl/2xl` ← `--radius-sm/md/lg/xl/2xl`、`bg-primary` ← `--color-primary` 等),这些在多包 `@import` 场景下是唯一可靠地被 Tailwind v4 识别并派生为 utility 的 token 命名。**非标准 namespace token**(如 `--radius-button`/`--radius-dialog` 等语义型别名) 在多包 `@import` 下 **不会被自动派生 utility**(实测 dev server 编译产物中 `.rounded-button { ... }` 规则不生成),如果代码跳过标准档写的 `rounded-button` 会静默失效(回退到浏览器默认 8px,与任何主题无关) —— 这是项目已记在案的 pitfall(见 “Tailwind 自定义 utility 在分层引入模式下不生效” 记忆)。
|
|
22
|
+
|
|
23
|
+
## Options Considered
|
|
24
|
+
|
|
25
|
+
| 选项 | 优点 | 缺点 |
|
|
26
|
+
| -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
|
27
|
+
| A. 允许 preferences.css 承载组件级 utility / token alias | 改组件时不需要碰 tokens 包,所有"工程性补丁"集中 | 文件职责漂移;装机方被动接收非偏好工件;掩盖 Tailwind v4 token namespace 自动派生能力;违反 ADR 0020 §8 单一职责 |
|
|
28
|
+
| B. **preferences.css 严格只放 shadcn 装机偏好** | 单一职责清晰;消费方装机内容可解释;倒逼正确使用 Tailwind v4 `@theme` 派生 / 组件内 inline style / 真正必要时回 tokens 包加 token | 个别极端场景(token 在 `@theme` 外/Tailwind 无自动 namespace 的属性如 `height`)需要走 inline style 或额外讨论,无 escape hatch |
|
|
29
|
+
|
|
30
|
+
## Decision
|
|
31
|
+
|
|
32
|
+
**`packages/ui/src/preferences.css` 严格只承载下列内容,其它一律禁止:**
|
|
33
|
+
|
|
34
|
+
1. **shadcn CLI init prompts 对应的全局偏好**(当前唯一一类):
|
|
35
|
+
- `Use pointer on buttons` → `button:not(:disabled) { cursor: pointer }`
|
|
36
|
+
- 未来 shadcn 新增 init prompts(如 `Use system font` / `Use rounded corners` 等)按需追加
|
|
37
|
+
2. **跨组件的全局 base layer 重置**(若 shadcn 上游 globals.css 新增,且属于装机偏好范畴)
|
|
38
|
+
|
|
39
|
+
**明确禁止**:
|
|
40
|
+
|
|
41
|
+
- ❌ 组件级 `@utility` 声明(如 `@utility rounded-btn`)
|
|
42
|
+
- ❌ token alias / 重命名(如 `--btn-radius: var(--radius-button)`)
|
|
43
|
+
- ❌ 单组件的 base 样式补丁
|
|
44
|
+
- ❌ 任何 `.foo-bar { ... }` 形态的具名 class 规则
|
|
45
|
+
- ❌ 与单一组件强相关的修复样式(应放回组件源码或 tokens)
|
|
46
|
+
|
|
47
|
+
**正确替代路径**:
|
|
48
|
+
|
|
49
|
+
| 需求 | 正确路径 |
|
|
50
|
+
| --------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
51
|
+
| 组件消费 token 圆角/颜色/间距/字号 | **优先**用 Tailwind v4 标准 namespace utility(`rounded-md` / `bg-primary` / `text-sm` 等),它们稳定派生且能被主题 `[data-theme]` 覆盖生效。**禁止**期望非标准 namespace token(如 `--radius-button`) 被 Tailwind v4 自动派生 utility —— 在多包 @import 场景下不可靠 |
|
|
52
|
+
| 某组件跨主题落在不同标准档上(如 button uni=2px=md / opentrek=8px=lg) | 三选一:(a) 都拢到同一标准档,接受其中一主题偏离设计意图(推荐最简单);(b) 在 tokens 包加显式 `@utility component-x { ... }` 注册,与 token 同源;(c) 组件内 inline style |
|
|
53
|
+
| 组件需要 Tailwind v4 无自动 namespace 的属性(如 `height: var(--xxx)`) | 组件内 inline `style={{ height: 'var(--xxx)' }}`,或评估是否真有必要(优先回退到 Tailwind 标准刻度 `h-6` / `h-8`) |
|
|
54
|
+
| 跨组件复用的语义槽(色/圆角/层级/间距) | 在 tokens 包对应 variant 的 `theme.css` `@theme {}` 块新增 token,所有组件共享 |
|
|
55
|
+
| ESLint `no-arbitrary-tw-value` 拦截 `[var(--xxx)]` 写法 | 这是规则在提示“你应该对齐标准 namespace utility,而不是任意值”。正确做法是换用现成标准 utility(`rounded-md`/`rounded-lg`等),**不是**在 preferences.css 造 utility 绕开 lint,也**不是**期望组件级别名 token 自动派生 utility |
|
|
56
|
+
|
|
57
|
+
## Consequences
|
|
58
|
+
|
|
59
|
+
- **Positive**:
|
|
60
|
+
- preferences.css 单一职责清晰,装机方业务工程能解释“这个文件为什么必装”;
|
|
61
|
+
- 明确“Tailwind 标准 namespace 优先”原则,避免将来重蹈“期望组件级别名 token 自动派生 utility”的坑;
|
|
62
|
+
- 新组件接入时,工程师必须先回答“我消费的 token 是否能拢到 Tailwind 标准档”——而不是绕路打补丁。
|
|
63
|
+
- **Negative**:
|
|
64
|
+
- 个别属性(如 `height`)在 Tailwind v4 没有自动 namespace,极端场景下组件需要 inline style,无 utility 可写;
|
|
65
|
+
- 历史技术债清单产生:`dialog.tsx` / `alert-dialog.tsx` 仍使用 `rounded-[var(--radius-dialog)]` 任意值写法,应改为 `rounded-2xl`(v4 默认 `--radius-2xl: 1rem = 16px`,与 `--radius-dialog` 一致)或 `rounded-lg` 等标准 namespace utility;那些跨主题反映不一致的语义 token(`--radius-dialog`/`--radius-tag`) 需在 tokens 包额外配 `@utility` 显式注册。
|
|
66
|
+
- **Trade-off**:
|
|
67
|
+
- 为了保持 preferences.css 的**装机偏好层**单一身份,放弃"集中工程补丁"的便利性,容忍 token 体系自身演进时的小阵痛。
|
|
68
|
+
|
|
69
|
+
## Source
|
|
70
|
+
|
|
71
|
+
- 2026-05-31 Button MVP 优化对话第一轮:用户驳回“在 preferences.css 加 `@utility rounded-btn`”方案,提出“圆角应该写进 tokens”。
|
|
72
|
+
- 2026-05-31 Button MVP 优化对话第二轮(圆角仍是 8px 的 bug 调查):追溯发现 `.rounded-button` utility 在 dev server 实时编译的 CSS 产物中完全**没有生成**,证实 Tailwind v4 在多包 `@import` 场景下不会为非标准 namespace token 自动派生 utility;修正本 ADR 原先错误的“自动派生”假设,明确优先使用 Tailwind 标准 namespace utility。Button 最终选择 A1 方案:`rounded-md`(消费 `--radius-md`) + 删除 `--radius-button` token。
|
|
73
|
+
- [ADR 0020 §8](0020-design-to-tokens-skill-fusion.md) preferences.css 文件归属决策(本 ADR 是其内容边界补丁)
|
|
74
|
+
- Common pitfall 记忆:“Tailwind 自定义 utility 在分层引入模式下不生效” —— 本 ADR 是同一类问题在 `@theme namespace 派生` 路径上的重复验证。
|
|
75
|
+
- Tailwind v4 文档:`@theme` namespace 推导规则在单入口文件中可靠,在多层 `@import` 中不保证为语义型别名 token 派生 utility(仅保证标准档 `sm/md/lg/xl/2xl/3xl/full/none`)。
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# 0023. 可交互样式 `cursor: pointer` 由组件源码显式声明,移除全局 `preferences.css`
|
|
2
|
+
|
|
3
|
+
- **Status**: Accepted
|
|
4
|
+
- **Date**: 2026-06-01
|
|
5
|
+
- **Region**: 0100–0999 协议与工具
|
|
6
|
+
- **Supersedes**: [ADR 0020 §8](0020-design-to-tokens-skill-fusion.md)(preferences.css 归属决策)、[ADR 0022](0022-preferences-css-boundary.md)(preferences.css 边界约束)
|
|
7
|
+
|
|
8
|
+
## Context
|
|
9
|
+
|
|
10
|
+
ADR 0020 §8 把 `preferences.css` 从 tokens 包搬到 `@teamix-evo/ui/src/preferences.css`,作为"shadcn 装机偏好"统一承载 `cursor: pointer`(可交互元素)与 `<input type="search">` 浏览器原生 clear 按钮屏蔽两类全局规则,通过 `teamix-evo ui init` 部署到消费方 `src/preferences.css`。ADR 0022 给该文件加了"严格只承载装机偏好,禁止组件级 utility / token alias"的边界。
|
|
11
|
+
|
|
12
|
+
W3 选择类波次中暴露了这个架构的内在矛盾:
|
|
13
|
+
|
|
14
|
+
1. **shadcn 老默认在组件 cva 里硬编码 `cursor-default`**(`Command` / `DropdownMenu` / `Menubar` / `ContextMenu`),因 Tailwind utility class 优先级高于 `preferences.css` 的属性选择器(`[role='option']:not(:disabled)`),**全局规则被组件类静默覆盖** — Select 弹层选项无手型即此 bug
|
|
15
|
+
2. **修法只有两条**:(a) 移除组件里的 `cursor-default` + 让全局规则生效;(b) 在组件里**显式**写 `cursor-pointer` + 让全局规则失去意义
|
|
16
|
+
3. **维护负担两边并存**:不论修法 a 还是 b,以后每加一个新组件都要记得"组件里别写 `cursor-default`"或"组件里要写 `cursor-pointer`",但**没有 ESLint 规则保护**(规则会让"全局兜底 + 组件覆盖"两侧反复打架,无法静态判定)
|
|
17
|
+
4. **隐性行为难调试**:消费方业务工程发现某个 `<button>` 没手型,要排查"是 preferences.css 没装、还是组件类压住了、还是 disabled 状态对了"三层
|
|
18
|
+
|
|
19
|
+
更深的问题:`preferences.css` 这一全局文件本身**让消费方装机内容多了一份非显式工件**,违反"装机内容用户可理解 / 可拒绝"的最小惊讶原则(ADR 0022 主张过同样精神)。当组件源码已经能 / 应该自带交互样式时,全局文件失去了存在理由。
|
|
20
|
+
|
|
21
|
+
## Options Considered
|
|
22
|
+
|
|
23
|
+
| 选项 | 优点 | 缺点 |
|
|
24
|
+
| --- | --- | --- |
|
|
25
|
+
| A. 保留 `preferences.css` + 修组件里所有 `cursor-default` | 改动量小(已修 4 个 menu 组件) | "全局兜底 + 组件不冲突"靠纪律,无静态保护;新增组件易踩同坑;`preferences.css` 仍是消费方装机的隐性工件 |
|
|
26
|
+
| B. **删除 `preferences.css` + 组件源码显式声明 `cursor-pointer`** | 单一来源,组件自闭环;消费方装机内容更轻;全 lint / typecheck 友好;新组件由 ADR + 设计 skill checklist 强制覆盖 | 需要批量给 ~20 个组件加 `cursor-pointer`(一次性) |
|
|
27
|
+
|
|
28
|
+
## Decision
|
|
29
|
+
|
|
30
|
+
**采纳选项 B**:
|
|
31
|
+
|
|
32
|
+
1. **删除 `packages/ui/src/preferences.css`** 文件
|
|
33
|
+
2. **CLI `ui init` 不再部署 `preferences.css`** — `runUiInit` 移除 `deployPreferencesCss` 调用,返回类型 `RunUiInitResult` 移除 `preferencesCss` 字段
|
|
34
|
+
3. **可交互组件源码内显式 `cursor-pointer`** — Button / Toggle / Tabs 等所有渲染 `<button>` 或 `[role='button']` 的组件,在其 cva base 或主 className 中直接写 `cursor-pointer`
|
|
35
|
+
4. **`<input type="search">` 浏览器原生 clear 按钮屏蔽** — 这两条 CSS 规则不属于"可交互样式"范畴,改为业务侧 globals.css 模板与 storybook globals.css 各自内联(脚手架已更新)
|
|
36
|
+
5. **disabled 态保持现有 `disabled:cursor-not-allowed` Tailwind 修饰符** — 与 `cursor-pointer` 共存时,`:disabled` 状态选择器优先级覆盖
|
|
37
|
+
6. **ADR 0022 同步降级为 historical** — 它的全部约束在新方案里不再适用(没有"preferences.css 该不该装内容"问题,因为没有这个文件)
|
|
38
|
+
|
|
39
|
+
## Consequences
|
|
40
|
+
|
|
41
|
+
### 强制约束(由本 ADR 与 [`teamix-evo-design-opentrek` skill](../../packages/skills/src/teamix-evo-design-opentrek/SKILL.md) checklist 同步落地)
|
|
42
|
+
|
|
43
|
+
> 设计 skill checklist 新增条目:**"任何 onClick / hover-反馈 / Radix Trigger / role='button' 的元素必须显式带 `cursor-pointer`"**(disabled 态保留现有 `disabled:cursor-not-allowed`)。AI 生成 / 人工 review 都按此查。
|
|
44
|
+
|
|
45
|
+
- 渲染 `<button>` / `[role='button']` 的组件,**必须在源码 className 里显式写 `cursor-pointer`**;不允许"留给全局 CSS 兜底"
|
|
46
|
+
- Radix `*Trigger` / `*Close` 等直透传(`const Trigger = Primitive.Trigger`)若用户能直接渲染并交互,**必须包成 `forwardRef` 加默认 `cursor-pointer`**(已对 Popover / Tooltip / HoverCard / Dialog / AlertDialog / Sheet / Collapsible 等按此模式改造)
|
|
47
|
+
- 组件**禁止写 `cursor-default`**,除非该元素**确实不可交互**(如 Tooltip 内部纯展示文本)
|
|
48
|
+
- `<a href>` 锚点元素由浏览器默认 `cursor: pointer`,无需显式声明;但 `<a>` 不带 `href` 仅 `onClick` 时,需显式 `cursor-pointer`
|
|
49
|
+
- disabled 态用 `disabled:cursor-not-allowed`(原生 `disabled` 属性) 或 `data-[disabled]:cursor-not-allowed`(Radix `data-disabled` 属性);**禁止写 `cursor-default`** 表示 disabled
|
|
50
|
+
- 已知例外(故意非 pointer):`Sidebar` 的 resize rail 用 `cursor-w-resize` / `cursor-e-resize`(语义是拖拽手柄,非按钮)
|
|
51
|
+
|
|
52
|
+
### 工程影响
|
|
53
|
+
|
|
54
|
+
- 消费方 `src/preferences.css` 不再生成;升级时 `teamix-evo ui upgrade` 不会主动删除已有用户文件(frozen 语义),消费方可手动删
|
|
55
|
+
- `packages/templates/dev/globals.css` / `packages/create/templates/react-ts/src/index.css` / `packages/ui/.storybook/globals.css` 已分别内联 `<input type="search">` 原生 clear 屏蔽规则
|
|
56
|
+
- `packages/skills/src/teamix-evo-manage/SKILL.md` / `packages/tokens/README.md` / `packages/create/README.md` / `packages/docs/docs/create/index.md` 移除对 `preferences.css` 的所有引用
|
|
57
|
+
- `packages/cli/src/core/ui-init.ts` 删除 `deployPreferencesCss` 函数;`packages/cli/src/commands/ui/init.ts` 删除 preferences 部署日志输出
|
|
58
|
+
|
|
59
|
+
### 迁移路径(已存在 preferences.css 的业务工程)
|
|
60
|
+
|
|
61
|
+
1. 删除 `src/preferences.css` 文件(或保留无影响 — 仅是冗余)
|
|
62
|
+
2. 删除 `src/index.css` 顶部的 `@import './preferences.css';` 行
|
|
63
|
+
3. `teamix-evo ui upgrade` 拉新组件源码,新源码自带 `cursor-pointer`,无须额外配置
|
|
64
|
+
4. 如果业务侧有 `<input type="search">` 用法,**手动**把 `::-webkit-search-cancel-button { display: none; }` 等规则加到自己的 `src/index.css`(或不加 — 接受浏览器原生 clear 按钮)
|
|
65
|
+
|
|
66
|
+
## Source
|
|
67
|
+
|
|
68
|
+
- shadcn-ui 官方 Command 默认是 `cursor-default`(为键盘优先 command palette 设计);本项目业务场景偏鼠标交互,统一改为 `cursor-pointer`
|
|
69
|
+
- [W3C ARIA 1.2](https://www.w3.org/TR/wai-aria-1.2/) `role='option'` / `role='menuitem'` 等没有强制 cursor 视觉规约,由设计语言决定
|
|
70
|
+
- [Tailwind v4 cascade ordering](https://tailwindcss.com/docs/v4-beta#layered-architecture):utilities 层晚于 base 层,组件类 utility 永远优先于 `@layer base { ... }` 的属性选择器规则
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# 0024. uni-manager scoped CSS 与组件激活态 / disabled 冲突的统一规则
|
|
2
|
+
|
|
3
|
+
- **Status**: Accepted
|
|
4
|
+
- **Date**: 2026-06-01
|
|
5
|
+
- **Region**: 0100–0999 协议与工具
|
|
6
|
+
- **Related ADR**: [ADR 0023](0023-cursor-pointer-explicit-in-component-source.md)(可交互手型显式声明)
|
|
7
|
+
|
|
8
|
+
## Context
|
|
9
|
+
|
|
10
|
+
ADR 0023 之后,`@teamix-evo/tokens/variants/uni-manager/theme.css` 用 scoped CSS(`[data-theme='uni-manager'] [class*='border-input']:hover/:focus-visible { ... }`)实现了对齐 cd hybridcloud 的"中性焦点 + 柔和 hover 阴影"行为。**这套规则在 form input wrapper 上很好用**(Input prefix/suffix 包壳、Select/Cascader/DatePicker trigger),但与下面两类组件**反复冲突**:
|
|
11
|
+
|
|
12
|
+
### 冲突 1 — Radix 激活态被中性灰边框压住
|
|
13
|
+
|
|
14
|
+
**症状**:Checkbox 选中后(蓝底白勾),周围**多一圈中性灰边框**;Switch 开启 / Toggle 激活同样问题。
|
|
15
|
+
|
|
16
|
+
**原因**:
|
|
17
|
+
- Radix Checkbox/Radio/Switch/Toggle 等组件的 `Primitive.Root` 是 `<button>` 渲染,默认 className 含 `border-input`(中性边)
|
|
18
|
+
- 选中态用 Tailwind `data-[state=checked]:border-primary` 切到主色
|
|
19
|
+
- uni-manager scoped CSS 命中 `[class*='border-input']:focus-visible`,设置 `border-color: var(--color-input-focus)`(`#aaaaaa`)
|
|
20
|
+
- **CSS 特异性**:scoped CSS `(0,5,0)` > Tailwind utility `(0,2,0)` → 全局规则赢,组件 `border-primary` 失效
|
|
21
|
+
|
|
22
|
+
**已踩过的组件**:Checkbox / Radio Group Item / Switch / Toggle Group Item
|
|
23
|
+
|
|
24
|
+
### 冲突 2 — disabled 态的 hover 仍触发样式
|
|
25
|
+
|
|
26
|
+
**症状**:Checkbox 禁用后,鼠标 hover 仍出现 border 变蓝 / 底色微变。
|
|
27
|
+
|
|
28
|
+
**原因**:
|
|
29
|
+
- 组件源码用 `hover:border-primary hover:bg-primary/5` 做 hover 反馈
|
|
30
|
+
- `:disabled` 伪类不阻止 `:hover` 触发(浏览器 spec)— 视觉效果照样应用
|
|
31
|
+
- 通常配 `disabled:opacity-50 disabled:cursor-not-allowed` 但都不影响 hover 样式 cascade
|
|
32
|
+
|
|
33
|
+
## Decision
|
|
34
|
+
|
|
35
|
+
**两条统一规则,合并写入设计 skill checklist 与 token 包文档**:
|
|
36
|
+
|
|
37
|
+
### 规则 A — uni-manager scoped CSS 必须排除 Radix 激活态
|
|
38
|
+
|
|
39
|
+
`packages/tokens/variants/uni-manager/theme.css` 中所有 `[class*='border-input']:hover` / `:focus-within` / `:focus-visible` 规则,**必须**在 `:not()` 链里排除以下 Radix `data-state` 值:
|
|
40
|
+
|
|
41
|
+
```css
|
|
42
|
+
:not([data-state='checked'])
|
|
43
|
+
:not([data-state='indeterminate'])
|
|
44
|
+
:not([data-state='on'])
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
理由:这三个值统一表示"组件已进入激活态,有自身的主色视觉",scoped CSS 不应再叠加中性反馈。如果未来出现新的"激活态"值(例如 Tabs trigger 的 `"active"`、Tooltip 的 `"open"`),按需补到 `:not()` 链里。
|
|
48
|
+
|
|
49
|
+
> `aria-invalid='true']`(error 态)与 `[disabled]`(禁用态)已在原有 `:not()` 链中,无需重复。
|
|
50
|
+
|
|
51
|
+
### 规则 B — 组件源码内的 hover / focus 反馈必须用 `enabled:` 前缀
|
|
52
|
+
|
|
53
|
+
任何**视觉变化型** hover / focus 反馈(border / bg / shadow / opacity 等),写在组件源码 className 时**必须**用 `enabled:` 前缀(等价 CSS `:enabled:hover`),disabled 态不触发样式变化:
|
|
54
|
+
|
|
55
|
+
```diff
|
|
56
|
+
- 'hover:border-primary hover:bg-primary/5'
|
|
57
|
+
+ 'enabled:hover:border-primary enabled:hover:bg-primary/5'
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
例外:
|
|
61
|
+
- `cursor-pointer`(由 ADR 0023 强制) **不需要** `enabled:` 前缀 — disabled 态有 `disabled:cursor-not-allowed` 优先级覆盖
|
|
62
|
+
- 不渲染为 `<button>` / `<input>` 的元素(如纯 `div` 容器)无 `:enabled` / `:disabled` 概念,可不加 `enabled:`(也不会有 disabled prop 传入)
|
|
63
|
+
|
|
64
|
+
### 规则 C — 新组件接入 `border-input` 类时检查 scoped CSS 命中范围
|
|
65
|
+
|
|
66
|
+
新增组件如果在主 className 用 `border-input`(典型场景:form trigger),**必须**确认是否有内置 `data-state` 激活态。如果有,需要核对 [`uni-manager/theme.css`](../../packages/tokens/variants/uni-manager/theme.css) 的 `:not()` 排除链是否覆盖了对应状态值。
|
|
67
|
+
|
|
68
|
+
## Consequences
|
|
69
|
+
|
|
70
|
+
### 强制约束(由本 ADR 与 [`teamix-evo-design-opentrek` skill checklist](../../packages/skills/src/teamix-evo-design-opentrek/checklist.md) 同步落地)
|
|
71
|
+
|
|
72
|
+
- 设计 skill checklist 强制项 #11(可交互手型,ADR 0023)**扩展为**:
|
|
73
|
+
> "可交互元素显式带 `cursor-pointer`(enabled);视觉反馈(hover/focus)用 `enabled:` 前缀;Radix `data-state` 激活态视觉自管,不被 scoped CSS 覆盖"
|
|
74
|
+
- AI 生成 / 人工 review 都按此查
|
|
75
|
+
- ESLint 规则**不强制**(状态态 + 排除链组合静态识别复杂度高,依赖 skill checklist + ADR 知识库)
|
|
76
|
+
|
|
77
|
+
### 已修组件清单(本次落地)
|
|
78
|
+
|
|
79
|
+
- ✅ Checkbox(`enabled:` 前缀 + scoped CSS `:not([data-state=checked])` 排除链)
|
|
80
|
+
- ✅ Radio / Switch / Toggle / ToggleGroup(自动受益于 scoped CSS `:not()` 排除链,组件源码已是 `data-[state=checked]:border-primary`)
|
|
81
|
+
|
|
82
|
+
### 后续工序
|
|
83
|
+
|
|
84
|
+
新增组件遵循:
|
|
85
|
+
1. 渲染 `<button>` 且有 `data-state` → cva base 加 `border-input` 时同时确认 scoped CSS 排除链覆盖
|
|
86
|
+
2. 视觉反馈 hover / focus → 加 `enabled:` 前缀
|
|
87
|
+
3. 写入 stories 时配 disabled 演示验证
|
|
88
|
+
|
|
89
|
+
### 反模式(踩过的坑)
|
|
90
|
+
|
|
91
|
+
- ❌ scoped CSS 用 `[class*='border-input']` 不加状态排除 — 撞 Radix 激活态
|
|
92
|
+
- ❌ 组件 hover 样式不加 `enabled:` 前缀 — disabled 仍响应
|
|
93
|
+
- ❌ 在组件 cva 里加 `cursor-default` 试图压制 preferences.css cursor 规则(已被 ADR 0023 禁止)
|
|
94
|
+
|
|
95
|
+
## Source
|
|
96
|
+
|
|
97
|
+
- 反复踩坑 → 修补 → 再踩的根因总结(2026-05 W3 选择类波次 / W3 后置 Checkbox 视觉对齐 cd hybridcloud)
|
|
98
|
+
- [Radix UI primitives data-state 命名约定](https://www.radix-ui.com/primitives/docs/guides/styling#styling-states)
|
|
99
|
+
- [CSS Selectors Level 4 :enabled / :disabled 伪类](https://www.w3.org/TR/selectors-4/#enabled-pseudo)
|