Files
cc-web/.trellis/tasks/07-17-gilded-wasteland-theme/research/icon-rework-audit.md
2026-07-18 10:14:38 +08:00

347 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Wasteland 图标重做审计
审计时间:2026-07-17
输入资产:
- 图标板:`sessions/_attachments/43bd9ed6-2ba6-4c9d-bd9d-25b068cb4711.webp`
- 完整界面参考:`sessions/_attachments/f01c1388-b603-434a-b226-2ff5771d4925.webp`
- 现有图标:`public/assets/themes/wasteland/icons/*.png`
- 当前样式:`public/style.css`
结论:主 UI 控件不建议继续直接使用现有原色 PNG。推荐改为“清理后的 24px 单色 mask + CSS 暗金材质”,再按控件容器设置 16/18/20/24px 的显示尺寸。`status` 这类带绿色状态语义、头像/主题装饰类图标可以保留原色,但要重新裁切对应规格。
## 1. 参考界面实际显示尺寸
图标板原尺寸为 `1672x941`,每张卡片标注了 `16px / 24px / 32px` 三档逻辑使用尺寸。需要注意:标注是设计目标尺寸,不等同于源图中的物理像素;当前切片来自 32px 档展示图,源图里主体通常有 49-70px 宽高。
完整参考图同为 `1672x941`。按原尺寸查看和局部放大后,主要控件的实际显示尺寸约为:
| 区域 | 控件 | 参考图容器尺寸 | 图标视觉主体 | 对齐观察 |
| --- | --- | ---: | ---: | --- |
| 侧栏顶部 | 新会话主按钮 | `229x48` | `18-20px` | 图标+文字整体居中,图标不贴左边 |
| 侧栏顶部 | 新会话下拉按钮 | `51x48` | `10-12px` 宽、`7-9px` 高 | 小三角居中 |
| 侧栏顶部 | 搜索框 | `288x34` | `18-20px` | 图标左距约 `13px`,图标到文字约 `10px` |
| 项目列表 | 折叠/展开三角 | 行高约 `44-46px` | `10-12px` | 左侧垂直居中 |
| 项目列表 | 新建圆形加号 | 约 `28-30px` 圆按钮 | `14-16px` | 圆按钮居中,线条要比搜索更实 |
| 输入区上方 | 运行状态/模式 chip | 高约 `30-31px` | 状态点约 `8px`,下拉约 `8px` | 文字与图标同基线 |
| 输入区 | 输入框外框 | 约 `804x70` | 附件 `22-24px` | 附件没有明显方形底,靠左居中 |
| 输入区右侧 | 发送/队列/停止按钮 | 约 `42x42` | 发送 `24-28px`,停止 `17-20px` | 三个按钮等宽等高,间距约 `6px` |
| 消息卡右下 | 小动作按钮 | `29-30px` | `14-16px` | 适合单色小图标,不适合复杂材质 PNG |
| 侧栏底部 | 设置按钮 | 可点击区约 `34px` 高 | `18px` | 与文字标签水平对齐 |
| 侧栏底部 | 主题/星芒入口 | 可点击区约 `34px` 高 | `22-24px` | 星芒比齿轮略大才接近参考 |
当前 `public/style.css` 中 Wasteland 图标相关尺寸:
- `.new-chat-btn::before`:`24x24`
- `.session-search::before`:`20x20`
- `.attach-btn::before` / `.send-btn::before` / `.abort-btn::before` / `.settings-btn::before`:默认 `22x22`
- `.settings-btn`:`34x34`
- `:is(.settings-select, .mode-select)` 下拉背景:`14x14`
- 移动端 `.attach-btn/.send-btn/.abort-btn::before`:降到 `20x20`
主要偏差:参考图里“主按钮图标”和“输入区发送图标”不是同一套尺寸;当前 CSS 把大部分伪元素统一为 `22x22`,导致小动作按钮偏脏、大按钮又不够有冲击。
## 2. 现有 PNG 为什么显得糊、脏、比例怪
现有 PNG 全部是 `64x64 RGBA`,但它们不是干净矢量导出的图标,而是从有损 WebP 展示板里裁 32px 档,再透明化/统一画布得到的位图。抽检全部 17 个 PNG 后,问题集中在以下几点。
### 2.1 缩放链路过长
当前路径大致是:
```text
有损 WebP 展示板
→ 裁 32px 档的放大截图区域
→ 统一输出 64x64 PNG
→ CSS 再缩到 14/20/22/24px
```
浏览器最后会把 64px 的半透明阴影、暗边、高光全部平均到 20-24px。图标不会变“精致”,反而会把阴影糊成灰边。
### 2.2 alpha 过软,缺少清晰实心主体
PNG 的非透明像素几乎都是半透明像素。统计结果显示:
- 多数图标的半透明像素占比在 `96%-100%`
- `stop.png` 也有约 `92%` 半透明像素
- 非透明像素平均 alpha 普遍只有 `67-142/255`
这说明边缘和主体都偏软。缩小时,暗边会吞掉金色高光,尤其在黑铁背景上更明显。
### 2.3 有效主体尺寸不一致
代表性 PNG 的 alpha 边界如下:
| 图标 | PNG 画布 | alpha 主体边界 | 视觉问题 |
| --- | ---: | ---: | --- |
| `new-chat.png` | `64x64` | `55x54` | 星芒长尖角多,缩小后中心笔画变弱 |
| `search.png` | `64x64` | `54x54` | 圆环+手柄复杂,20px 时手柄容易糊 |
| `attachment.png` | `64x64` | `42x54` | 窄高图标,被统一方形缩放后显得瘦 |
| `send.png` | `64x64` | `54x49` | 纸飞机横向强,22px 时尖角仍可辨但高光变灰 |
| `stop.png` | `64x64` | `54x54` | 填充和外框过重,小尺寸像脏方块 |
| `settings.png` | `64x64` | `54x53` | 齿轮齿太多,22px 以下信息密度过高 |
| `dropdown.png` | `64x64` | `54x40` | 横宽纵矮,放进 `14x14` 背景后实际只有约 `14x10` |
同样放进 `22x22` 伪元素时,`attachment` 会显瘦,`stop/settings` 会显重,`dropdown` 会显矮,整体视觉重量不统一。
### 2.4 原色 PNG 不能响应 CSS 颜色状态
当前 hover/focus 主要改变 `color`、`background-color`、`border-color`。PNG 作为 `background-image` 不会跟随 `color` 改变,所以 hover 后按钮变亮,但图标仍是暗铜色,造成“按钮亮、图标脏”的割裂。
## 3. 逐控件建议尺寸与对齐
建议把“容器尺寸”和“图标主体尺寸”分开控制,不再一刀切 `22x22`。
| 控件 | 当前落点 | 建议桌面尺寸 | 建议移动尺寸 | 对齐建议 |
| --- | --- | ---: | ---: | --- |
| 新会话 | `.new-chat-btn::before` | `20x20` | `18x18` | `.new-chat-btn` 改回图标+文字整体居中,`gap: 10px` |
| 新会话下拉 | `.new-chat-arrow::before` | `12x8` 或 `14x9` | `12x8` | 按钮 `48-52px` 宽,三角居中;隐藏原文本 `▾` |
| 搜索 | `.session-search::before` | `18x18` 或 `20x20` | `18x18` | `left: 13px`,输入框 `padding-left: 42px` |
| 附件 | `.attach-btn::before` | `24x24` | `22x22` | 40px 按钮内居中;不要用实心按钮底色压住图标 |
| 发送 | `.send-btn::before` | `24x24`,主发送可到 `26x26` | `22x22` | 桌面建议按钮 `40-42px`,纸飞机略向右上视觉居中 |
| 停止 | `.abort-btn::before` | `18x18` 或 `20x20` | `18x18` | 与发送按钮同容器,但图标主体必须小一档 |
| 设置 | `.settings-btn::before` | `18x18` | `18x18` | 34px 点击区内居中;避免 22px 齿轮过密 |
| 下拉 select | `:is(.settings-select, .mode-select)` | `10x7` 或 `12x8` | `10x7` | `background-position: right 12px center`;不要用 `14x14` 方形 PNG |
补充建议:
- 消息卡角落动作按钮:容器 `30x30`,图标只用 `14-16px` mask。
- 项目折叠三角:使用 `10-12px` mask,不要复用 24px/32px 原色 PNG。
- 状态点/在线图标:如果要保留绿色,应单独重裁 `16px` 或 `20px` 原色图,不建议统一金色 mask。
## 4. 三种方案对比与推荐
| 方案 | 优点 | 缺点 | 适用范围 | 结论 |
| --- | --- | --- | --- | --- |
| 原色 PNG | 最接近图标板的金属纹理;不需要改 DOM;可保留绿色状态、头像等多色信息 | 当前资产来自有损截图且 alpha 过软;缩到 20px 会糊;hover/focus 不能自动变色;每个尺寸都要维护独立图片 | 装饰图标、状态图标、头像/主题入口、较大 32px 展示 | 不推荐作为主 UI 控件方案 |
| CSS mask | 形状和材质分离;可用 CSS 控制金色、hover、禁用、危险色;小尺寸更干净;同一 mask 可按控件调尺寸 | 会损失原图内部金属纹理;如果直接拿现有 PNG 当 mask,软 alpha 仍会残留;严格做好需要清理 mask 资产 | new-chat/search/attach/send/stop/settings/dropdown 等交互控件 | 推荐主路径 |
| 重新裁 24px | 保留原色质感;比 64px 再缩小更稳;实现成本中等 | 仍是位图,16px 以下会糊;hover 不能换材质;不同控件仍要分别调视觉重量 | 必须保留原色材质的 24px 常规按钮 | 可作为过渡或备用 |
推荐路径:
1. 主交互控件使用 CSS mask,但不要直接依赖当前软 alpha PNG;先从图标板重做清晰的 24px 单色 mask,或从现有 PNG 做阈值化/锐化后生成 `icons/masks/*.png`。
2. `new-chat/search/attach/send/stop/settings/dropdown` 全部走 mask + CSS 暗金材质。
3. `status/user/theme/ai` 这类多色或装饰语义保留原色,但分别重裁 `16/24/32px`,不要再统一 64px 后缩放。
## 5. CSS mask 规则建议
下面是基于当前 DOM 的精确 selector 规则。路径可以先指向现有 PNG 做验证;正式落地时建议替换为清理后的 mask 资产,例如 `assets/themes/wasteland/icons/masks/send.png`。
### 5.1 通用金色材质
```css
html[data-theme='wasteland'] {
--waste-icon-gold:
radial-gradient(circle at 32% 22%, rgba(255, 244, 196, 0.98) 0 10%, transparent 32%),
linear-gradient(135deg, #fff0bd 0%, #dfbd82 28%, #c49a5a 48%, #8f592b 72%, #f0d7aa 100%);
--waste-icon-gold-muted:
linear-gradient(135deg, #ead7ad 0%, #c49a5a 44%, #7b4c27 100%);
--waste-icon-danger:
linear-gradient(135deg, #f1b68d 0%, #b96849 48%, #6f2f24 100%);
--waste-icon-shadow:
drop-shadow(0 0 2px rgba(223, 189, 130, 0.42))
drop-shadow(0 1px 1px rgba(0, 0, 0, 0.82));
}
html[data-theme='wasteland'] :is(
.new-chat-btn,
.new-chat-arrow,
.attach-btn,
.send-btn,
.abort-btn,
.settings-btn
)::before,
html[data-theme='wasteland'] .session-search::before {
content: '';
display: block;
flex: 0 0 auto;
background: var(--waste-icon-gold);
filter: var(--waste-icon-shadow);
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
-webkit-mask-position: center;
mask-position: center;
-webkit-mask-size: contain;
mask-size: contain;
}
```
### 5.2 new-chat
```css
html[data-theme='wasteland'] .new-chat-btn {
justify-content: center;
gap: 10px;
padding-inline: 16px;
}
html[data-theme='wasteland'] .new-chat-btn .new-chat-glyph {
display: none;
}
html[data-theme='wasteland'] .new-chat-btn::before {
width: 20px;
height: 20px;
-webkit-mask-image: url('assets/themes/wasteland/icons/new-chat.png');
mask-image: url('assets/themes/wasteland/icons/new-chat.png');
}
```
### 5.3 search
```css
html[data-theme='wasteland'] .session-search::before {
position: absolute;
left: 13px;
top: 50%;
z-index: 1;
width: 18px;
height: 18px;
transform: translateY(-50%);
pointer-events: none;
-webkit-mask-image: url('assets/themes/wasteland/icons/search.png');
mask-image: url('assets/themes/wasteland/icons/search.png');
}
html[data-theme='wasteland'] .session-search-input {
padding-left: 42px;
}
```
### 5.4 attach
```css
html[data-theme='wasteland'] .attach-btn::before {
width: 24px;
height: 24px;
-webkit-mask-image: url('assets/themes/wasteland/icons/attachment.png');
mask-image: url('assets/themes/wasteland/icons/attachment.png');
}
```
### 5.5 send
```css
html[data-theme='wasteland'] .send-btn::before {
width: 24px;
height: 24px;
-webkit-mask-image: url('assets/themes/wasteland/icons/send.png');
mask-image: url('assets/themes/wasteland/icons/send.png');
}
html[data-theme='wasteland'] .send-btn:hover::before {
background: var(--waste-icon-gold);
filter:
drop-shadow(0 0 4px rgba(223, 189, 130, 0.58))
drop-shadow(0 1px 1px rgba(0, 0, 0, 0.82));
}
```
### 5.6 stop
```css
html[data-theme='wasteland'] .abort-btn::before {
width: 18px;
height: 18px;
background: var(--waste-icon-danger);
-webkit-mask-image: url('assets/themes/wasteland/icons/stop.png');
mask-image: url('assets/themes/wasteland/icons/stop.png');
}
```
### 5.7 settings
```css
html[data-theme='wasteland'] .settings-btn {
display: inline-flex;
align-items: center;
justify-content: center;
width: 34px;
height: 34px;
padding: 0;
font-size: 0;
}
html[data-theme='wasteland'] .settings-btn::before {
width: 18px;
height: 18px;
-webkit-mask-image: url('assets/themes/wasteland/icons/settings.png');
mask-image: url('assets/themes/wasteland/icons/settings.png');
}
```
### 5.8 dropdown
`new-chat-arrow` 是普通按钮,可以直接用 mask:
```css
html[data-theme='wasteland'] .new-chat-arrow {
font-size: 0;
line-height: 0;
}
html[data-theme='wasteland'] .new-chat-arrow::before {
width: 12px;
height: 8px;
background: var(--waste-icon-gold-muted);
-webkit-mask-image: url('assets/themes/wasteland/icons/dropdown.png');
mask-image: url('assets/themes/wasteland/icons/dropdown.png');
}
```
`settings-select` 和 `mode-select` 是原生 `select`,当前 DOM 没有外层专用 wrapper,不能安全地只给箭头使用 `::before` mask。当前结构下推荐继续用金色 SVG 背景;如果强制用 CSS mask,需要新增 wrapper 或自定义 select 结构。
当前 DOM 兼容规则:
```css
html[data-theme='wasteland'] :is(.settings-select, .mode-select) {
appearance: none;
-webkit-appearance: none;
background-image:
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.25 6 6.75 11 1.25Z' fill='%23dfbd82' stroke='%238f592b' stroke-width='0.8'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-size: 12px 8px;
}
html[data-theme='wasteland'] .settings-select {
background-position: right 12px center;
}
html[data-theme='wasteland'] .mode-select {
background-position: right 10px center;
}
```
若后续允许改 DOM,建议把 select 放进 `.select-shell`,由 `.select-shell::after` 承载 dropdown mask,这样文本和箭头可以完全分层。
### 5.9 移动端尺寸
```css
@media (max-width: 560px) {
html[data-theme='wasteland'] .new-chat-btn::before,
html[data-theme='wasteland'] .session-search::before,
html[data-theme='wasteland'] .settings-btn::before {
width: 18px;
height: 18px;
}
html[data-theme='wasteland'] :is(.attach-btn, .send-btn)::before {
width: 22px;
height: 22px;
}
html[data-theme='wasteland'] .abort-btn::before {
width: 18px;
height: 18px;
}
}
```
## 6. 实施优先级
1. 先把 `new-chat/search/attach/send/stop/settings/new-chat-arrow` 改成 mask 方案,解决主路径视觉脏和 hover 不一致。
2. 同步把 select 下拉从 `dropdown.png` 改成金色 SVG 背景,尺寸降到 `12x8` 或 `10x7`。
3. 再生成清理后的 mask 资产,替换当前 PNG mask 源。清理标准是:去掉暗色投影,只保留形状 alpha;小尺寸下需要比原图更粗、更少内部细节。
4. 最后再决定是否为 `status/user/theme/ai` 重裁原色 `16/24/32px`,这些不应阻塞主交互控件修复。