feat(settings): M299 选中项收口到 selected_fill + 分组导航改真按钮 + tabs 用 status

- 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 的单测按「纯搬移」拆出去
This commit is contained in:
AskaEth committed 2026-11-13 14:41:57 +08:00
1 parent 9b6e92c7b4
commit 0d917e88da
16 files changed
+1072 -355

No files matched your search

+45 -7
View File
@@ -175,20 +175,22 @@ pub(super) fn account_item<'a>(
}
}
/// 头像圆的底色(**唯一**实现点):hover / pressed / 过渡帧都画在这个 Ø40 圆上。
/// 头像圆的底色(**几何**的唯一实现点):hover / pressed / 过渡帧都画在这个 Ø40 圆上。
///
/// 两条分支不许合并(照 `drawer/item.rs` 的 `pill_color`):已登录的头像静息是实色
/// `SecondaryContainer`,缺层时兜底到那个角色;未登录的头像静息只有描边、不填底,
/// 兜底就必须是 `None`。
/// **颜色**只有一个来源:已登录支走 [`interaction::selected_fill`](全仓唯一的选中底色入口,
/// M299 收口了这里的私有拷贝),未登录支走 [`interaction::layer_color`]。两条分支不许合并:
/// 已登录的头像静息是实色 `SecondaryContainer`(`selected_fill` 的兜底),未登录的头像静息只有
/// 描边、不填底(`layer_color` 给 `None`)。
fn avatar_color(ui: &Ui, state: Interaction, signed_in: bool) -> Option<Color> {
if signed_in {
interaction::layer_color(
// 同一个唯一入口(M299):已登录头像的静息底是实色 `SecondaryContainer`,
// hover / pressed 叠在它上面——此前这里是第五份私有拷贝。
Some(interaction::selected_fill(
ui,
state,
Role::OnSecondaryContainer,
Role::SecondaryContainer,
)
.or_else(|| Some(ui.color(Role::SecondaryContainer)))
))
} else {
// 头像直接摆在导航轨上(轨画的是 `MaterialLayer::Canvas`):状态层要叠在同一个角色上。
interaction::layer_color(
@@ -220,6 +222,42 @@ mod tests {
assert!(compacted.compact, "compact(true) 必须收成图标条");
}
/// **已登录头像也跟态走**,且走的是全仓唯一的那个入口(M299)。
///
/// 抓得住:把 `signed_in` 支改回「选中就不叠层」⇒ hover / pressed 都等于静息,前两条红;
/// hover 与 pressed 同源 ⇒ 第三条红。未登录支(只有描边、不填底)一并钉住。
/// 抓不住:像素(`DevDocs/artifacts/m299/shell-account-*`);Ø40 几何本次没动。
#[test]
fn the_signed_in_avatar_reacts_to_hover_and_press() {
use unlucky_design::color::SchemeFlavor;
use unlucky_design::typography::Platform;
use crate::theme::Families;
let ui = Ui::with_platform(
SchemeFlavor::Light,
Platform::Windows,
Families {
text: "Segoe UI",
display: "Segoe UI",
mono: "Consolas",
},
);
let fill = |state| avatar_color(&ui, state, true).expect("已登录静息也有底");
let rest = fill(Interaction::Enabled);
let hover = fill(Interaction::Hovered);
let pressed = fill(Interaction::Pressed);
assert_eq!(rest, ui.color(Role::SecondaryContainer));
assert_ne!(hover, rest, "已登录 + hover 必须与静息不同");
assert_ne!(pressed, rest, "已登录 + pressed 必须与静息不同");
assert_ne!(hover, pressed, "8% 与 10% 必须能区分");
// 未登录:静息不填底,hover 才有状态层
assert_eq!(avatar_color(&ui, Interaction::Enabled, false), None);
assert!(avatar_color(&ui, Interaction::Hovered, false).is_some());
}
#[test]
fn the_avatar_slot_fits_the_rail() {
use unlucky_design::color::SchemeFlavor;