Regression / regression (push) Canceled after 0s
## 品牌标识(本次会话) 起因:品牌此前没有任何图形标识 —— 唯一 favicon 是内联 data-URI 里的字母「A」, 那是 v2.0.0「Aurora Admin → Kole UI」改名漏掉的一处(PC 顶栏也是「A」, 移动端站已是「K」;移动端文档站则完全没有 favicon)。 - 几何:24 网格三个互不接触的笔画(竖 + 两斜),圆头描边; 描边 2.25 → 16px 标签页尺寸下正好 1.5px = 规范原文「描边1.5px」 - 取色分两套(刻意):favicon 硬编码品牌蓝/白(渲染在浏览器标签栏,不继承 kole-dark); 顶栏标记走 currentColor(实测暗色下自动转 rgb(20,22,28)) - 新增 theme-color 双条(light #FFFFFF / dark #1C1F26,取 --kole-color-card-bg) - 修 site/app.js hero 标语 KOLE ADMIN → KOLE UI(改名变形残留) - 移动端 7 个模板补 favicon(此前计数 0) 验收:门禁 9 条全 OK(site-routing/site-routes/mobile-docs/mobile-site/isolation/ theme/nav/i18n/icons);PC 回归 1464/1464 · 移动端 807/807,各连跑 8 次一致; 两端 favicon 405 字节逐字节一致;PC 站控制台错误 1→0。 ## 并行会话成果(本次一并入库) - 图标系统:2576 图标(TDesign/Element Plus,MIT)+ 11 端注入 + 5 个构建门禁工具 + IconPreview 预览页 + ICON-SPEC.md 冻结规格 - 移动端平台:47 组件 × 6 端 + 文档站 53 页 + 隔离门禁 - PC 组件:103 个大后台组件 / 组件11 批次 - uni-app:PC 端试点 + 移动端端实现 + 真实编译验证 ## 工程 - .gitignore 补 .scratch/ 与 .zcode-preexisting-*.txt(会话中间产物,实测 9.1MB,不入库) - CHANGELOG 补品牌标识条目 - ROADMAP 登 S8-P4(品牌标识任务包 + og:image/apple-touch-icon 未做部分)
158 lines
8.1 KiB
Markdown
158 lines
8.1 KiB
Markdown
# 图标系统冻结规格(IconSpec v1)
|
||
|
||
> 本文件是图标相关任务的**唯一真源**。改图标行为先改这里,再改实现。
|
||
> 冻结日期:2026-09-20 | 依据:三库实测(见 §一)+ 本仓库既有规范原文。
|
||
|
||
---
|
||
|
||
## 一 · 参考基准(实测,非推测)
|
||
|
||
用户指定参考 TDesign 与 Element 组件库。以下是 2026-09-20 对三个上游的**实测**数据:
|
||
|
||
| 上游 | 版本 | 许可 | 图标数 | 形态 | 网格 |
|
||
|---|---|---|---|---|---|
|
||
| TDesign Icons(线性) | `tdesign-icons-svg@0.4.7` | MIT | 1334 | `stroke="currentColor"` 描边 | 24×24(少数 24×25 / 25×24) |
|
||
| TDesign Icons(面性) | 同上 | MIT | 1020 | `fill="currentColor"` 填充 | 同上 |
|
||
| Element Plus Icons | `@element-plus/icons-svg@2.3.2` | MIT | 293 | `fill="currentColor"` 填充 | 1024×1024 |
|
||
| Element UI Icons | `element-ui@2.15.14` | MIT | 283 名 | 图标字体(无独立 SVG) | — |
|
||
|
||
- **名称并集**:1511 个不同名(归一化后);在 ≥2 个库里都出现的:**217** 个。
|
||
- **进入本仓库**:**2576** 个图标(TDesign 线性 1334 + 面性 1020 + Element Plus 293)。
|
||
Element UI 的 283 个字体图标名**不单独引入字形**(它是字体不是 SVG),
|
||
而是通过**别名层**映射到上述三类里语义相同的图标(见 §三)。
|
||
|
||
### 上游参考组件的图标相关功能(用户点名)
|
||
|
||
| 组件 | 上游的图标能力 | 本仓库如何覆盖 |
|
||
|---|---|---|
|
||
| TDesign `TabBar` / `TabBarItem` | `icon`(函数或插槽)、`badgeProps`(图标右上角角标)、`subTabBar`(二级菜单) | 图标组件提供 `name` + 角标由 `Badge` 承担(既有设计);`subTabBar` 不在图标职责内 |
|
||
| Element UI `PageHeader` | 返回箭头(内置 `el-icon-back`)、标题 / 副标题、右侧 `extra` 插槽 | 图标组件提供 `back` / `chevron-left` / `arrow-left` 三个语义名,`PageHeader` 既有实现继续用 |
|
||
| TDesign `Icon` | `size` 支持**关键字**(`xs`/`small`/`medium`/`large`/`xl`)**与任意 CSS 值**(写成内联 `font-size`)、`onClick`、`class`/`style` 透传 | 本规格 §四:`size` 同名关键字 + 任意 CSS 值;`onClick` 由端上事件绑定承担 |
|
||
|
||
---
|
||
|
||
## 二 · 归一化(我们做了哪些修正,不是照抄)
|
||
|
||
| # | 上游问题 | 我们的处理 | 谁卡这条 |
|
||
|---|---|---|---|
|
||
| 1 | TDesign 全部 2356 个 SVG 把 `viewBox` 写成 **`view-box`**(无效属性,浏览器忽略 → 图标按默认视口缩放) | 构建期两种拼写都读,产物统一写回 `viewBox` | `tools/verify-icons.mjs` |
|
||
| 2 | TDesign 描边宽度 `stroke-width="2"`(24 网格) | 归一为 **1.5**,依据 `组件1.txt`「图标规范:线性图标,描边1.5px」 | 同上 |
|
||
| 3 | `fill="transparent"` 命中区路径 | 丢弃(那是热区不是视觉内容) | 同上 |
|
||
| 4 | 路径数字精度不一(最多 6 位小数) | 归一到 2 位小数 + 折叠空白(实测省 25% 体积) | 同上 |
|
||
| 5 | 两库同名不同形 | 优先级 `tdesign-outline > element-plus > tdesign-filled` | 同上 |
|
||
|
||
**为什么优先级是线性优先**:本仓库规范明示「线性图标」,且 PC 既有实现(`Button.html` 的内联 SVG)与移动端 `TabBar` 都是描边风格。面性图标保留 `-filled` 后缀供需要时选用。
|
||
|
||
---
|
||
|
||
## 三 · 命名与别名
|
||
|
||
### 3.1 主名(canonical name)
|
||
|
||
- 一律 **kebab-case**,`[a-z0-9-]`。
|
||
- 面性图标保留 **`-filled`** 后缀(与上游一致,不发明第二套词)。
|
||
- 例:`search` / `star` / `star-filled` / `chevron-right` / `logo-github`。
|
||
|
||
### 3.2 别名层(alias)
|
||
|
||
用途:让 **Element UI 的 283 个历史图标名**、以及常见同义词都能落到某个真实图标上。
|
||
别名表 `aliases.json` 是**显式列出**的映射,不做启发式猜测。
|
||
|
||
- 断言:每个别名必须指向一个真实存在的 canonical name(`verify-icons.mjs` 卡)。
|
||
- 别名不产生新图标,只改查找路径。
|
||
|
||
---
|
||
|
||
## 四 · 组件 API(PC 与移动端共用同一套语义)
|
||
|
||
### 4.1 props
|
||
|
||
| 名 | 类型 | 默认 | PC | 移动端 | 说明 |
|
||
|---|---|---|---|---|---|
|
||
| `name` | string | `''` | ✅ | ✅ | 图标名;空则渲染 `default` 插槽 |
|
||
| `size` | string \| number | `'default'`(PC)/ `'default'`(移动端) | ✅ | ✅ | **关键字**或**任意 CSS 长度**(见 4.2) |
|
||
| `tone` | string | `'default'` | ✅ | ✅ | `default` / `brand` / `secondary` / `danger` / `success` / `warning` |
|
||
| `spin` | boolean | `false` | ✅ | ✅ | 持续旋转,仅表示「进行中」 |
|
||
| `label` | string | `''` | ✅ | ✅ | 无障碍名称;有值 → `role="img"`,无值 → `aria-hidden` |
|
||
| `color` | string | `''` | ✅ | — | 任意 CSS 颜色,优先于 `tone`(PC 历史字段,保留兼容) |
|
||
| `icon` | string | `'★'` | ✅ | — | **PC 历史字段**:直接给字形字符而非图标名(保留兼容,见 §六) |
|
||
|
||
### 4.2 size 取值(覆盖 TDesign 的关键字 + 任意值双模式)
|
||
|
||
| 关键字 | 边长 | 出处 |
|
||
|---|---|---|
|
||
| `small` | 16px | PC 规范 16/20/24;移动端四档 |
|
||
| `default` | 20px | 同上 |
|
||
| `large` | 24px | 同上 |
|
||
| `xlarge` | 32px | 仅移动端(空状态大图标) |
|
||
| 其他字符串 | 原样作为 CSS 长度 | 对齐 TDesign「任意值写内联 fontSize」 |
|
||
|
||
PC 端另有 `--kole-icon-size-*` 令牌层;移动端 `--kole-m-icon-size` 可被业务覆盖。
|
||
|
||
### 4.3 无障碍(硬要求)
|
||
|
||
- `label` 有值 → `role="img"` + `aria-label`。
|
||
- `label` 为空 → `aria-hidden="true"`,装饰性图标不进读屏序列。
|
||
- 图标**不得作为唯一信息载体**:颜色变化必须伴随文字或 `label`。
|
||
- 语义色图标与背景对比度 ≥ **3:1**(WCAG 1.4.11 非文本对比)。
|
||
- `spin=true` 在 `prefers-reduced-motion: reduce` 下停止旋转。
|
||
|
||
---
|
||
|
||
## 五 · 分层与加载策略(按实测体积决定,不是拍脑袋)
|
||
|
||
| 层 | 数量 | 加载方式 | 实测体积 |
|
||
|---|---|---|---|
|
||
| `core` | 151 | **内联**进组件包(`core.js`) | 35KB |
|
||
| `standard` | 1993 | 按需 `loadAll()` | — |
|
||
| `extended` | 432 | 按需 `loadAll()` | — |
|
||
| 全量 `registry.json` | 2576 | 按需 | 670KB |
|
||
|
||
**为什么不全内联**:实测全量 670KB —— 内联等于给每一页都加 670KB,
|
||
直接破坏 `ROADMAP` 的 data.js 150KB 预算精神。core 层 151 个 35KB 是可接受的常驻成本。
|
||
|
||
---
|
||
|
||
## 六 · 兼容与迁移
|
||
|
||
- **PC `icon` prop 保留**:既有 5 端实现用 `icon`(字形字符,默认 `'★'`)。
|
||
v1 起新增 `name`(图标名)。两者都在时 **`name` 优先**;`icon` 仍按字形字符直接渲染。
|
||
这样既有调用点(`frameworks/Icon.*`)不破,新调用点用 `name`。
|
||
- **移动端 `GLYPHS` 9 名字形表保留**:`check`/`close`/`star`/`warn`/`info`/`arrow`/`plus`/`minus`/`more`
|
||
是移动端既有语义名,通过别名层映射到新图标集(`warn` → `warning` 等),
|
||
既有 4 端实现的行为不破。
|
||
|
||
---
|
||
|
||
## 七 · 产物清单
|
||
|
||
| 路径 | 内容 | 入库 |
|
||
|---|---|---|
|
||
| `.design_library/kole-ui/icons/sources.json` | 上游原始路径数据(归一化后) | ✅ |
|
||
| `.design_library/kole-ui/icons/registry.json` | 全量渲染数据 2574 | ✅ |
|
||
| `.design_library/kole-ui/icons/manifest.json` | 清单(名字 / 层 / 组 / viewBox / 模式) | ✅ |
|
||
| `.design_library/kole-ui/icons/core.js` | 内联运行时(UMD) | ✅ |
|
||
| `.design_library/kole-ui/icons/viewbox.js` | viewBox 例外表 | ✅ |
|
||
| `.design_library/kole-ui/icons/aliases.json` | 别名表 | ✅ |
|
||
| `.design_library/kole-ui/icons/ATTRIBUTION.md` | MIT 归属(分发必带) | ✅ |
|
||
| `site/icons.json` | 文档站轻量索引 | ✅ |
|
||
|
||
---
|
||
|
||
## 八 · 验收门
|
||
|
||
```bash
|
||
npm run build:icons # 离线重建全部产物
|
||
npm run verify:icons # 静态断言(见 tools/verify-icons.mjs)
|
||
```
|
||
|
||
`verify:icons` 至少覆盖:
|
||
|
||
1. 产物齐全且互相一致(manifest ↔ registry 双向)。
|
||
2. 无 `view-box` 拼写残留。
|
||
3. 描边宽度全部 1.5。
|
||
4. core 层图标真的能从 `core.js` 渲染出非空 SVG。
|
||
5. 别名全部指向真实图标。
|
||
6. 每个端实现的 `name` 查找路径都能落到 registry(不出现"端上有 API 但取不到图标")。
|
||
7. 分组覆盖率 ≥ 75%(低于则说明分组规则退化)。
|