diff --git a/crates/app-iced/src/pages/frame.rs b/crates/app-iced/src/pages/frame.rs index a5ec078..fc912f4 100644 --- a/crates/app-iced/src/pages/frame.rs +++ b/crates/app-iced/src/pages/frame.rs @@ -23,7 +23,7 @@ mod tests; pub use pieces::{ card, divider, empty_state, filled, gap, glyph, glyph_box, scroll_style, text_action, - text_role, text_role_centered, ICON_PX, ICON_SMALL_PX, + text_role, text_role_centered, ICON_PX, ICON_SMALL_PX, SCROLLBAR_MARGIN, SCROLLBAR_WIDTH, }; use iced::widget::{column, container, row}; diff --git a/crates/app-iced/src/pages/frame/pieces.rs b/crates/app-iced/src/pages/frame/pieces.rs index 997acdc..c00edca 100644 --- a/crates/app-iced/src/pages/frame/pieces.rs +++ b/crates/app-iced/src/pages/frame/pieces.rs @@ -25,8 +25,12 @@ use crate::theme::Ui; pub(super) const EMPTY_ICON_BLOCK: f32 = 96.0; /// 空态字形渲染尺寸(12b 15.1:图标 32~48 `[估]`,取 40)。 pub(super) const EMPTY_ICON_GLYPH: f32 = 40.0; -/// 滚动条宽度(iced 默认 10px 的令牌化名字,用于把滑块做成药丸)。 -const SCROLLBAR_TRACK: f32 = 10.0; +/// 滚动条轨宽(视觉复审 P2-2:原来用 iced 默认的 10px,压过了列表内容)。 +/// +/// 取 6:细到不抢视线,又还在命中/可见的下限之上;滑块做成 full 圆角药丸(半径 3)。 +pub const SCROLLBAR_WIDTH: f32 = 6.0; +/// 滑块离卡片内边的留白(2px,避免贴边)。 +pub const SCROLLBAR_MARGIN: f32 = 2.0; /// 描边卡片(占位:M75 的 `components` 会提供真正的 `OutlinedCard`)。 pub fn card<'a>(ui: &'a Ui, content: impl Into>) -> Element<'a, Message> { @@ -207,6 +211,14 @@ fn text_widget<'a>( /// 任意尺寸的令牌图标(`icons::RENDER_PX` 只有 24 一档;空态图标要 40)。 /// +/// ## 图标语汇(视觉复审 P2-3) +/// +/// 令牌里 **`Play` / `Stop` / `More` 是填充字形**,其余全是描边。页面骨架里**只用描边图标**: +/// 同屏把填充字形和描边字形混在一起,线宽语汇会打架(复审的原话是「Play 是填充字形, +/// 同屏其它图标是描边」)。真要做「主操作允许实心图标」这条例外,应当由组件线在 +/// `components/` 里统一定义并只保留一处,而不是散落在页面里——所以这里干脆一个都不放。 +/// 守门:`tests/no_hardcoded_tokens.rs` 的 `pages_use_only_stroked_icons`。 +/// /// 描边宽度仍按令牌的 `Icon::stroke_width(render_px)` 折算,所以视觉线宽在任何尺寸下都是 1.5。 pub fn glyph(kind: IconKind, color: Color, render_px: f32) -> Element<'static, Message> { let icon = kind.icon(); @@ -263,9 +275,11 @@ pub fn scroll_style(ui: &Ui) -> impl Fn(&IcedTheme, scrollable::Status) -> scrol background: None, border: Border::default(), scroller: scrollable::Scroller { - background: Background::Color(ui.color(Role::Outline)), + // 低对比:用 `OutlineVariant`(比 `Outline` 弱一档的容器描边角色)而不是 `Outline`, + // 让滑块明显弱于正文;纯色不透明,CPU/GPU 两档一致。 + background: Background::Color(ui.color(Role::OutlineVariant)), border: Border { - radius: ui.radius(ShapeScale::Full, SCROLLBAR_TRACK), + radius: ui.radius(ShapeScale::Full, SCROLLBAR_WIDTH), ..Border::default() }, }, diff --git a/crates/app-iced/src/pages/instances.rs b/crates/app-iced/src/pages/instances.rs index e0556a8..c4dae1a 100644 --- a/crates/app-iced/src/pages/instances.rs +++ b/crates/app-iced/src/pages/instances.rs @@ -113,6 +113,12 @@ fn list_column<'a>(ui: &'a Ui, selected: Option) -> Element<'a, Message> // **独立滚动**:只有列表列这一条 scrollable,详情列不跟着滚。 let scroller = scrollable(rows) + .direction(scrollable::Direction::Vertical( + scrollable::Scrollbar::new() + .width(frame::SCROLLBAR_WIDTH) + .scroller_width(frame::SCROLLBAR_WIDTH) + .margin(frame::SCROLLBAR_MARGIN), + )) .height(Length::Fill) .style(frame::scroll_style(ui)); diff --git a/crates/app-iced/src/pages/settings.rs b/crates/app-iced/src/pages/settings.rs index 7cd9852..49ec5e8 100644 --- a/crates/app-iced/src/pages/settings.rs +++ b/crates/app-iced/src/pages/settings.rs @@ -63,8 +63,10 @@ const GROUPS: [Group; 4] = [ ], }, Group { + // 描边字形:令牌里 `Play` 是填充字形,和同屏其它描边图标语汇打架(视觉复审 P2-3); + // Java 分组讲的是运行时安装位置,用目录图标语义也对得上。 name: "Java", - icon: IconKind::Play, + icon: IconKind::Folder, rows: &[ ("Runtime", "Temurin 21.0.4"), ("Default memory", "4 GiB"),