fix(design): M228 复审 r1 三条(字段底角色对齐、四处小疵、产品默认口径)
P2-1 字段底角色不对称(塔裁决方案 a):Silver 的 #dcddde 从 surface-container-high 改判到 surface-container-highest,与 Ink 的 #262b25 同位——component_map 的 TextField 口径就是最高 容器层,单一角色接法才不会一边掉层。Silver 的 high 改取推导值 #e4e4e5(tone 90),阶梯 94.12 → 90.61 → 88.07 保持单调、步长 ≥1.74 L*。实测:Error on 新 highest = 4.686(原按单一 角色接到 high 时的 4.379 失守已消除)、OnSurfaceVariant = 6.383、OnSurface = 12.576。 测试同步:Silver 三条字段用法 pin 从 high 改 highest(与 Ink 对称),并新增 `field_backdrop_is_the_same_role_on_both_boards` 把这个不对称钉住(顺带断言 high 比 highest 更亮、highest 就是规格卡的 #dcddde)。 P2-2 四处小疵: ① inkcat/size.rs 扩展 FAB 起始内距 16 → **28**(规格卡画的数):框 x=292 → 图标盒 320(`+` font-size 24 居中于 x=332),28 才是图上的距离;16 是 M3 官方口径,已在 doc 里登记为偏离, 并说明「要回 M3 的 16 得同时把图标中心挪回 316,那是要出截图的视觉改动」。测试补一条自洽 断言:292 + 28 + 24/2 = 332。 ② inkcat/metrics.rs 的 SWITCH_THUMB_INSET 注释重写(原句断成碎片且读起来像算错):写明 轨道 y=1060..1092 / 拇指 y=1064..1088 ⇒ 上下各 4、右端 116−112=4,以及行程 52−24−2×4 = 20 的推导。 ③ Silver「状态容器 / 容器层」数字统一成实测口径:boards/mod.rs 与 palette/visibility.rs 都写 「最低 1.02」(Ink 1.54),并点名最差的一组是 tertiary-container 压 surface-container-high = 1.016;visibility 表的 Silver 阶梯步长改写 −1.7 ~ −4.1。 ④ inkcat/type_scale.rs 正文清单只列 11 个**文字**字号(去掉 FAB 字形 20/26/34),并注明那三个 归 FabSize::icon_px、SpecText 没有 20 这一档。 P2-3 产品默认口径统一:palettes.rs 的「两个入口」表与 Palettes::baseline 文档、color/mod.rs 的「出厂默认色」小节、Scheme::baseline 文档统一写明「M228 起出厂外观入口是 DesignTokens::brand,本入口是 D38 取色链中性锚点」,与 lib.rs 同口径;顺带把 BASELINE_SEED / DEFAULT_SEED / DEFAULT_NEUTRAL_CHROMA 的「产品默认」措辞改成取色链口径。 另:tests/ink_cat_boards.rs 已 400 行贴线,把 4 条容器层可视性测试拆到新文件 tests/ink_cat_visibility.rs(纯搬移 + 补 import);palettes.rs 因新增口径说明到 403 行,按 「合并相邻段落、不删信息」压回 399 行;size.rs 现在 323 行。 五步(design 口径):fmt --all --check=0;check -p unlucky-design --all-targets=0(零 warning); test -p unlucky-design --all-targets=0(267 passed);clippy -p unlucky-design --all-targets -- -D warnings=0;400 行扫描只剩 README.md(豁免)、无 <2 字节 .rs。
This commit is contained in:
1 parent
0169d4c8fb
commit
b8003177d7
11 files changed
+203
-118
No files matched your search
@@ -46,8 +46,9 @@
|
||||
//! **1.057:1**(m223 视觉复审),Ink 板抬到 **1.97:1**、Silver 板 **1.23:1**;
|
||||
//! - **层级容器**(`surface-container-*`)不参与那条数字门禁,只要求 L\\* 沿阶梯单调、相邻步长
|
||||
//! ≥ [`crate::palette::visibility::LAYER_STEP_MIN_LSTAR`]。M3 的容器层天生贴在一起
|
||||
//! (Silver 的状态容器对 `surface-container-high` 只有 1.05~1.13),所以裁决第 3 条是
|
||||
//! **构成要求**:选中态必须「容器底 + 文字对比 + 形状/图标/描边」三件套,不许只靠底色差。
|
||||
//! (Silver 的状态容器压在容器层上实测最低 **1.02**、Ink 最低 1.54,见 `palette::visibility`
|
||||
//! 的实测表),所以裁决第 3 条是**构成要求**:选中态必须「容器底 + 文字对比 + 形状/图标/描边」
|
||||
//! 三件套,不许只靠底色差。
|
||||
|
||||
mod ink;
|
||||
mod silver;
|
||||
|
||||
@@ -10,6 +10,12 @@ use crate::color::{Color, Role};
|
||||
/// 出处分三处:SILVER CAT / LIGHT SCHEME 的色板行、同页 Filled/Tonal/Outlined 按钮与两个字段
|
||||
/// (`on-primary` 取自 Filled 的文字 `#f6f9ff`、`on-secondary-container` 取自 Tonal 的文字
|
||||
/// `#0d1d2a`、`outline-variant` 取自色板方块的描边 `#bec8cd`)。
|
||||
///
|
||||
/// ⚠️ 字段底 `#dcddde` 落在 **`surface-container-highest`**(不是 high):它与 Ink 的字段底
|
||||
/// `#262b25` 是同一层角色(`component_map` 的 `TextField` 口径 = 最高容器层)。浅色板的
|
||||
/// `surface-container-high` 因此是**推导值** `#e4e4e5`(tone 90),只为让阶梯在 94.1 → 88.1
|
||||
/// 之间保持单调、步长 ≥1.0 L\\*;若把 `#dcddde` 定在 high,Silver 的字段底会比 Ink 低一层,
|
||||
/// 单一角色接法(只读 Highest)会读到 4.38:1 的 `Error` 标签(掉 AA)。
|
||||
pub const ANCHORS: [(Role, &str); 13] = [
|
||||
(Role::Primary, "#006499"),
|
||||
(Role::OnPrimary, "#F6F9FF"),
|
||||
@@ -18,7 +24,7 @@ pub const ANCHORS: [(Role, &str); 13] = [
|
||||
(Role::OnSecondaryContainer, "#0D1D2A"),
|
||||
(Role::Surface, "#F9F9FA"),
|
||||
(Role::SurfaceContainer, "#EEEEEF"),
|
||||
(Role::SurfaceContainerHigh, "#DCDDDE"),
|
||||
(Role::SurfaceContainerHighest, "#DCDDDE"),
|
||||
(Role::OnSurface, "#1A1C1D"),
|
||||
(Role::OnSurfaceVariant, "#434D51"),
|
||||
(Role::Outline, "#6F797D"),
|
||||
@@ -55,8 +61,8 @@ pub const COLORS: [Color; 49] = [
|
||||
Color::rgb(0xFF, 0xFF, 0xFF), // 25 surface-container-lowest [derive] tone 100
|
||||
Color::rgb(0xF3, 0xF3, 0xF4), // 26 surface-container-low [derive] tone 96
|
||||
Color::rgb(0xEE, 0xEE, 0xEF), // 27 surface-container [spec] 卡片/列表行底
|
||||
Color::rgb(0xDC, 0xDD, 0xDE), // 28 surface-container-high [spec] 输入框底
|
||||
Color::rgb(0xD5, 0xD6, 0xD7), // 29 surface-container-highest [derive] tone 86
|
||||
Color::rgb(0xE4, 0xE4, 0xE5), // 28 surface-container-high [derive] tone 90(比 highest 高 2.5 L*,阶梯步长 3.5)
|
||||
Color::rgb(0xDC, 0xDD, 0xDE), // 29 surface-container-highest [spec] 输入框底(与 Ink 的 #262B25 同位:字段底就是最高容器层)
|
||||
Color::rgb(0x6F, 0x79, 0x7D), // 30 outline [spec] 字段描边
|
||||
Color::rgb(0xBE, 0xC8, 0xCD), // 31 outline-variant [spec] 分隔线、chip 描边
|
||||
Color::rgb(0x2F, 0x31, 0x33), // 32 inverse-surface [derive] tone 20
|
||||
|
||||
@@ -53,6 +53,10 @@
|
||||
//!
|
||||
//! ## 出厂默认色(M70:浅冷天蓝)——含**两处**有意偏离(同一处偏离的两半)
|
||||
//!
|
||||
//! > **口径更新(M228)**:出厂外观的入口是 `DesignTokens::brand`(Ink / Silver 两套固化色板,
|
||||
//! > 见 [`crate::color::boards`])。本节描述的「浅冷天蓝」**仍是 D38 取色链的中性锚点**
|
||||
//! > (`Scheme::baseline` / `from_accent` 的表面色基准),不再是「产品出厂看起来长什么样」。
|
||||
//!
|
||||
//! 产品默认不走官方紫,而是「浅冷天蓝」。默认值收在两个常量里,**换默认只改这两行**
|
||||
//! (用户 2026-11-01 拍板采用候选 **④ 天蓝**;③ 浅冷天蓝 `#87CEEB` 留作备选,值仍 pin 在
|
||||
//! `tests/skyseed_candidates.rs`):
|
||||
|
||||
@@ -9,12 +9,12 @@
|
||||
//! 注意 primary 的 36 与种子自身的彩度无关——这是官方口径:Tonal Spot 是「镇静」变体,
|
||||
//! 再鲜艳的种子也会被收到 36,再灰的种子也会被提到 36。
|
||||
//!
|
||||
//! ## 两个入口:官方口径 vs 产品默认(M70)
|
||||
//! ## 两个入口:官方口径 vs 取色链锚点(M70 / M228 口径更新)
|
||||
//!
|
||||
//! | 入口 | 种子 | 中性彩度 | 用途 |
|
||||
//! |---|---|---|---|
|
||||
//! | [`Palettes::official_baseline`] / [`super::Scheme::official_baseline`] | [`BASELINE_SEED`](`#6750A4`) | 6(官方) | 与官方 Java 实现逐角色对齐的**锚点**,`tests/official_baseline.rs` 用它 |
|
||||
//! | [`Palettes::baseline`] / [`super::Scheme::baseline`] | [`DEFAULT_SEED`] | [`DEFAULT_NEUTRAL_CHROMA`] | **产品出厂默认**(消费方拿到的就是它) |
|
||||
//! | [`Palettes::baseline`] / [`super::Scheme::baseline`] | [`DEFAULT_SEED`] | [`DEFAULT_NEUTRAL_CHROMA`] | **D38 取色链的中性锚点**(`from_accent` 的表面色基准)。M228 起**出厂外观**的入口是 `DesignTokens::brand`(Ink / Silver 固化板),不是这里 |
|
||||
//!
|
||||
//! 换默认色只改 [`DEFAULT_SEED`] 与 [`DEFAULT_NEUTRAL_CHROMA`] 两行常量(中性彩度不动就只改一行),
|
||||
//! 然后重跑 `tests/skyseed_candidates.rs` 的 pin(它会打印新值并指出哪几行要同步)。
|
||||
@@ -26,12 +26,12 @@
|
||||
use super::tonal::TonalPalette;
|
||||
use super::Color;
|
||||
|
||||
/// M3 baseline 种子色(与 material-color-utilities 的默认基线同值)。
|
||||
///
|
||||
/// **不是**产品默认色——产品默认见 [`DEFAULT_SEED`]。
|
||||
/// M3 baseline 种子色(与 material-color-utilities 的默认基线同值);**不是**产品色——
|
||||
/// 产品外观见 `DesignTokens::brand`,取色链锚点见 [`DEFAULT_SEED`]。
|
||||
pub const BASELINE_SEED: Color = Color::rgb(0x67, 0x50, 0xA4);
|
||||
|
||||
/// 产品出厂默认种子色 —— M70 候选④「天蓝」,**用户 2026-11-01 拍板采用**。
|
||||
/// 取色链的锚点种子色 —— M70 候选④「天蓝」,**用户 2026-11-01 拍板采用**;M228 起产品出厂
|
||||
/// 外观走 `DesignTokens::brand`(Ink / Silver 固化板),本常量只影响 D38 取色链。
|
||||
///
|
||||
/// `#3C8DBC`(CAM16 hue ≈ 239.5°,主色 `#236488`)。注意种子的彩度(42.6)会被 Tonal Spot
|
||||
/// 丢掉——主色板的彩度恒为 36,种子只贡献**色相**。
|
||||
@@ -41,12 +41,11 @@ pub const BASELINE_SEED: Color = Color::rgb(0x67, 0x50, 0xA4);
|
||||
/// 用户定了三级优先的配色来源:① 启动器背景图取色(Monet)→ ② 桌面壁纸取色 → ③ 莫奈关闭
|
||||
/// (默认)时用户从内置多套色卡里选。本常量 + [`DEFAULT_NEUTRAL_CHROMA`] 只定义**第三级里
|
||||
/// 出厂预选的那一套**(首次启动、用户没选过色卡时的那一套;`palette::DEFAULT_CARD` 的种子即本值)。
|
||||
///
|
||||
/// 取色(量化 + 挑主色)、内置色卡库与三级回落都在 [`crate::palette`](M87,分层见 D40);
|
||||
/// 本模块只负责「给定种子 + 中性彩度,派生出 49 个角色」。
|
||||
pub const DEFAULT_SEED: Color = Color::rgb(0x3C, 0x8D, 0xBC);
|
||||
|
||||
/// 产品出厂默认的中性调色板彩度(官方 Tonal Spot 是 6,这里 12 = **有意偏离**)。
|
||||
/// 取色链的中性调色板彩度(官方 Tonal Spot 是 6,这里 12 = **有意偏离**)。
|
||||
///
|
||||
/// 官方 6 让表面几乎无色;12 让 surface / surface-container-* 带一层淡蓝调,
|
||||
/// 这是「浅冷天蓝」唯一能落在表面上的手段(primary 的 tone 被官方钉在 40,
|
||||
@@ -143,10 +142,11 @@ pub struct Palettes {
|
||||
}
|
||||
|
||||
impl Palettes {
|
||||
/// **产品出厂默认**:种子 [`DEFAULT_SEED`] + 中性彩度 [`DEFAULT_NEUTRAL_CHROMA`]。
|
||||
/// **D38 取色链的中性锚点**:种子 [`DEFAULT_SEED`] + 中性彩度 [`DEFAULT_NEUTRAL_CHROMA`]。
|
||||
///
|
||||
/// 消费方(`DesignTokens::baseline`、iced 适配层)拿到的就是这套,所以产品默认色
|
||||
/// 只需要改那两个常量。
|
||||
/// 用途只剩一条:给「莫奈关闭时的机内色卡」与 [`super::Scheme::from_accent`] 提供中性表面色
|
||||
/// 基准。**M228 起产品出厂外观走 `DesignTokens::brand`**([`super::boards::BrandBoard`] 的
|
||||
/// Ink / Silver 板),改这两个常量**不再改变用户看到的默认外观**,只影响取色链。
|
||||
pub fn baseline() -> Self {
|
||||
Self::from_seed_with_neutral_chroma(DEFAULT_SEED, DEFAULT_NEUTRAL_CHROMA)
|
||||
}
|
||||
|
||||
@@ -179,8 +179,12 @@ pub struct Scheme {
|
||||
}
|
||||
|
||||
impl Scheme {
|
||||
/// **产品出厂默认方案**(种子 [`super::palettes::DEFAULT_SEED`] + 中性彩度
|
||||
/// **D38 取色链的中性锚点**(种子 [`super::palettes::DEFAULT_SEED`] + 中性彩度
|
||||
/// [`super::palettes::DEFAULT_NEUTRAL_CHROMA`],见 [`Palettes::baseline`])。
|
||||
///
|
||||
/// M228 起**产品出厂外观**走 [`Scheme::from_board`](Ink / Silver 固化色板);本入口保留给
|
||||
/// 取色链与 [`Scheme::from_accent`] 的表面色基准,两者并列而不是互相替换(理由见
|
||||
/// [`super::boards`] 的模块文档)。
|
||||
pub fn baseline(flavor: SchemeFlavor) -> Self {
|
||||
Self::from_palettes(&Palettes::baseline(), flavor)
|
||||
}
|
||||
|
||||
@@ -138,7 +138,11 @@ pub const SWITCH_TRACK: SpecBox = SpecBox {
|
||||
};
|
||||
/// 开关拇指直径(px)。
|
||||
pub const SWITCH_THUMB: f32 = 24.0;
|
||||
/// 拇指相对轨道的内缩(px):拇指 `x=88` − 轨道 `x=64` − 描边 …= 实测 0 起点 24 偏移、右端留 4。
|
||||
/// 拇指相对轨道的内缩(px):规格卡轨道 `y=1060..1092`、拇指 `y=1064..1088`,上下各 **4**;
|
||||
/// 右端 `116−112` 同为 4。
|
||||
///
|
||||
/// 位移行程(拇指可从左滑到右的距离)= 轨道宽 52 − 拇指 24 − 2×内缩 4 = **20**(规格卡没写行程,
|
||||
/// 这是由前三项推出来的唯一值;写死 20 就是第四份副本)。
|
||||
pub const SWITCH_THUMB_INSET: f32 = 4.0;
|
||||
/// 关态拇指直径(px):规格卡 `16×16 rx8`。
|
||||
pub const SWITCH_THUMB_OFF: f32 = 16.0;
|
||||
|
||||
@@ -219,10 +219,18 @@ impl FabSize {
|
||||
}
|
||||
}
|
||||
|
||||
/// 起始内距(px;只有 Extended 有:图标左边 = 16)。
|
||||
/// 起始内距(px;只有 Extended 有):**28**,规格卡画的就这个数。
|
||||
///
|
||||
/// 推导(可逐位核):框 `x=292` 起、宽 160;`+` 是 `font-size=24`、`text-anchor=middle`、
|
||||
/// 中心 `x=332` ⇒ 图标盒 = 320..344 ⇒ 内距 = 320 − 292 = **28**;标签 `x=352` 起,
|
||||
/// 于是图标盒右沿 344 到标签 352 = [`FabSize::gap_px`] 的 8。
|
||||
///
|
||||
/// ⚠️ 与官方口径的偏离已登记:M3 ExtendedFAB 的起始内距是 **16**(图标盒 292+16=308)。
|
||||
/// 规格卡画得更宽松,本表按**规格卡**取值(A 级依据 = 图中坐标,不是猜的);M229 若要用
|
||||
/// M3 的 16,得同时把图标中心从 332 挪回 316 —— 那是一处视觉改动,要出截图,别悄悄改数。
|
||||
pub const fn pad_start_px(self) -> f32 {
|
||||
match self {
|
||||
FabSize::Extended => 16.0,
|
||||
FabSize::Extended => 28.0,
|
||||
_ => 0.0,
|
||||
}
|
||||
}
|
||||
@@ -290,7 +298,10 @@ mod tests {
|
||||
assert_eq!(FabSize::Extended.width_px(), 160.0);
|
||||
assert_eq!(FabSize::Extended.height_px(), 56.0);
|
||||
assert_eq!(FabSize::Extended.label_px(), 15.0);
|
||||
assert_eq!(FabSize::Extended.pad_start_px(), 16.0);
|
||||
// 内距 28 = 规格卡图中「框 292 → 图标盒 320」的实测距离(不是 M3 的 16)。
|
||||
assert_eq!(FabSize::Extended.pad_start_px(), 28.0);
|
||||
// 图标中心落点必须自洽:292 + 28 + 24/2 = 332,与规格卡 `x=332` 对得上。
|
||||
assert_eq!(FabSize::Extended.pad_start_px() + 24.0 / 2.0 + 292.0, 332.0);
|
||||
assert_eq!(FabSize::Extended.gap_px(), 8.0);
|
||||
// 图标字号随档递增(扩展态回到 24,因为它跟标签同一行)。
|
||||
assert!(FabSize::Small.icon_px() < FabSize::Default.icon_px());
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
//! 规格卡字号 → 官方 type scale 的**校核**(不是又一张字号表)。
|
||||
//!
|
||||
//! 规格卡上每一处文字都写了 `font-size`:40 / 32 / 24 / 20 / 16 / 15 / 14 / 13 / 12 / 11 / 10 / 9。
|
||||
//! 规格卡上每一处**文字**都写了 `font-size`,去重共 11 档:
|
||||
//! 40 / 32 / 24 / 16 / 15 / 14 / 13 / 12 / 11 / 10 / 9。
|
||||
//! 其中一部分**命中** M3 的 15 档(14 / 16 / 24 / 32 / 12 / 11),一部分**落在两档之间**
|
||||
//! (13 / 15 / 40),还有一部分**低于本项目允许的 UI 下限**(10 / 9)。
|
||||
//!
|
||||
//! 规格卡上另有 20 / 26 / 34 三个字号,但它们是 **FAB 的图形符号(`+` 字形)**,不是文字——
|
||||
//! 归 [`crate::inkcat::size::FabSize::icon_px`] 管,本模块不收录(`SpecText` 里没有 20 这一档)。
|
||||
//!
|
||||
//! 本模块的职责就是把「规格卡字级」翻译成这三类结论,让换肤时不用逐个拿卷尺量:
|
||||
//!
|
||||
//! | 结论 | 含义 | 处置 |
|
||||
|
||||
@@ -14,25 +14,27 @@
|
||||
//! `surface` 上时必须数得出来。这是唯一一条**数字门禁**,[`SurfaceHierarchy::state_failures`]
|
||||
//! 守它。
|
||||
//! 3. **容器层之间的亮度差不设门禁,改为「组合指示」要求**:M3 的容器层天生贴在一起
|
||||
//! (官方口径浅色 `secondary-container` 对 `surface-container-high` 只有 1.05:1,
|
||||
//! 深色也只有 1.54:1 —— 这是配色结构的必然,不是哪套板的失误)。所以
|
||||
//! (官方口径浅色 `secondary-container` 对 `surface-container-high` 只有 1.06:1,
|
||||
//! 本项目 Ink 板最低也只有 1.54:1 —— 这是配色结构的必然,不是哪套板的失误)。所以
|
||||
//! **禁止**把「容器底色差异」当作唯一的选中 / 层级指示:选中态必须是
|
||||
//! 「容器底(过第 2 条)+ 文字对比(第 1 条)+ 形状 / 图标 / 描边指示」三件套。
|
||||
//! 另一半同理:`surface-container-*` 只表达「几乎看不见的抬升」,
|
||||
//! 拿它当选中态用连第 2 条都过不了。
|
||||
//!
|
||||
//! 第 3 条为什么不是「把阈值降到 1.05 就完事」:那样等于承认「选中态可以看不见」,
|
||||
//! 第 3 条为什么不是「把阈值降到 1.02 就完事」:那样等于承认「选中态可以看不见」,
|
||||
//! 而用户抱怨的正是这个。把不可测的那一半转成**构成要求**,才是能落地的那一半。
|
||||
//!
|
||||
//! ## 实测(`tests/ink_cat_boards.rs` 守住第 2 条与阶梯)
|
||||
//!
|
||||
//! | 板 | 最弱状态容器 / `surface` | 状态容器 / 最亮(深)或最暗(浅)的容器层 | 阶梯 L\\* 步长 |
|
||||
//! | 板 | 最弱状态容器 / `surface` | 状态容器 / 容器层(最低 ~ 最高) | 阶梯 L\\* 步长 |
|
||||
//! |---|---|---|---|
|
||||
//! | Ink | **1.97**(secondary-container) | 1.54 ~ 12.13 | +1.4 ~ +4.4 |
|
||||
//! | Silver | **1.23**(tertiary/error-container) | 1.05 ~ 1.24 | −1.8 ~ −6.1 |
|
||||
//! | Silver | **1.23**(tertiary/error-container) | **1.02** ~ 1.80 | −1.7 ~ −4.1 |
|
||||
//! | 旧 baseline(债务现场) | 1.23 | **1.057**(对卡片,m223 实测) | — |
|
||||
//!
|
||||
//! 第三列就是第 3 条的由来:它过不了任何有意义的门禁,所以不设门禁、只设组合要求。
|
||||
//! 第三列就是第 3 条的由来:它过不了任何有意义的门禁(Silver 最差的一组是
|
||||
//! `tertiary-container` 压 `surface-container-high`,1.016 —— 两者几乎同亮度),
|
||||
//! 所以不设门禁、只设组合要求。
|
||||
//!
|
||||
//! ## 阶梯本身还是要查([`SurfaceHierarchy::layer_violations`])
|
||||
//!
|
||||
|
||||
Reference in new issue
Block a user