mirror of
https://github.com/dsh-market/dsh-market.git
synced 2026-09-28 05:03:07 +08:00
`--dsw-alias-brand-primary` is an INK colour: the host resolves it to #0f1115 in the light theme and to #f9fafb in the dark one, and uses it for text and strokes while the surface underneath is a different token. The market had it as a badge *background* with a hardcoded `#fff` label, so in dark mode on 0.1.7 the fill and the text were both #f9fafb — white on white. The bundle "official" badge and every row of the override list rendered as empty white pills, which is what the report showed; the numbers were still there, invisible. Verified on a real 0.1.7-rc.2 host, both themes, computed styles: - before: `ovByTag` / `diagBadgeOfficial` bg rgb(249,250,251), colour rgb(255,255,255) — identical channels, nothing to read - after: dark bg rgb(249,250,251) colour rgb(15,17,21); light bg rgb(15,17,21) colour rgb(255,255,255) The host's own filled pair is `button-primary-fill` + `label-primary-foreground` (its primary Button and Pill use exactly that) — both with the old pair as the fallback, so hosts that predate those tokens are unchanged. The same sweep found four more surfaces hardcoding white on a themed fill, and the avatar letter that was white on `bg-layer-2` — which is white in the light theme. `tests/style-tokens.spec.ts` keeps it from coming back: no rule may set a themed background and a literal text colour together. Deliberately not checked: an ink token *as* a background — that is the correct fill for a progress bar and for the 9% tints the market already uses.
5.6 KiB
5.6 KiB
AGENTS.md — 产品设计原则
这份文档是约束,不是参考。市场里的任何产品设计、功能设计、界面改动,先按这里过一遍。
代码规范见 TESTING.md,安全边界见 SECURITY.md;这里只管一件事:给普通用户做的东西。
一、三条根本原则
1. 自然 —— 从用户的意图出发,不从实现出发
用户是带着一件事来的(「我想让 DSH 能发通知」),他不知道也不需要知道系统内部怎么分工。 界面要顺着他的意图走,不能要求他先理解我们的模型(插件 / bundle / profile / 层 / 依赖树)才能用。
- 用户要做的事 → 一步就是一步,别为了对应内部结构而拆成三步。
- 界面上出现的概念,必须是用户已有的概念。新造的词只有在无法避免时才出现,且第一次出现就要用人话解释。
- 系统的复杂度由系统吸收:排序、格式化、本地化、缓存、降级、重试,都是我们的事,不是让用户去选。
2. 好理解 —— 说人话,别让用户猜
- 用日常词:不说「凭据」「解析依赖」「幂等」「实例」「装载」,说「密钥」「准备依赖」「重复执行也没问题」「本次运行」「加载」。
- 一句话说一件事;按钮 2–4 字;正文一句不超过 20 字。
- 每一处文案都要能回答「所以呢?」——说完现象要说后果,说完后果要说下一步。
- 报错必须是三件事:发生了什么、为什么、现在怎么办。只有错误码、只有「失败了」而没有出路的,都不合格。
- 不确定就说不确定。宁可说「不知道」,也不要用一句听起来合理的话把空缺填上。
3. 面向普通用户 —— 替他做决定,而不是把决定推给他
- 默认值就是产品:绝大多数人不会改设置。默认要选那个「不读文档也对」的。
- 不把判断责任推给没有能力判断的人:给用户看的要么是他能行动的,要么是让他放心的,不能是「你自己看着办」。
- 常态安静,罕见才打扰(渐进披露):
- 大多数情况下都会出现的信息,是陈述,不是警告;
- 只有在罕见并且用户此刻必须做点什么时,才允许变醒目;
- 一个随处可见的警告,训练出来的是「不看警告」——包括真出事的那一次;
- 高级/专业信息默认收起,但可发现:需要它的那一刻能找到,不需要的时候不占位置。
- 不替用户做无谓的确认:可撤销的动作直接做,配一个撤销;只有不可撤销、或有真实后果的动作才打断他,并且说清后果。
- 反馈与确定性:每个动作都要有即时反应和明确落点(成功 / 失败 / 去哪看)。「点了没反应」是最差的状态。
二、苹果那套做法,落到这个项目的可检验规则
苹果的产品哲学里真正有用的是几条很朴素的判断,下面每条都写成本项目能检查的形式:
| 原则 | 在本项目里意味着 |
|---|---|
| 看不见的复杂度 | 用户不该看到内部模型;需要暴露时,先翻译成他的语言 |
| 直接操作 | 一个动作一个结果;不要为了「安全」加一层只有开发者懂的中间态 |
| 渐进披露 | 常态安静、罕见打扰、高级可发现(见上) |
| 少即是多 | 「要不要加这个信息」的默认答案是不加;能去掉的先去掉 |
| 一致性 | 同一个概念全篇同一个词;同一个控件同一个行为;同一份事实在不同卡片上用同一段渲染 |
| 恰当 | 语气跟场合走:出错时克制并给出路,成功时简短,危险操作时严肃 |
| 细节即产品 | 空状态、错误状态、深浅色、窄屏、长文本、加载中——都是要设计的界面,不是边界情况 |
| 不为不可能的错误设计 | 不要为了理论上可能的情况,给所有人加步骤 |
三、动手前先问自己(验收清单)
- 这句话,一个不懂技术的用户能读懂吗?读不懂的替换成日常词。
- 这条信息他看完能做什么?不能行动、也不能让他放心的,就不进主流程。
- 这个提醒是常态还是罕见?常态 → 降级为陈述。
- 这个确认能撤销吗?能撤销就别问。
- 这个功能默认展开还是收起?普通用户真的需要默认看到它吗?
- 出错了之后他知道下一步吗?
- 深浅色、窄屏、空列表、加载中、失败态,都过了一遍吗?
- 中英两份文案说的是同一件事吗?
四、已经犯过、不要再犯
这些是本项目真实发生过并修掉的,写在这是为了不再重演:
- 把常态渲染成警告:目录里 483 条「红色提示」中 354 条是同一句「同时读凭据并联网」——插件调模型本来就要用 key,把它标黄的结果是用户学会无视这一行。
- 把能力清单挂在每张卡片上:列表里没人靠「会读文件」挑插件;它的位置在详情页,且默认收起。
- 让用户读到系统内部:卡片上直接显示
uses literal IP 198.18.0.0 for network access;诊断页显示bundle、profile、disable-carrier。 - 只有现象没有出路:
Error: fetch failed(真实原因在cause里)、「操作失败」而不说重试。 - 把「没查到」说成「没问题」:
未检出要写成「没有扫描到。这不等于安全。」 - 同一句标签重复铺满:每行前面都加「值得看一眼:」。
- 为不可能发生的错误加步骤:装前用一屏能力清单拦人,而其中没有一条是用户能采纳的。