From bf5e6c6cec2e7a370cfa58b1deb50125f402755f Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 10 Oct 2026 19:16:03 +0000 Subject: [PATCH] #581: the Discord pill fits its label and field text sits on the field's middle Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f --- crates/ui-egui/src/header.rs | 9 ++++++--- crates/ui-egui/src/widgets.rs | 26 ++++++++++++++++++++++++++ crates/ui-egui/tests/ui_panels.rs | 11 +++++++++++ 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/crates/ui-egui/src/header.rs b/crates/ui-egui/src/header.rs index 1b93658f..f92193f7 100644 --- a/crates/ui-egui/src/header.rs +++ b/crates/ui-egui/src/header.rs @@ -177,12 +177,15 @@ pub fn show(app: &mut EffectcraftApp, ui: &mut egui::Ui, rect: Rect) { // Right side: community buttons, workspaces. let mut rx = rect.max.x - 10.0; - let discord = Rect::from_min_max(pos2(rx - 104.0, cy - 13.0), pos2(rx, cy + 13.0)); + // The pill fits its label (icon, gap, text) with even padding: it was a fixed 104 px with the + // text at its left, which left a wide gap on the right (#581). + let label = p.layout_no_wrap(tr("Discord").to_string(), Tokens::semibold(12.0), Color32::WHITE); + let discord = Rect::from_min_max(pos2(rx - (10.0 + 14.0 + 6.0 + label.size().x + 12.0), cy - 13.0), pos2(rx, cy + 13.0)); let dresp = ui.interact(discord, egui::Id::new("hdr-discord"), Sense::click()); let dc = Color32::from_rgb(0x58, 0x65, 0xf2); p.rect_filled(discord, 13.0, if dresp.hovered() { dc.gamma_multiply(1.2) } else { dc }); - icons::paint(&p, Rect::from_center_size(pos2(discord.min.x + 16.0, cy), vec2(14.0, 14.0)), Icon::Chat, Color32::WHITE); - p.text(pos2(discord.min.x + 28.0, cy), Align2::LEFT_CENTER, tr("Discord"), Tokens::semibold(12.0), Color32::WHITE); + icons::paint(&p, Rect::from_center_size(pos2(discord.min.x + 17.0, cy), vec2(14.0, 14.0)), Icon::Chat, Color32::WHITE); + p.galley(pos2(discord.min.x + 30.0, cy - label.size().y / 2.0), label, Color32::WHITE); app.auto.add("header.discord", discord, "Join the ArtCraft Discord"); if dresp.on_hover_text(tr("Join the ArtCraft community on Discord")).clicked() { let _ = app.session.execute("help.discord", json!({})); diff --git a/crates/ui-egui/src/widgets.rs b/crates/ui-egui/src/widgets.rs index 8f12e52b..c37f8c34 100644 --- a/crates/ui-egui/src/widgets.rs +++ b/crates/ui-egui/src/widgets.rs @@ -277,6 +277,8 @@ fn field(ui: &mut Ui, rect: Rect, text: &mut String, hint: &str, t: &Tokens, sea .hint_text(hint) .frame(egui::Frame::NONE) .desired_width(inner.width()) + // As tall as the field, so the text and the hint sit on its middle (they sat high, #581). + .min_size(inner.size()) .font(Tokens::ui(12.0)) .vertical_align(egui::Align::Center), ) @@ -559,3 +561,27 @@ pub fn popup_is_open(ui: &Ui, id: egui::Id) -> bool { pub fn open_popup(ui: &Ui, id: egui::Id) { ui.data_mut(|d| d.insert_temp(id.with("open"), true)); } + +#[cfg(test)] +mod tests { + use super::*; + + /// #581: a field's text edit fills it, so its text and hint sit on the field's middle line + /// (it was a row at the top of the field, its text high). + #[test] + fn field_text_is_vertically_centred() { + let ctx = egui::Context::default(); + let t = Tokens::for_kind(Default::default()); + for h in [22.0, 26.0, 30.0] { + let field = Rect::from_min_size(pos2(20.0, 40.0), vec2(220.0, h)); + let mut text = String::new(); + let mut got = None; + let mut out = ctx.run_ui(Default::default(), |ui| { + got = Some(search_field(ui, field, &mut text, "Filter recent files", &t).rect); + }); + out.textures_delta.clear(); + let r = got.expect("the field was drawn"); + assert!((r.center().y - field.center().y).abs() < 0.5 && r.height() >= h - 2.5, "{h}: {r:?} in {field:?}"); + } + } +} diff --git a/crates/ui-egui/tests/ui_panels.rs b/crates/ui-egui/tests/ui_panels.rs index d58c2146..3b580921 100644 --- a/crates/ui-egui/tests/ui_panels.rs +++ b/crates/ui-egui/tests/ui_panels.rs @@ -35,6 +35,17 @@ fn click(h: &mut Harness<'_, EffectcraftApp>, id: &str) { h.run_steps(2); } +/// #581: the header's Discord pill fits its label with even padding (it was a fixed 104 px with +/// the text at its left). +#[test] +fn discord_pill_fits_its_label() { + let h = harness(); + let e = h.state().auto.find("header.discord").expect("the Discord pill").clone(); + let text = h.ctx.fonts_mut(|f| f.layout_no_wrap("Discord".into(), effectcraft_ui_egui::theme::Tokens::semibold(12.0), egui::Color32::WHITE).size().x); + // Padding 10, the 14 px icon, a 6 px gap, the text, padding 12. + assert!((e.rect[2] - (text + 42.0)).abs() < 0.5, "{} for a {text} px label", e.rect[2]); +} + #[test] fn window_menu_opens_the_new_panels() { let mut h = harness();