fix(app-iced): 列表行圆角改从组件表取(M287)
`list_item.rs` 硬写 `ui.radius_dp(ShapeScale::None)`,旁边还写着「4.x:ListItem 的形状 是 `CornerNone`(直角),没有圆角档」——而令牌表 `component_map::table` 的 `ListItem` 是 `Small(8)`。产品侧根本没读表,注释在替错误站台。 改为 `row_border(ui)` → `ui.radius_dp(Component::ListItem.spec().shape)`,数值只留在 令牌表。变异实测(只改表的那一行 `Small→Large`):行圆角 8 → 16,240×60 选中行的顶行 缩进 6 → 13;改回后 11 张图逐字节复原(`DevDocs/artifacts/listradius/`,不入库)。 同 commit 改掉那条直角注释、模块文档补 4.9 行,并加两条单测:渲染路径的 `Border.radius` = 表值折算;源码里不许再出现硬编码的 `ShapeScale::*` 档。 外观影响的边界(写进取证报告):行只在 选中/悬停/按下 时有容器色,未选中静息与禁用 两态 `fill` 为 `None`,那两态逐字节不变是**正确**的,不是没生效。
This commit is contained in:
1 parent
a07cda34cb
commit
5174845cda
2 files changed
+80
-5
No files matched your search
@@ -11,6 +11,7 @@
|
|||||||
//! | 4.5 | 字级 | 主 `BodyLarge 16/24`、辅助 `BodyMedium 14/20`、overline `LabelSmall 11/16` | `TypeRole` |
|
//! | 4.5 | 字级 | 主 `BodyLarge 16/24`、辅助 `BodyMedium 14/20`、overline `LabelSmall 11/16` | `TypeRole` |
|
||||||
//! | 4.7 | 状态 | hover/focus/pressed **文本与图标色不变**,只叠状态层(8/10/10%) | [`interaction`] |
|
//! | 4.7 | 状态 | hover/focus/pressed **文本与图标色不变**,只叠状态层(8/10/10%) | [`interaction`] |
|
||||||
//! | 4.8 | 选中 trailing | 图标 → **`Primary`** | `Role::Primary` |
|
//! | 4.8 | 选中 trailing | 图标 → **`Primary`** | `Role::Primary` |
|
||||||
|
//! | 4.9 | 圆角 | 官方 `ListTokens` 是 `CornerNone`(直角);本项目**登记偏离**取 **8**(`Small`) | `Component::ListItem.spec().shape`(M287) |
|
||||||
//!
|
//!
|
||||||
//! ## 禁用是**修饰器**,不是构造函数(照 `selection/chip.rs` 复审 P2-1 的结论)
|
//! ## 禁用是**修饰器**,不是构造函数(照 `selection/chip.rs` 复审 P2-1 的结论)
|
||||||
//!
|
//!
|
||||||
@@ -44,6 +45,7 @@ use iced::widget::{button, container, text};
|
|||||||
use iced::{Alignment, Background, Border, Color, Element, Length, Padding, Pixels, Shadow};
|
use iced::{Alignment, Background, Border, Color, Element, Length, Padding, Pixels, Shadow};
|
||||||
|
|
||||||
use unlucky_design::color::Role;
|
use unlucky_design::color::Role;
|
||||||
|
use unlucky_design::component_map::Component;
|
||||||
use unlucky_design::icons::IconKind;
|
use unlucky_design::icons::IconKind;
|
||||||
use unlucky_design::shape::ShapeScale;
|
use unlucky_design::shape::ShapeScale;
|
||||||
|
|
||||||
@@ -193,6 +195,28 @@ fn palette(ui: &Ui, base: Base, state: Interaction, selected: bool) -> ItemPalet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 一行的圆角档位:**只从组件表取**(`Component::ListItem.spec().shape`)。
|
||||||
|
///
|
||||||
|
/// 官方 `ListTokens` 是 `CornerNone`(直角行),本项目取 `Small`(8)——列表行在启动器里是
|
||||||
|
/// 卡片内的**独立可点块**,不是贴边通栏行,圆角与卡片同族更协调(偏离登记见
|
||||||
|
/// `crates/design/src/component_map/table.rs` 的 `ListItem` 条目)。
|
||||||
|
///
|
||||||
|
/// 数值归令牌表,**产品侧不许在这里再写一份**:改表值 ⇒ 行圆角跟着变(M287 的判据)。
|
||||||
|
fn shape_scale() -> ShapeScale {
|
||||||
|
Component::ListItem.spec().shape
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 一行的描边:只画圆角,四边宽度与色都不画(`Border::default()` 的其余字段)。
|
||||||
|
///
|
||||||
|
/// 单独成函数是为了让「圆角真的来自组件表」可被单测直接量到
|
||||||
|
/// (`tests::row_corner_comes_from_the_component_table`)。
|
||||||
|
fn row_border(ui: &Ui) -> Border {
|
||||||
|
Border {
|
||||||
|
radius: ui.radius_dp(shape_scale()),
|
||||||
|
..Border::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 一行文本(显式行高:三行块的 16+24+20 必须能精确等于 60,靠的就是它)。
|
/// 一行文本(显式行高:三行块的 16+24+20 必须能精确等于 60,靠的就是它)。
|
||||||
fn line<'a, M: 'a>(
|
fn line<'a, M: 'a>(
|
||||||
ui: &'a Ui,
|
ui: &'a Ui,
|
||||||
@@ -285,17 +309,14 @@ pub fn list_item<'a, M: Clone + 'a>(ui: &'a Ui, item: ListItem<'a, M>) -> Elemen
|
|||||||
|
|
||||||
let selected = item.selected;
|
let selected = item.selected;
|
||||||
let base = item.base;
|
let base = item.base;
|
||||||
|
let border = row_border(ui);
|
||||||
let style = move |_theme: &iced::Theme, status: button::Status| {
|
let style = move |_theme: &iced::Theme, status: button::Status| {
|
||||||
let state = forced.unwrap_or_else(|| Interaction::from_status(status));
|
let state = forced.unwrap_or_else(|| Interaction::from_status(status));
|
||||||
let colors = palette(ui, base, state, selected);
|
let colors = palette(ui, base, state, selected);
|
||||||
button::Style {
|
button::Style {
|
||||||
background: colors.fill.map(Background::Color),
|
background: colors.fill.map(Background::Color),
|
||||||
text_color: colors.headline,
|
text_color: colors.headline,
|
||||||
// 4.x:ListItem 的形状是 `CornerNone`(直角),没有圆角档
|
border,
|
||||||
border: Border {
|
|
||||||
radius: ui.radius_dp(ShapeScale::None),
|
|
||||||
..Border::default()
|
|
||||||
},
|
|
||||||
shadow: Shadow::default(),
|
shadow: Shadow::default(),
|
||||||
snap: true,
|
snap: true,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,6 +98,60 @@ fn interaction_states_keep_the_content_colors() {
|
|||||||
assert_eq!(resting.fill, None, "静息态不叠状态层");
|
assert_eq!(resting.fill, None, "静息态不叠状态层");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 行的圆角**读组件表**(`Component::ListItem.spec().shape`),不是在这里另写一个常量。
|
||||||
|
///
|
||||||
|
/// 抓得住:渲染路径用的 `Border.radius` = 组件表里 `ListItem` 那一行的 `shape` 折算出的 dp;
|
||||||
|
/// 表值不是 `None`(直角),而 `Small` = 8。
|
||||||
|
/// 抓不住:有人把 `row_border` 换成一个**数值恰好相同**的字面常量(`ShapeScale::Small`)——
|
||||||
|
/// 见 `render_path_reads_the_table` 的源码结构断言,以及 M287 的变异图(改表值 ⇒ 图跟着变)。
|
||||||
|
#[test]
|
||||||
|
fn row_corner_comes_from_the_component_table() {
|
||||||
|
let ui = ui();
|
||||||
|
let spec = Component::ListItem.spec();
|
||||||
|
assert_eq!(spec.shape, ShapeScale::Small, "组件表的 ListItem 档位");
|
||||||
|
assert_eq!(spec.micro_radius, None, "ListItem 不走 D32 的微圆角层");
|
||||||
|
assert_eq!(
|
||||||
|
row_border(&ui),
|
||||||
|
Border {
|
||||||
|
radius: ui.radius_dp(spec.shape),
|
||||||
|
..Border::default()
|
||||||
|
},
|
||||||
|
"行的圆角必须就是组件表那一档折算出来的"
|
||||||
|
);
|
||||||
|
assert_eq!(row_border(&ui).radius.top_left, 8.0, "Small = 8dp");
|
||||||
|
assert_ne!(
|
||||||
|
row_border(&ui),
|
||||||
|
Border {
|
||||||
|
radius: ui.radius_dp(ShapeScale::None),
|
||||||
|
..Border::default()
|
||||||
|
},
|
||||||
|
"M287 之前这里是 `ShapeScale::None`(直角):退回去会红"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 源码结构(`Element` 没有内省接口,见 `pages::layout::source` 的同一条纪律):
|
||||||
|
/// 渲染路径必须**从组件表取**圆角,文件里不许再出现硬编码的圆角档。
|
||||||
|
#[test]
|
||||||
|
fn render_path_reads_the_table() {
|
||||||
|
let source = include_str!("../list_item.rs");
|
||||||
|
assert!(
|
||||||
|
source.contains("Component::ListItem.spec().shape"),
|
||||||
|
"行的圆角必须读组件表(`Component::ListItem.spec().shape`)"
|
||||||
|
);
|
||||||
|
for hardcoded in [
|
||||||
|
"ShapeScale::None",
|
||||||
|
"ShapeScale::Small",
|
||||||
|
"ShapeScale::ExtraSmall",
|
||||||
|
"ShapeScale::Medium",
|
||||||
|
"ShapeScale::Large",
|
||||||
|
] {
|
||||||
|
assert!(
|
||||||
|
!source.contains(hardcoded),
|
||||||
|
"{hardcoded} 是硬编码圆角档:ListRow 的圆角只许从组件表取"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 三档行高与 `LM.row_height` 的关系**钉死**(有人按 A1 改回 56 时这里会红)。
|
/// 三档行高与 `LM.row_height` 的关系**钉死**(有人按 A1 改回 56 时这里会红)。
|
||||||
#[test]
|
#[test]
|
||||||
fn heights_are_pinned_to_the_row_height_token() {
|
fn heights_are_pinned_to_the_row_height_token() {
|
||||||
|
|||||||
Reference in new issue
Block a user