feat(app-iced): 禁用态合成底改成容器给的 Base(M234)
`interaction::disabled` 的四个入口一直收一个「底」,但 8 个调用点全传死 `Role::Surface`:卡片(SurfaceContainer)/ 面板(SurfaceContainerLow)里的禁用控件 把 10%(按钮族)/ 12%(面状控件族)叠在画布色上 —— M223「CR 1.05、形丢失」的根因。 - 新增 `interaction::Base`(画布 / 容器底的一等参数,`From<Role>` 兼容历史调用点); 四个入口改成 `(ui, base, …)`,内部不再出现任何写死的 `Role::Surface`。 - 容器导出自己的 `BASE`:`surfaces::elevated::BASE`(卡)、`inputs::menu::PANEL_BASE` (菜单面板,项的 38% 与状态层都改叠它)、`navigation::drawer::BASE`。 - 控件收 `.base(..)`:Button / icon_on / Field / SearchBar / Slider / Checkbox / Radio / Switch / Chip / ListItem / Tabs;Fab 与 icon() 是画布默认值。 - `feedback/action.rs` 的本地 α 合成删掉,改走 `disabled_content_over_role` 并给真实容器底 (Snackbar `InverseSurface` / Dialog `SurfaceContainerHigh`)。 - 判据:`interaction::disabled::tests`(卡片/面板/画布三档逐值)、 `buttons::tests::base`(Button::base → StyleSpec → style_closure 接线)、 `gallery` 新增 `disabledbase` 段 + `gallery::probe::bases` 精确像素断言 (±10 容差区分不了 1/255 的差,所以自己数逐位相等的像素)。 - 变异自证:assemble 的调用点改回画布底后,上面两条都红(见 artifacts/m234/README.md)。 已知未尽:`crates/app-iced/src/pages/**` 不在 scope 内,页面侧「把控件放进卡片/面板」的 调用点尚未接 `.base(..)`(行为与本 mission 之前一致);`pages/…/java/tests/marker.rs` 有一行被迫更新(入口多了一个实参,语义不变 = 画布底)。
This commit is contained in:
1 parent
a9d1cb4c44
commit
35dbefb08d
48 files changed
+1690
-496
No files matched your search
@@ -0,0 +1,83 @@
|
||||
//! 禁用态的**底**:控件脚下那一层容器实际画出来的底色(M234)。
|
||||
//!
|
||||
//! ## 为什么不是一个 `Role::Surface`
|
||||
//!
|
||||
//! 禁用态的容器(按钮 10% / 面状控件 12%)与内容(38%)都要**预先合成成不透明色**
|
||||
//! (D27:GPU/CPU 两档逐像素一致,所以不许把 α 交给渲染器混合)。合成必须知道「叠在什么上」,
|
||||
//! 而这个「什么」是**宿主容器**的属性,不是控件的属性:
|
||||
//!
|
||||
//! ```text
|
||||
//! 画布(Surface) ← 页面底色
|
||||
//! └ 卡片(SurfaceContainer) ← `surfaces::elevated::card`
|
||||
//! └ 面板(SurfaceContainerLow)← 取景板 / Card 层
|
||||
//! └ 禁用按钮(OnSurface@10% 叠在面板底上)
|
||||
//! ```
|
||||
//!
|
||||
//! M229 之前 `disabled.rs` 的入口签名是 `(ui, surface: Role)`,而**所有调用点都传死
|
||||
//! `Role::Surface`** —— 于是卡片里的禁用按钮把 10% 叠在画布色上,出来是一块与卡片底
|
||||
//! 不协调的灰(M223 记的「CR 1.05、形丢失」)。参数在、语义也在,只是没人给真值。
|
||||
//!
|
||||
//! ## 纪律:底由**画那个底的容器**给
|
||||
//!
|
||||
//! 每个自己画底的容器**导出 `BASE` 常量**,画的时候用同一个 `Role`、给子控件时给这个常量
|
||||
//! (见 [`super::super::surfaces::elevated::BASE`]、`inputs::menu::PANEL_BASE`)。两边同源,
|
||||
//! 改色不会漂一半。
|
||||
//!
|
||||
//! iced 没有「环境上下文」(样式闭包只拿得到 `&Theme`,拿不到父容器的样式),所以这条信息
|
||||
//! **只能显式往下传**:容器 → 控件(`.base(..)`)→ 禁用色求值。控件自己不猜。
|
||||
//!
|
||||
//! ## 抓得住 / 抓不住
|
||||
//!
|
||||
//! - 抓得住:合成用了哪个 `Role`(`interaction::disabled::tests` 的逐值断言、gallery 的像素 probe);
|
||||
//! - 抓不住:① 容器画的是**合成色**(半透明面板 α、状态层叠过的底)——`Base` 只装一个 `Role`;
|
||||
//! ② 调用点给了**错的** `Role`(机制不校验语义,判据只能落在「给的底对不对」的像素上);
|
||||
//! ③ 忘了调 `.base(..)` 时回落到 [`Base::CANVAS`],编译期不会报错(文档 + 像素 probe 兜)。
|
||||
|
||||
use unlucky_design::color::Role;
|
||||
|
||||
/// 控件脚下那一层的底(容器自己画的角色,**不是**「反正是 surface」)。
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct Base(Role);
|
||||
|
||||
impl Base {
|
||||
/// 画布底(`Surface`):控件**直接**摆在页面/画布上时用它。
|
||||
///
|
||||
/// 这也是各控件 `.base(..)` 的默认值——默认值只对「没有容器」这一种情形成立,
|
||||
/// 放进卡片/面板/浮层里**必须**换成那个容器的 `BASE`。
|
||||
pub const CANVAS: Base = Base(Role::Surface);
|
||||
|
||||
/// 从容器**画自己底时用的那个角色**构造(容器应导出一个 `BASE` 常量走这条路)。
|
||||
pub const fn of(role: Role) -> Self {
|
||||
Self(role)
|
||||
}
|
||||
|
||||
/// 该底对应的角色(合成时取色用)。
|
||||
pub const fn role(self) -> Role {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// 容器也可以直接把**自己的角色**传进来(`disabled_*` 的入口收 `impl Into<Base>`):
|
||||
/// 这样历史调用点不必全改签名,但语义只有一条——「你脚下那一层是谁」。
|
||||
impl From<Role> for Base {
|
||||
fn from(role: Role) -> Self {
|
||||
Self(role)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
/// 画布底就是画布角色:`Base` 不许偷偷改语义。
|
||||
#[test]
|
||||
fn canvas_is_surface_and_of_keeps_the_role() {
|
||||
assert_eq!(Base::CANVAS.role(), Role::Surface);
|
||||
assert_eq!(
|
||||
Base::of(Role::SurfaceContainer).role(),
|
||||
Role::SurfaceContainer
|
||||
);
|
||||
// 容器底与画布底**不是同一个值**:这一条红了说明 `Base` 把角色丢了
|
||||
assert_ne!(Base::of(Role::SurfaceContainer), Base::CANVAS);
|
||||
}
|
||||
}
|
||||
@@ -34,46 +34,77 @@ use unlucky_design::color::{Role, Scheme};
|
||||
|
||||
use crate::theme::{to_iced, Ui};
|
||||
|
||||
use super::base::Base;
|
||||
|
||||
// 四个入口都收 `impl Into<Base>`:容器导出的 `BASE` 常量(推荐)与裸 `Role`(历史调用点,
|
||||
// 例如 `pages/settings/java/tests/marker.rs`)都能进来。**没有隐式默认值**——不给就是编译错误,
|
||||
// 这一条正是 M229 缺的:参数在、语义在,只是调用点全传了 `Role::Surface`。
|
||||
|
||||
/// 禁用态内容色(**按角色、按有没有容器**求值)——A1 口径的入口(**面状控件族**的底)。
|
||||
///
|
||||
/// - `base`:控件**脚下那一层的底**([`Base`])。容器给的 `BASE` 常量,不是猜;
|
||||
/// - `role`:由变体决定(Filled/Outlined/Text/Elevated = `OnSurfaceVariant`;
|
||||
/// FilledTonal 与三式 IconButton = `OnSurface`,见 `Variant::disabled_content`);
|
||||
/// - `on_container = true`:叠在**面状控件族的 12% 容器**([`DISABLED_SURFACE_ALPHA`])上
|
||||
/// (Filled TextField / 有容器控件在 12% 底上求内容时);
|
||||
/// `false`:直接叠在 **surface** 上(Text / Outlined / standard IconButton / 描边类控件的内容)。
|
||||
/// (Filled TextField / 有容器控件在 12% 底上求内容时),容器本身叠在 `base` 上;
|
||||
/// `false`:直接叠在 `base` 上(Text / Outlined / standard IconButton / 描边类控件的内容)。
|
||||
///
|
||||
/// **按钮家族不要用这个函数**(按钮容器是 10%):走 [`disabled_button_content`]。
|
||||
///
|
||||
/// 之前这里写死 `OnSurfaceVariant` 且只有一个「底」,导致 FilledTonal 与 IconButton 两族偏浅
|
||||
/// 15/255(视觉 r3 用像素量的)。
|
||||
pub fn disabled_content_over_role(ui: &Ui, role: Role, on_container: bool) -> Color {
|
||||
pub fn disabled_content_over_role(
|
||||
ui: &Ui,
|
||||
base: impl Into<Base>,
|
||||
role: Role,
|
||||
on_container: bool,
|
||||
) -> Color {
|
||||
// **取 `Ui` 里已注入的方案**,不重算 baseline:M229 之后产品方案是品牌色板
|
||||
// (Ink / Silver),照 baseline 重算会画出旧的天蓝中性色(复审 F1)。
|
||||
disabled_content_with_alpha(ui.scheme(), role, on_container, DISABLED_SURFACE_ALPHA)
|
||||
disabled_content_with_alpha(
|
||||
ui.scheme(),
|
||||
base.into(),
|
||||
role,
|
||||
on_container,
|
||||
DISABLED_SURFACE_ALPHA,
|
||||
)
|
||||
}
|
||||
|
||||
/// 禁用态内容色——**按钮家族**(`on_container`:是否叠在本族 10% 容器上)。
|
||||
///
|
||||
/// 与 [`disabled_content_over_role`] 的差别只有「底」的 α:按钮 10%、面状控件 12%。
|
||||
/// 两个入口分开是 M86 的结论:合成一个数会让一族永远差 1/255,肉眼看不见、只有 probe 会红。
|
||||
pub fn disabled_button_content(ui: &Ui, role: Role, on_container: bool) -> Color {
|
||||
disabled_content_with_alpha(ui.scheme(), role, on_container, DISABLED_CONTAINER_ALPHA)
|
||||
pub fn disabled_button_content(
|
||||
ui: &Ui,
|
||||
base: impl Into<Base>,
|
||||
role: Role,
|
||||
on_container: bool,
|
||||
) -> Color {
|
||||
disabled_content_with_alpha(
|
||||
ui.scheme(),
|
||||
base.into(),
|
||||
role,
|
||||
on_container,
|
||||
DISABLED_CONTAINER_ALPHA,
|
||||
)
|
||||
}
|
||||
|
||||
/// 两个族共用的内容色求值(「底」的 α 由调用方给)。
|
||||
fn disabled_content_with_alpha(
|
||||
scheme: &Scheme,
|
||||
base: Base,
|
||||
role: Role,
|
||||
on_container: bool,
|
||||
container_alpha: f32,
|
||||
) -> Color {
|
||||
let underneath = scheme.get(base.role());
|
||||
let base = if on_container {
|
||||
scheme
|
||||
.get(Role::OnSurface)
|
||||
.with_alpha(container_alpha)
|
||||
.over(scheme.get(Role::Surface))
|
||||
.over(underneath)
|
||||
} else {
|
||||
scheme.get(Role::Surface)
|
||||
underneath
|
||||
};
|
||||
|
||||
to_iced(
|
||||
@@ -99,29 +130,32 @@ fn disabled_content_with_alpha(
|
||||
///
|
||||
/// 顺序必须「先容器后内容」:Compose 也是这么画的,先叠容器再叠 label,
|
||||
/// 所以内容叠的角色是容器实色而不是底下的 surface。
|
||||
pub fn disabled_colors(ui: &Ui, surface: Role) -> (Color, Color) {
|
||||
disabled_colors_with_alpha(ui, surface, DISABLED_SURFACE_ALPHA)
|
||||
///
|
||||
/// ⚠️ **`base` 必须是控件脚下那一层的底**([`Base`]):M229 之前这里的参数名叫 `surface`,
|
||||
/// 而 8 个调用点全传 `Role::Surface`,于是卡片/面板里的禁用控件把 12% 叠在画布色上(M234)。
|
||||
pub fn disabled_colors(ui: &Ui, base: impl Into<Base>) -> (Color, Color) {
|
||||
disabled_colors_with_alpha(ui, base.into(), DISABLED_SURFACE_ALPHA)
|
||||
}
|
||||
|
||||
/// 禁用态的一对颜色 `(容器, 内容)`——**按钮家族**(10% 容器)。
|
||||
///
|
||||
/// - 容器 = `OnSurface` @ 10%([`DISABLED_CONTAINER_ALPHA`])叠在 `surface` 上;
|
||||
/// - 容器 = `OnSurface` @ 10%([`DISABLED_CONTAINER_ALPHA`])叠在 `base` 上;
|
||||
/// - 内容 = **默认** `OnSurfaceVariant` @ 38%;按变体的取值走 [`disabled_button_content`]。
|
||||
///
|
||||
/// 除了按钮家族,**没有别的消费者**:面状控件(chip / slider 轨道 / switch 轨道 / 描边)走
|
||||
/// [`disabled_colors`] 的 12%。
|
||||
pub fn disabled_button_colors(ui: &Ui, surface: Role) -> (Color, Color) {
|
||||
disabled_colors_with_alpha(ui, surface, DISABLED_CONTAINER_ALPHA)
|
||||
pub fn disabled_button_colors(ui: &Ui, base: impl Into<Base>) -> (Color, Color) {
|
||||
disabled_colors_with_alpha(ui, base.into(), DISABLED_CONTAINER_ALPHA)
|
||||
}
|
||||
|
||||
/// 两个族共用的求值:容器 = `OnSurface` @ `container_alpha` 叠在 `surface` 上,内容 = 38% 叠在容器上。
|
||||
fn disabled_colors_with_alpha(ui: &Ui, surface: Role, container_alpha: f32) -> (Color, Color) {
|
||||
/// 两个族共用的求值:容器 = `OnSurface` @ `container_alpha` 叠在 `base` 上,内容 = 38% 叠在容器上。
|
||||
fn disabled_colors_with_alpha(ui: &Ui, base: Base, container_alpha: f32) -> (Color, Color) {
|
||||
let scheme = ui.scheme();
|
||||
let base = scheme.get(surface);
|
||||
let underneath = scheme.get(base.role());
|
||||
let container = scheme
|
||||
.get(Role::OnSurface)
|
||||
.with_alpha(container_alpha)
|
||||
.over(base);
|
||||
.over(underneath);
|
||||
// 这里是**默认口径**(OnSurfaceVariant);按变体取值请走 [`disabled_content_over_role`]
|
||||
// ——FilledTonal 与三式 IconButton 的禁用内容是 `OnSurface`(A1)。
|
||||
let content = scheme
|
||||
|
||||
@@ -71,7 +71,7 @@ fn surface_family_disabled_colors_are_the_12_percent_class() {
|
||||
.with_alpha(EXPECTED_SURFACE_ALPHA)
|
||||
.over(base);
|
||||
|
||||
let (surface, surface_content) = disabled_colors(&ui, Role::Surface);
|
||||
let (surface, surface_content) = disabled_colors(&ui, Base::CANVAS);
|
||||
assert_eq!(
|
||||
surface,
|
||||
to_iced(expected_container),
|
||||
@@ -102,7 +102,7 @@ fn surface_family_disabled_colors_are_the_12_percent_class() {
|
||||
"{flavor:?}:内容必须叠在容器上"
|
||||
);
|
||||
// 跨族对照:面状族的合成色必须与按钮族不同(两族一旦合流,这条红)
|
||||
let (button, _) = disabled_button_colors(&ui, Role::Surface);
|
||||
let (button, _) = disabled_button_colors(&ui, Base::CANVAS);
|
||||
assert_ne!(
|
||||
surface, button,
|
||||
"{flavor:?}:面状族 12% 与按钮族 10% 必须落在不同像素值上"
|
||||
@@ -133,7 +133,7 @@ fn button_family_disabled_colors_are_the_10_percent_class() {
|
||||
.with_alpha(EXPECTED_BUTTON_ALPHA)
|
||||
.over(base);
|
||||
|
||||
let (button, button_content) = disabled_button_colors(&ui, Role::Surface);
|
||||
let (button, button_content) = disabled_button_colors(&ui, Base::CANVAS);
|
||||
assert_eq!(
|
||||
button,
|
||||
to_iced(expected_container),
|
||||
@@ -149,7 +149,7 @@ fn button_family_disabled_colors_are_the_10_percent_class() {
|
||||
),
|
||||
);
|
||||
|
||||
let (surface, _) = disabled_colors(&ui, Role::Surface);
|
||||
let (surface, _) = disabled_colors(&ui, Base::CANVAS);
|
||||
assert_ne!(
|
||||
button, surface,
|
||||
"{flavor:?}:10% 与 12% 必须落在不同像素值上(合成一个数就是这次要防的回归)"
|
||||
@@ -158,18 +158,18 @@ fn button_family_disabled_colors_are_the_10_percent_class() {
|
||||
// 内容色同理:按钮 38% 叠 10% 底 ≠ 面状 38% 叠 12% 底
|
||||
assert_ne!(
|
||||
button_content,
|
||||
disabled_content_over_role(&ui, Role::OnSurfaceVariant, true),
|
||||
disabled_content_over_role(&ui, Base::CANVAS, Role::OnSurfaceVariant, true),
|
||||
"{flavor:?}:两族的「有容器」内容色不能同源"
|
||||
);
|
||||
assert_eq!(
|
||||
disabled_button_content(&ui, Role::OnSurfaceVariant, true),
|
||||
disabled_button_content(&ui, Base::CANVAS, Role::OnSurfaceVariant, true),
|
||||
button_content,
|
||||
"{flavor:?}:按钮内容入口必须与按钮颜色入口同源"
|
||||
);
|
||||
// 无容器时两族完全一致(都叠 surface)——差异只在「有容器」那一支
|
||||
assert_eq!(
|
||||
disabled_button_content(&ui, Role::OnSurfaceVariant, false),
|
||||
disabled_content_over_role(&ui, Role::OnSurfaceVariant, false),
|
||||
disabled_button_content(&ui, Base::CANVAS, Role::OnSurfaceVariant, false),
|
||||
disabled_content_over_role(&ui, Base::CANVAS, Role::OnSurfaceVariant, false),
|
||||
"{flavor:?}:没有容器时不该有族差异"
|
||||
);
|
||||
}
|
||||
@@ -192,7 +192,7 @@ fn disabled_colors_follow_the_brand_board_not_the_tone_baseline() {
|
||||
let baseline = Scheme::baseline(flavor);
|
||||
|
||||
// ① 面状控件族的容器(chip 描边 / slider 未激活轨 / switch 轨道)
|
||||
let (surface, _surface_content) = disabled_colors(&ui, Role::Surface);
|
||||
let (surface, _surface_content) = disabled_colors(&ui, Base::CANVAS);
|
||||
let expect_surface = to_iced(
|
||||
board
|
||||
.get(Role::OnSurface)
|
||||
@@ -216,12 +216,12 @@ fn disabled_colors_follow_the_brand_board_not_the_tone_baseline() {
|
||||
);
|
||||
|
||||
// ② 按钮族的容器
|
||||
let (button, _) = disabled_button_colors(&ui, Role::Surface);
|
||||
let (button, _) = disabled_button_colors(&ui, Base::CANVAS);
|
||||
assert_ne!(button, surface, "{flavor:?}:两族 α 仍要可区分");
|
||||
|
||||
// ③ 内容色(两个入口)
|
||||
assert_eq!(
|
||||
disabled_content_over_role(&ui, Role::OnSurfaceVariant, true),
|
||||
disabled_content_over_role(&ui, Base::CANVAS, Role::OnSurfaceVariant, true),
|
||||
to_iced(
|
||||
board
|
||||
.get(Role::OnSurfaceVariant)
|
||||
@@ -236,7 +236,7 @@ fn disabled_colors_follow_the_brand_board_not_the_tone_baseline() {
|
||||
"{flavor:?}:面状控件族内容色要按色板合成"
|
||||
);
|
||||
assert_eq!(
|
||||
disabled_button_content(&ui, Role::OnSurfaceVariant, true),
|
||||
disabled_button_content(&ui, Base::CANVAS, Role::OnSurfaceVariant, true),
|
||||
to_iced(
|
||||
board
|
||||
.get(Role::OnSurfaceVariant)
|
||||
@@ -267,6 +267,108 @@ fn disabled_colors_follow_the_brand_board_not_the_tone_baseline() {
|
||||
}
|
||||
}
|
||||
|
||||
/// **M234 的主判据**:禁用态的合成必须用**给的底**,不是画布色。
|
||||
///
|
||||
/// 卡片(`SurfaceContainer`)与面板(`SurfaceContainerLow`)里各放一个禁用控件时,
|
||||
/// 10%(按钮族)/ 12%(面状族)那一层要叠在**卡/面板的底**上;叠在 `Surface` 上就是 M223
|
||||
/// 记的「CR 1.05、形丢失」。
|
||||
///
|
||||
/// 抓得住:① 入口把 `base` 丢了(内部又写死 `Role::Surface`);② 入口把两个族的 α 合成一个数;
|
||||
/// ③ 调用点给了画布底(这条测试只证「给了卡片底 → 算出卡片色」,调用点是否真的给了由
|
||||
/// `buttons::tests::a_disabled_button_composites_over_the_base_it_is_given` 与 gallery 的像素
|
||||
/// probe 分别守)。
|
||||
///
|
||||
/// 抓不住:① 容器画的是**合成色**(半透明面板 α、叠过状态层的底)——`Base` 只装一个 `Role`;
|
||||
/// ② 卡/面板组件的 `BASE` 常量与它自己画的色不一致(那条由 `surfaces::elevated::tests` 与
|
||||
/// 像素 probe 守);③ GPU(wgpu) 档(本测试是纯值,两档同源同值)。
|
||||
#[test]
|
||||
fn disabled_paint_composites_over_the_base_it_is_given() {
|
||||
use unlucky_design::color::BrandBoard;
|
||||
use unlucky_design::color::Role;
|
||||
|
||||
const BUTTON_ALPHA: f32 = 0.10;
|
||||
const SURFACE_ALPHA: f32 = 0.12;
|
||||
const CONTENT_ALPHA: f32 = 0.38;
|
||||
|
||||
for flavor in [SchemeFlavor::Light, SchemeFlavor::Dark] {
|
||||
let ui = ui(flavor);
|
||||
let scheme = BrandBoard::for_flavor(flavor).scheme();
|
||||
let card = Base::of(Role::SurfaceContainer);
|
||||
let panel = Base::of(Role::SurfaceContainerLow);
|
||||
|
||||
// 期望值一律**独立算**(写死 α + 直接取色板角色),不调被测常量。
|
||||
let over = |base: Role, alpha: f32| {
|
||||
to_iced(
|
||||
scheme
|
||||
.get(Role::OnSurface)
|
||||
.with_alpha(alpha)
|
||||
.over(scheme.get(base)),
|
||||
)
|
||||
};
|
||||
|
||||
// ① 按钮族 10%:卡片底 / 面板底 / 画布底三档互不相等
|
||||
let (card_button, card_button_ink) = disabled_button_colors(&ui, card);
|
||||
let (panel_button, _) = disabled_button_colors(&ui, panel);
|
||||
let (canvas_button, canvas_button_ink) = disabled_button_colors(&ui, Base::CANVAS);
|
||||
assert_eq!(
|
||||
card_button,
|
||||
over(Role::SurfaceContainer, BUTTON_ALPHA),
|
||||
"{flavor:?}:卡片里的禁用按钮容器 = on-surface@10% 叠**卡片底**"
|
||||
);
|
||||
assert_eq!(
|
||||
panel_button,
|
||||
over(Role::SurfaceContainerLow, BUTTON_ALPHA),
|
||||
"{flavor:?}:面板里的禁用按钮容器 = on-surface@10% 叠**面板底**"
|
||||
);
|
||||
assert_ne!(card_button, canvas_button, "{flavor:?}:卡片底 ≠ 画布底");
|
||||
assert_ne!(panel_button, canvas_button, "{flavor:?}:面板底 ≠ 画布底");
|
||||
assert_ne!(card_button, panel_button, "{flavor:?}:卡片底 ≠ 面板底");
|
||||
|
||||
// ② 面状控件族 12%(字段容器 / chip 容器 / switch 轨道)
|
||||
let (card_surface, _) = disabled_colors(&ui, card);
|
||||
let (panel_surface, _) = disabled_colors(&ui, panel);
|
||||
let (canvas_surface, _) = disabled_colors(&ui, Base::CANVAS);
|
||||
assert_eq!(
|
||||
card_surface,
|
||||
over(Role::SurfaceContainer, SURFACE_ALPHA),
|
||||
"{flavor:?}:卡片里的禁用字段容器 = on-surface@12% 叠**卡片底**"
|
||||
);
|
||||
assert_eq!(
|
||||
panel_surface,
|
||||
over(Role::SurfaceContainerLow, SURFACE_ALPHA),
|
||||
"{flavor:?}:面板里的禁用字段容器 = on-surface@12% 叠**面板底**"
|
||||
);
|
||||
assert_ne!(card_surface, canvas_surface);
|
||||
assert_ne!(panel_surface, canvas_surface);
|
||||
|
||||
// ③ 内容色也跟着底走(38% 叠在容器上 / 直接叠在底上,两支都要换底)
|
||||
assert_eq!(
|
||||
disabled_button_content(&ui, card, Role::OnSurfaceVariant, true),
|
||||
to_iced(
|
||||
scheme
|
||||
.get(Role::OnSurfaceVariant)
|
||||
.with_alpha(CONTENT_ALPHA)
|
||||
.over(
|
||||
scheme
|
||||
.get(Role::OnSurface)
|
||||
.with_alpha(BUTTON_ALPHA)
|
||||
.over(scheme.get(Role::SurfaceContainer))
|
||||
)
|
||||
),
|
||||
"{flavor:?}:有容器的内容色 = 38% 叠(10% 叠卡片底)"
|
||||
);
|
||||
assert_ne!(
|
||||
card_button_ink, canvas_button_ink,
|
||||
"{flavor:?}:内容叠的容器换了底"
|
||||
);
|
||||
assert_ne!(
|
||||
disabled_content_over_role(&ui, card, Role::OnSurface, false),
|
||||
disabled_content_over_role(&ui, Base::CANVAS, Role::OnSurface, false),
|
||||
"{flavor:?}:无容器时 38% 也必须叠在**给的底**上"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// iced 颜色 → 8bit 通道(像素值,报告里的证据就用它)。
|
||||
fn channels(color: Color) -> (u8, u8, u8) {
|
||||
(
|
||||
|
||||
@@ -39,6 +39,13 @@
|
||||
//! 上表右列是**唯一**允许的取值口;左列只是给人看的,代码里一个数字都不许出现
|
||||
//! (`components::gate` 会扫)。
|
||||
//!
|
||||
//! ## 合成的「底」是参数,不是常量(M234)
|
||||
//!
|
||||
//! 四个入口都收一个 [`Base`]——控件**脚下那一层的底**,由画那个底的容器导出
|
||||
//! (`surfaces::elevated::BASE` / `inputs::menu::PANEL_BASE` / 各控件的 `.base(..)`)。
|
||||
//! M229 之前这个值恒等于 `Role::Surface`,于是卡片/面板里的禁用控件把 10%/12% 叠在画布色上
|
||||
//! (M223 的「CR 1.05、形丢失」)。**不许**在入口内部再写一个默认值回来。
|
||||
//!
|
||||
//! ## 两个消费形态
|
||||
//!
|
||||
//! 1. **iced `button` 系**(本 mission 的按钮家族):拿 [`Interaction`] 直接配 [`overlay_color`];
|
||||
@@ -144,8 +151,10 @@ pub fn overlay_color(ui: &Ui, state: Interaction, content: Role, container: Role
|
||||
.map(|layer| ui.state_over(layer, content, container))
|
||||
}
|
||||
|
||||
mod base;
|
||||
mod disabled;
|
||||
|
||||
pub use base::Base;
|
||||
pub use disabled::{
|
||||
disabled_button_colors, disabled_button_content, disabled_colors, disabled_content_over_role,
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user