fix(m206): 「当前默认」改用选中的语汇,不再套禁用配色
Java 组用 `Chip::badge` 表示「哪个 JDK 是默认」,而 badge 走的是「无消息 ⇒ 禁用」 那条路(`OnSurface`@38% 叠 surface):M204 实测字/底只有 1.84:1(浅)/ 2.28:1(深), 成了整页最不可读的一段,而它正是「能不能改默认 Java」这个问题的答案本身。 同一张设置页里相邻的「下载」组表达「选中」用的是 `SecondaryContainer` + `OnSecondaryContainer`(7.21:1)——两个相邻页面对同一个语义用了两套语汇。 改法(不动禁用语义): 1. 新增 `Chip::current(label)` + `paint::current_item`:**与选中 chip 同一套颜色**, 但没有消息、不吃五态(没有可点性就没有反馈)。它不等于「未选中」,也不等于 「禁用」——第三档,判据表写在 `components/selection/chip.rs` 的模块文档里。 2. `Chip::paint(&self, ui)` 成为「哪个档位 → 什么颜色」的唯一入口,`chip()` 用它求 静息色,断言也用它——档位的判据只有一处,「改回旧配色」的变异会被直接抓住。 3. Java 页的动作位抽成 `view::action_chip`,当前默认走 `Chip::current`,其余仍是可点 的 `Chip::filter(.., false, ..)`。 4. 下载组**不改**:它本来就是参照语汇(M201 已验收),改完两页逐字段同色。 断言(`pages/settings/java/tests/marker.rs`,浅深两档都跑): 对比度 ≥4.5:1(实测 7.21/7.21)、与下载组选中 chip 逐字段相等、以及反向断言 「禁用态仍走 38% 字 + 12% 容器且与当前项肉眼可分」。两条变异都在报告里复现过: `action_chip` 换回 `Chip::badge` ⇒ 对比度断言红(只有 1.84:1);`Chip::current` 里 `marker: true` 改 `false` ⇒ 三条全红。 举证图(离屏 `--screenshot`,浅/深 + 改前/改后 + 下载组对照)与实测色值表见 `DevDocs/artifacts/m206/`(gitignore,不入库)。
This commit is contained in:
1 parent
46559910c9
commit
b7a1abb18a
6 files changed
+357
-35
No files matched your search
@@ -14,6 +14,24 @@
|
||||
//! M3 的 chip **没有圆形状态层**:hover / pressed 就是把状态层叠在**自己的容器**上,
|
||||
//! 而容器尺寸 = 命中区尺寸。所以 chip 直接走 `button` 的样式闭包(与按钮家族同一条产线),
|
||||
//! 不需要「48 外壳 + 40 圆」那套。
|
||||
//!
|
||||
//! ## 「选中」与「当前项」:两个档位,一套颜色(M206)
|
||||
//!
|
||||
//! 这两件事**不是**「选中 / 未选中」,而是「可点的选中」与「不可点的当前项」——它们必须长得
|
||||
//! **一样**(同一个视觉语汇),差别只在**有没有反馈**:
|
||||
//!
|
||||
//! | 档位 | 构造器 | 容器 / 文字 | 对比度下限 | 五态反馈 | 什么时候用 |
|
||||
//! |---|---|---|---|---|---|
|
||||
//! | A 可点选中 | [`Chip::filter`] `(label, true, msg)` | `SecondaryContainer` / `OnSecondaryContainer` | **≥ 4.5:1**(WCAG AA 正文;实测 7.21:1 浅 / 7.21:1 深) | 有(hover/pressed 状态层) | 点它**会改变**选中项(下载组的分段单选、预置项开关) |
|
||||
//! | B 不可点当前项 | [`Chip::current`] | **同 A,一个像素都不差** | **≥ 4.5:1**(同 7.21:1) | **无**(没有可点性就没有反馈) | 「这就是当前生效的那个」,再点一次没有动作(Java 组的「默认」) |
|
||||
//! | (不是档位)暂不可用 | [`Chip::badge`] / [`.disabled()`](Chip::disabled) | `OnSurface`@12% / @38% | **不适用**:它是禁用语汇(实测 1.84:1 浅 / 2.28:1 深) | — | 真的点不了(下载进行中把「安装」灰掉、LTS/基线这类标签) |
|
||||
//!
|
||||
//! **判据只有一句**:这个 chip 点下去**会不会改变**它表示的值?
|
||||
//! 会 → A;不会(它已经是当前值)→ B;**根本不能点**(忙/不可用)→ 禁用档。
|
||||
//! 尤其:**不许拿 `badge` 表示「当前默认」**——那是把「不可用」的语汇贴在「答案」上,
|
||||
//! M204 实测出来就是整页最不可读的一段(1.84:1)。这一条不靠调用方记住,`Chip::current`
|
||||
//! 与 `paint::current_item` 的文档 + `pages::settings::java::tests::marker` 的三条断言
|
||||
//! (对比度 / 同族 / 禁用语义)一起把它钉在组件层。
|
||||
|
||||
use iced::widget::{button, container, row, text};
|
||||
use iced::{Alignment, Background, Border, Element, Length, Padding, Shadow};
|
||||
@@ -38,6 +56,8 @@ pub struct Chip<'a, M> {
|
||||
trailing: Option<IconKind>,
|
||||
on_press: Option<M>,
|
||||
state: Option<Interaction>,
|
||||
/// 「当前项」标记([`Chip::current`]):选中配色照画,但**不**降成禁用配色、也不吃五态。
|
||||
marker: bool,
|
||||
}
|
||||
|
||||
impl<'a, M> Chip<'a, M> {
|
||||
@@ -58,8 +78,12 @@ impl<'a, M> Chip<'a, M> {
|
||||
|
||||
/// **纯展示**的 filter chip(选中态、无消息 ⇒ 永远不可交互)。
|
||||
///
|
||||
/// 与 `filter(label, true, msg).disabled()` 等价,但**不要求调用方编一条永远收不到的消息**:
|
||||
/// 本轮 Java 页那颗「默认」标记就是这么用的(`Message::Noop` 已删,别再拿一条真消息当占位)。
|
||||
/// 与 `filter(label, true, msg).disabled()` 等价,但**不要求调用方编一条永远收不到的消息**。
|
||||
///
|
||||
/// ⚠️ **它不是「当前项」**(M206 纠正):`badge` 走的是**禁用**配色(`OnSurface`@38% 叠
|
||||
/// surface,实测 **1.84:1 浅 / 2.28:1 深**),那是「暂不可用」的语汇。要表达「这行就是当前
|
||||
/// 生效的那个」,用 [`Chip::current`]——它和下载组的选中 chip 同一套颜色,7.21:1。
|
||||
/// 仍然用 `badge` 的两处都是**真禁用语义**:下载进行中把「安装」灰掉、以及 LTS/基线/推荐这类标签。
|
||||
pub fn badge(label: &'a str) -> Self {
|
||||
Self {
|
||||
label,
|
||||
@@ -69,6 +93,29 @@ impl<'a, M> Chip<'a, M> {
|
||||
trailing: None,
|
||||
on_press: None,
|
||||
state: None,
|
||||
marker: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// **当前项**标记:`SecondaryContainer` + `OnSecondaryContainer`(与可点的选中 chip
|
||||
/// **同一套配色**),没有消息 ⇒ 也不吃 hover / pressed / 禁用态。
|
||||
///
|
||||
/// 语义:「这一行就是当前生效的那个」。它与 [`Chip::filter`]`(label, true, msg)` 的差别
|
||||
/// **只在有没有动作**——点当前值不会改变任何东西,所以给它一个永远不响的消息是撒谎
|
||||
/// (`Message::Noop` 已删,见 `Chip::badge` 的旧注)。判据表见本文档开头的「选中与当前项」。
|
||||
///
|
||||
/// 为什么不能写成「`filter(.., true, ..)` + `.disabled()`」:`disabled()` 会走禁用配色
|
||||
/// (38% 文字、12% 容器),当前项就又变成不可读了——这正是 M206 要修的那件事。
|
||||
pub fn current(label: &'a str) -> Self {
|
||||
Self {
|
||||
label,
|
||||
variant: ChipVariant::Filter,
|
||||
selected: true,
|
||||
leading: None,
|
||||
trailing: None,
|
||||
on_press: None,
|
||||
state: None,
|
||||
marker: true,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,6 +139,7 @@ impl<'a, M> Chip<'a, M> {
|
||||
trailing: None,
|
||||
on_press: Some(on_press),
|
||||
state: None,
|
||||
marker: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,6 +160,25 @@ impl<'a, M> Chip<'a, M> {
|
||||
self.state = Some(state);
|
||||
self
|
||||
}
|
||||
|
||||
/// 静息时的外观——**唯一**把「这颗 chip 属于哪个档位」翻成颜色的地方。
|
||||
///
|
||||
/// `chip()` 用它求文字/图标色,测试也用它量对比度:档位的判据(当前项 / 选中 / 禁用)
|
||||
/// 只有这一处,所以「实现改回旧配色」这类变异会被
|
||||
/// `pages::settings::java::tests::marker` 的对比度断言直接抓住。
|
||||
pub fn paint(&self, ui: &Ui) -> paint::ChipPaint {
|
||||
let radius = ChipGeometry::of(ui).radius;
|
||||
if self.marker {
|
||||
return paint::current_item(ui, radius);
|
||||
}
|
||||
// 没有消息 = 禁用(`Chip::badge` 与 `.disabled()` 都走这里)。
|
||||
let state = if self.on_press.is_none() {
|
||||
Interaction::Disabled
|
||||
} else {
|
||||
self.state.unwrap_or(Interaction::Enabled)
|
||||
};
|
||||
paint::chip(ui, self.variant, self.selected, state, radius)
|
||||
}
|
||||
}
|
||||
|
||||
/// 画一个 chip。
|
||||
@@ -119,22 +186,14 @@ pub fn chip<'a, M: Clone + 'a>(ui: &'a Ui, spec: Chip<'a, M>) -> Element<'a, M>
|
||||
let geometry = ChipGeometry::of(ui);
|
||||
let variant = spec.variant;
|
||||
let selected = spec.selected;
|
||||
let disabled = spec.on_press.is_none();
|
||||
let marker = spec.marker;
|
||||
let forced = spec.state;
|
||||
|
||||
// 文字/图标色只看「选中 + 禁用」(A1:Filter/Input 的 label 色在 hover/focus/pressed 不变),
|
||||
// 所以这里静态求值;容器(含状态层)在样式闭包里跟态走。
|
||||
let at_rest = paint::chip(
|
||||
ui,
|
||||
variant,
|
||||
selected,
|
||||
if disabled {
|
||||
Interaction::Disabled
|
||||
} else {
|
||||
forced.unwrap_or(Interaction::Enabled)
|
||||
},
|
||||
geometry.radius,
|
||||
);
|
||||
// 所以这里静态求值;容器(含状态层)在样式闭包里跟态走。档位的判据在 `Chip::paint` 一处
|
||||
// (M206:当前项标记走 `paint::current_item`——**不是**禁用态。它的不可点性与「忙/不可用」
|
||||
// 是两件事:前者是「已经选中的那个」(选中配色),后者是「暂不可用」(38% 文字))。
|
||||
let at_rest = spec.paint(ui);
|
||||
|
||||
let mut content = row![].align_y(Alignment::Center).spacing(geometry.gap);
|
||||
if let Some(kind) = spec.leading {
|
||||
@@ -177,8 +236,13 @@ pub fn chip<'a, M: Clone + 'a>(ui: &'a Ui, spec: Chip<'a, M>) -> Element<'a, M>
|
||||
left: geometry.pad,
|
||||
})
|
||||
.style(move |_theme, status| {
|
||||
let state = forced.unwrap_or_else(|| Interaction::from_status(status));
|
||||
let paint = paint::chip(ui, variant, selected, state, geometry.radius);
|
||||
// 标记不吃五态:没有可点性就没有反馈(`--force-state` 也不该把它画成 hover)。
|
||||
let paint = if marker {
|
||||
paint::current_item(ui, geometry.radius)
|
||||
} else {
|
||||
let state = forced.unwrap_or_else(|| Interaction::from_status(status));
|
||||
paint::chip(ui, variant, selected, state, geometry.radius)
|
||||
};
|
||||
button::Style {
|
||||
background: paint.frame.fill.map(Background::Color),
|
||||
text_color: paint.label,
|
||||
|
||||
Reference in new issue
Block a user