fix(design): M69 r1 —— SEARCH_BAR 内边距语义收口 + ComponentRadius 取值口上闸

P2-1(语义缝隙):`SEARCH_BAR` 的 pad_start / pad_end 原为 16,与
icon_offset = 4 按字面相加得 20,比官方图标可视边 16 多 4px(越过 rubric
±2px 容差);而被加数的 12 不在 CM 里,消费方只能自己写 12.0 —— 正是 G10
要消灭的字面量。改为 12(文本框内容内边距,Space::X3)+ 4,两侧同式:
图标可视边 = pad + icon_offset = 16。字段文档写明求和公式;测试钉死
pad + offset == 16 且 pad != 16(防有人把 16 写回 pad 再叠加)。
顺带给 SEARCH_BAR.gap 补 [估] 出处(官方无图标↔文字 token)。

P2-2(绕过路径):ComponentRadius::dp() 收成 pub(crate)。它不看尺寸、
无条件返回 2.0,公开等于把 D32 的尺寸闸交给自觉。对外唯一取值口是
radius_px(size) -> Option<f32>;ALL 只暴露变体名、不暴露数值。
tokext_pins 原用 dp(),改为紧邻的 radius_px(20.0) == Some(2.0),覆盖不丢。

顺手:修掉本轮新引入的 rustdoc warning(component_map 文档链到私有模块
metrics,改指 ComponentMetrics);Divider 行标注 motion/duration 为占位,
并在 ComponentSpec 的 text / motion 字段文档写明「无文字 / 无动效的组件
这里是占位值,消费方不得据此排版 / 排动效」。

门禁:test 165 全绿、fmt --check、clippy -D warnings、check --workspace
--all-targets、doc(warning 2 → 1,只剩既有的 typography→emphasized 一条)。
This commit is contained in:
AskaEth committed 2026-11-01 17:05:19 +08:00
1 parent 141e9b12c7
commit 16bdad1b98
5 files changed
+50 -17

No files matched your search

+16 -6
View File
@@ -42,17 +42,19 @@ fn shape_scale_is_unchanged_and_never_contains_two() {
#[test]
fn component_radius_is_a_one_item_whitelist() {
assert_eq!(ComponentRadius::ALL, [ComponentRadius::Micro]);
// 2dp 只能通过带尺寸闸的 `radius_px` 拿到(`dp()` 是 crate 内部口,外部看不见)。
assert_eq!(
ComponentRadius::Micro.dp(),
2.0,
ComponentRadius::Micro.radius_px(20.0),
Some(2.0),
"官方 Checkbox RadiusSize = 2.dp"
);
// 尺寸闸:>24dp 一律拿不到微半径(D32 的「只允许 ≤24dp 微控件」)。
assert_eq!(ComponentRadius::Micro.radius_px(20.0), Some(2.0));
assert_eq!(ComponentRadius::Micro.radius_px(24.0), Some(2.0));
assert_eq!(ComponentRadius::Micro.radius_px(25.0), None);
assert_eq!(ComponentRadius::Micro.radius_px(240.0), None);
assert_eq!(ComponentRadius::Micro.radius_px(0.0), None);
// 边长小于两倍半径时按边长一半折算(2dp 元素不能有 2dp 圆角)。
assert_eq!(ComponentRadius::Micro.radius_px(2.0), Some(1.0));
}
#[test]
@@ -149,10 +151,16 @@ fn search_bar_metrics_are_pinned() {
// 高 56 属骨架级:CM 里必须留 0,不许重复一份。
assert_eq!((cm.width, cm.height), (0.0, 0.0));
assert_eq!(cm.icon, IconSize::Toolbar.px(), "leading/trailing 图标 24");
// A 级(§20.4):图标可视左缘 16 = 文本框内容内边距 12 + `SearchBarIconOffsetX = 4`。
assert_eq!(cm.pad_start, Space::X3.dp(), "内容内边距 12");
assert_eq!(cm.icon_offset, 4.0, "SearchBarIconOffsetX = 4");
// 可视左缘 16 = 文本框默认 12 + 偏移 4。
assert_eq!(cm.pad_start, Space::X4.dp());
assert_eq!(cm.pad_end, Space::X4.dp());
assert_eq!(cm.pad_start + cm.icon_offset, 16.0, "图标可视左缘必须是 16");
// 右侧同式:图标右缘也是 16。
assert_eq!(cm.pad_end, Space::X3.dp());
assert_eq!(cm.pad_end + cm.icon_offset, 16.0, "图标可视右缘必须是 16");
// 守门:不许把 pad 本身写成 16(否则 pad + offset = 20,越过 rubric 的 ±2px)。
assert_ne!(cm.pad_start, 16.0);
assert_ne!(cm.pad_end, 16.0);
// 搜索条圆角 = 高/2 = 28,等于官方 SearchBarCornerRadius。
assert_eq!(
ShapeScale::Full.radius_px(LayoutMetrics::DESKTOP.search_bar_height),
@@ -171,6 +179,8 @@ fn navigation_drawer_metrics_are_pinned() {
assert_eq!(cm.pad_start, Space::X4.dp(), "项内 start 16");
assert_eq!(cm.pad_end, Space::X6.dp(), "项内 end 24");
assert_eq!(cm.icon, IconSize::Toolbar.px());
// 与 search bar 同一条公式:图标边 = pad + icon_offset(抽屉的 offset 是 0)。
assert_eq!(cm.pad_start + cm.icon_offset, 16.0, "图标起点 = 项内 start");
assert_eq!(cm.gap, Space::X3.dp(), "图标 ↔ label 12");
// 指示器宽 = 容器宽 − 24;官方 360 − 24 = 336,本项目 240 − 24 = 216。
assert_eq!(cm.indicator_width(360.0), 336.0);