- pages/settings/frame.rs:分组导航从 mouse_area 换成 button(四态可辨), 几何不变(ShapeScale::Full 胶囊),颜色走唯一的 selected_fill;forced 从 settings::view 递下来,于是 --force-state 能拍到这一处 - language / theme / appearance choice 三处「选中档位」补状态层 - components/selection/paint/chip.rs:选中分支用上 state 参数 - shell/nav.rs / shell/nav/account.rs:两处私有拷贝收口到 selected_fill(几何没动) - components/navigation/tabs.rs:状态层在样式闭包里跟 button::Status 求值 - 新增门禁 selection/tests/single_entry.rs:11 个站点必须调 selected_fill + 产品代码里不许再出现 or_else(|| Some(ui.color( 这个私有拷贝形态 - 行数:frame.rs / nav.rs / appearance::section 的单测按「纯搬移」拆出去
119 lines
4.4 KiB
Rust
119 lines
4.4 KiB
Rust
//! `appearance::section` 的单测(M299 从 `mod.rs` 纯搬移,守 400 行硬线)。
|
||
//!
|
||
//! 判据与注释一字未动,只是**换文件**:`mod.rs` 加了一条「选中的档位跟态走」之后到 438 行。
|
||
//! 模块路径仍是 `appearance::section::tests`(`mod.rs` 里改成 `mod tests;`),`super::*` 拿到的
|
||
//! 还是 `appearance::section`。
|
||
|
||
use super::*;
|
||
use unlucky_design::color::{SchemeFlavor, StateLayer};
|
||
use unlucky_design::typography::Platform;
|
||
|
||
use crate::theme::Families;
|
||
|
||
fn ui() -> Ui {
|
||
Ui::with_platform(
|
||
SchemeFlavor::Light,
|
||
Platform::Windows,
|
||
Families {
|
||
text: "Segoe UI",
|
||
display: "Segoe UI",
|
||
mono: "Consolas",
|
||
},
|
||
)
|
||
}
|
||
|
||
fn solid(style: button::Style) -> Color {
|
||
match style.background {
|
||
Some(Background::Color(color)) => color,
|
||
None => panic!("未选中态的 hover/pressed 必须叠状态层"),
|
||
Some(other) => panic!("背景必须是实色,得到 {other:?}"),
|
||
}
|
||
}
|
||
|
||
/// hover(8%) 与 pressed(10%) 是**两档**,且各自逐值等于令牌表(把 10% 改成 11% 也会红)。
|
||
///
|
||
/// 抓得住:①回到 `matches!(status, Hovered | Pressed)` 合并分支(两色相等 ⇒ 第一条红);
|
||
/// ②pressed 用 hover 的 α、或合成底被换回画布(第二、三条红)。
|
||
/// 抓不住:观感;**过渡中间帧**(forced 路径不套 `tracked`,`layer_color` 直落端点值)。
|
||
///
|
||
/// 底的角色取 `MaterialLayer::Card.surface_role()`(`frame::BASE` 就是它):既盯住「叠的是卡底」
|
||
/// 这条语义,也不往 `settings/*.rs` 的接线点计数里多塞一次字面量(`pages/tests/base_wiring.rs`)。
|
||
#[test]
|
||
fn the_choice_button_draws_pressed_darker_than_hover() {
|
||
let ui = ui();
|
||
let style = choice_style(
|
||
&ui,
|
||
false,
|
||
ui.color(Role::OnSurfaceVariant),
|
||
ui.radius(ShapeScale::Full, ui.metrics().control_height),
|
||
None,
|
||
);
|
||
let theme = ui.theme();
|
||
let hover = solid(style(&theme, button::Status::Hovered));
|
||
let pressed = solid(style(&theme, button::Status::Pressed));
|
||
|
||
assert_ne!(hover, pressed, "hover 与 pressed 必须是两档(8% / 10%)");
|
||
let base = MaterialLayer::Card.surface_role();
|
||
assert_eq!(
|
||
hover,
|
||
ui.state_over(StateLayer::Hover, Role::OnSurface, base)
|
||
);
|
||
assert_eq!(
|
||
pressed,
|
||
ui.state_over(StateLayer::Pressed, Role::OnSurface, base)
|
||
);
|
||
assert!(
|
||
style(&theme, button::Status::Active).background.is_none(),
|
||
"静息态不叠状态层"
|
||
);
|
||
}
|
||
|
||
/// **选中的档位也跟态走**(M299):底是实色 `SecondaryContainer`,状态层叠在它上面。
|
||
///
|
||
/// 抓得住:①把选中支改回 `Some(ui.color(SecondaryContainer))`(= 选中就不响应)⇒ hover /
|
||
/// pressed 都等于静息,前三条红;②hover 与 pressed 同 α ⇒ 第四条红;③合成底被换掉 ⇒ 后两条
|
||
/// 逐值断言红。
|
||
/// 抓不住:像素(`DevDocs/artifacts/m299/settings-appearance-*-hover|pressed.png`,`--force-state`
|
||
/// 经 `settings::view` → `appearance::section` 的 `forced`);也抓不住「自己抄了一份**正确**的
|
||
/// 叠层」——由 `selection/tests/single_entry.rs` 的接线扫描负责。
|
||
#[test]
|
||
fn a_selected_choice_reacts_to_hover_and_press() {
|
||
let ui = ui();
|
||
let style = choice_style(
|
||
&ui,
|
||
true,
|
||
ui.color(Role::OnSecondaryContainer),
|
||
ui.radius(ShapeScale::Full, ui.metrics().control_height),
|
||
None,
|
||
);
|
||
let theme = ui.theme();
|
||
let rest = solid(style(&theme, button::Status::Active));
|
||
let hover = solid(style(&theme, button::Status::Hovered));
|
||
let pressed = solid(style(&theme, button::Status::Pressed));
|
||
|
||
assert_eq!(
|
||
rest,
|
||
ui.color(Role::SecondaryContainer),
|
||
"选中静息 = 实色容器"
|
||
);
|
||
assert_ne!(hover, rest, "选中 + hover 必须与静息不同");
|
||
assert_ne!(pressed, rest, "选中 + pressed 必须与静息不同");
|
||
assert_ne!(hover, pressed, "8% 与 10% 必须能区分");
|
||
assert_eq!(
|
||
hover,
|
||
ui.state_over(
|
||
StateLayer::Hover,
|
||
Role::OnSecondaryContainer,
|
||
Role::SecondaryContainer
|
||
)
|
||
);
|
||
assert_eq!(
|
||
pressed,
|
||
ui.state_over(
|
||
StateLayer::Pressed,
|
||
Role::OnSecondaryContainer,
|
||
Role::SecondaryContainer
|
||
)
|
||
);
|
||
}
|