diff --git a/assets/fonts/Inter-400.ttf b/assets/fonts/Inter-400.ttf deleted file mode 100644 index b5616ecf..00000000 Binary files a/assets/fonts/Inter-400.ttf and /dev/null differ diff --git a/assets/fonts/Inter-500.ttf b/assets/fonts/Inter-500.ttf deleted file mode 100644 index b5616ecf..00000000 Binary files a/assets/fonts/Inter-500.ttf and /dev/null differ diff --git a/assets/fonts/Inter-600.ttf b/assets/fonts/Inter-600.ttf deleted file mode 100644 index b5616ecf..00000000 Binary files a/assets/fonts/Inter-600.ttf and /dev/null differ diff --git a/crates/moon-ui-gpui/src/analytics/profit_monitor/settings.rs b/crates/moon-ui-gpui/src/analytics/profit_monitor/settings.rs index a23bf1ba..8190cf2f 100644 --- a/crates/moon-ui-gpui/src/analytics/profit_monitor/settings.rs +++ b/crates/moon-ui-gpui/src/analytics/profit_monitor/settings.rs @@ -14,8 +14,8 @@ use std::collections::HashSet; use gpui::*; use moon_core::config::layout::WindowLayout; use moon_ui::{ - MoonCheckbox, MoonCheckboxSize, MoonGroupBox, MoonPalette, MoonPopover, MoonPopoverPlacement, - h_flex, v_flex, + MoonCheckbox, MoonGroupBox, MoonPalette, MoonPopover, MoonPopoverPlacement, MoonSize, h_flex, + v_flex, }; use rust_i18n::t; @@ -523,7 +523,7 @@ fn pref_group( ))) .label(t!(row.label).to_string()) .checked((row.read)(&prefs)) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |checked: &bool, _window, app| { let checked = *checked; target.update(app, |this, cx| { diff --git a/crates/moon-ui-gpui/src/analytics/tuner/coins/mod.rs b/crates/moon-ui-gpui/src/analytics/tuner/coins/mod.rs index 76102e02..5ba6beec 100644 --- a/crates/moon-ui-gpui/src/analytics/tuner/coins/mod.rs +++ b/crates/moon-ui-gpui/src/analytics/tuner/coins/mod.rs @@ -29,9 +29,9 @@ pub(in crate::analytics::tuner) mod state; use gpui::prelude::FluentBuilder; use gpui::*; use moon_ui::{ - MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonCheckboxSize, MoonInput, - MoonInputEvent, MoonInputState, MoonPalette, MoonScrollbarVisibility, MoonSlider, - MoonSliderEvent, MoonSliderState, MoonVirtualList, h_flex, v_flex, + MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonInput, MoonInputEvent, + MoonInputState, MoonPalette, MoonScrollbarVisibility, MoonSize, MoonSlider, MoonSliderEvent, + MoonSliderState, MoonVirtualList, h_flex, v_flex, }; use rust_i18n::t; @@ -594,7 +594,7 @@ fn coin_row( if black_side { "bl" } else { "wl" } ))) .checked(on) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |_, _w, app| { let token = coin_token(&coin); // The view may already be gone; a dropped window is not an error here. diff --git a/crates/moon-ui-gpui/src/analytics/tuner/coins/picker.rs b/crates/moon-ui-gpui/src/analytics/tuner/coins/picker.rs index e9ad2e22..b41c7cc2 100644 --- a/crates/moon-ui-gpui/src/analytics/tuner/coins/picker.rs +++ b/crates/moon-ui-gpui/src/analytics/tuner/coins/picker.rs @@ -514,7 +514,6 @@ impl AnalyticsView { Some(n) => format!("{} {n}", t!("analytics.coins.pick_title")), None => t!("analytics.coins.pick_title").to_string(), }, - p, cx, )) // The field's own label, spelled as the strategy parameter it will be written to diff --git a/crates/moon-ui-gpui/src/analytics/tuner/filter/mod.rs b/crates/moon-ui-gpui/src/analytics/tuner/filter/mod.rs index c1a97ce1..6ef25d6a 100644 --- a/crates/moon-ui-gpui/src/analytics/tuner/filter/mod.rs +++ b/crates/moon-ui-gpui/src/analytics/tuner/filter/mod.rs @@ -20,8 +20,7 @@ use std::sync::Arc; use gpui::prelude::FluentBuilder; use gpui::*; use moon_ui::{ - MoonCheckbox, MoonCheckboxSize, MoonInput, MoonInputEvent, MoonInputState, MoonPalette, h_flex, - v_flex, + MoonCheckbox, MoonInput, MoonInputEvent, MoonInputState, MoonPalette, MoonSize, h_flex, v_flex, }; use rust_i18n::t; @@ -506,7 +505,7 @@ impl AnalyticsView { // The master checkbox ignores unmapped fields (no matching // strategy parameter): 'all enabled' = all MAPPED ones. .checked(self.tuner.all_mapped_enabled()) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change({ let view = cx.entity(); move |ch: &bool, _w, app| { @@ -633,7 +632,7 @@ impl AnalyticsView { div().flex_none().child( MoonCheckbox::new(SharedString::from(format!("tun-en-{fi}"))) .checked(self.tuner.enabled[fi]) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change({ let view = cx.entity(); move |ch: &bool, _w, app| { @@ -801,7 +800,6 @@ impl AnalyticsView { let header = self.shell_toolbar( TunerKind::Filter, t!("analytics.tuner.fields_title").to_string(), - p, cx, ); v_flex() diff --git a/crates/moon-ui-gpui/src/analytics/tuner/list/mod.rs b/crates/moon-ui-gpui/src/analytics/tuner/list/mod.rs index 34ae03f0..5da3ba97 100644 --- a/crates/moon-ui-gpui/src/analytics/tuner/list/mod.rs +++ b/crates/moon-ui-gpui/src/analytics/tuner/list/mod.rs @@ -16,8 +16,8 @@ mod tests; use gpui::*; use moon_ui::{ - MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonCheckboxSize, MoonDropdown, MoonInput, - MoonInputEvent, MoonInputState, MoonMenuItem, MoonMenuSize, MoonPalette, h_flex, + MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonDropdown, MoonInput, MoonInputEvent, + MoonInputState, MoonMenuItem, MoonMenuSize, MoonPalette, MoonSize, h_flex, }; use rust_i18n::t; use std::cmp::Ordering; @@ -441,7 +441,7 @@ impl AnalyticsView { div().font_family(design::ui_font()).child( MoonCheckbox::new("an-strat-active") .checked(self.strat_active_only) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .label(t!("analytics.strat.active_only").to_string()) .on_change({ let view = cx.entity(); diff --git a/crates/moon-ui-gpui/src/analytics/tuner/shell.rs b/crates/moon-ui-gpui/src/analytics/tuner/shell.rs index bfdfce7b..44c517a8 100644 --- a/crates/moon-ui-gpui/src/analytics/tuner/shell.rs +++ b/crates/moon-ui-gpui/src/analytics/tuner/shell.rs @@ -12,9 +12,9 @@ use gpui::prelude::FluentBuilder; use gpui::*; use moon_core::db::ReadFail; use moon_ui::{ - MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonCheckboxSize, MoonDropdown, - MoonInput, MoonInputEvent, MoonInputState, MoonMenuSize, MoonPalette, MoonPopover, - MoonPopoverPlacement, MoonTag, MoonTooltipView, h_flex, v_flex, + MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonDropdown, MoonInput, + MoonInputEvent, MoonInputState, MoonMenuSize, MoonPalette, MoonPopover, MoonPopoverPlacement, + MoonSize, MoonTag, MoonTooltipView, h_flex, v_flex, }; use rust_i18n::t; @@ -102,7 +102,6 @@ impl AnalyticsView { &self, kind: TunerKind, title: String, - p: MoonPalette, cx: &Context, ) -> AnyElement { let k = match kind { @@ -142,41 +141,35 @@ impl AnalyticsView { // Rounding the result affects the SUGGESTION — always shown (the suggestion is // available without a selected strategy too, over the current scope). if let Some(round) = round { - header = header - .child( - div() - .text_size(design::t_caption(cx)) - .text_color(moon(p.text_muted)) - .child(t!("analytics.tuner.round_lbl").to_string()), - ) - .child( - div().flex_none().child( - MoonCheckbox::new(SharedString::from(format!("tun-round-{k}"))) - .checked(round) - .size(MoonCheckboxSize::Compact) - .on_change({ - let view = cx.entity(); - move |ch: &bool, _w, app| { - let on = *ch; - view.update(app, |this, cx| { - match kind { - TunerKind::Filter => { - this.tuner.round_results = on; - this.tuner.invalidate_suggest(); - } - TunerKind::Time => { - this.time_tuner.round_results = on; - this.time_tuner.invalidate_suggest(); - } - // No rounding on this axis — the control is hidden. - TunerKind::Coins => {} + header = header.child( + div().flex_none().child( + MoonCheckbox::new(SharedString::from(format!("tun-round-{k}"))) + .label(t!("analytics.tuner.round_lbl").to_string()) + .checked(round) + .size(MoonSize::Sm) + .on_change({ + let view = cx.entity(); + move |ch: &bool, _w, app| { + let on = *ch; + view.update(app, |this, cx| { + match kind { + TunerKind::Filter => { + this.tuner.round_results = on; + this.tuner.invalidate_suggest(); } - cx.notify(); - }); - } - }), - ), - ); + TunerKind::Time => { + this.time_tuner.round_results = on; + this.time_tuner.invalidate_suggest(); + } + // No rounding on this axis — the control is hidden. + TunerKind::Coins => {} + } + cx.notify(); + }); + } + }), + ), + ); } // Render write controls for a retained anchor, but enable them only when the action // authority admits at least one selected target. @@ -724,8 +717,9 @@ impl AnalyticsView { .child( MoonCheckbox::new(SharedString::from("tun-cfg-compose-f")) .label(t!("analytics.tuner.compose_toggle").to_string()) + .description(t!("analytics.tuner.compose_short").to_string()) .checked(self.tuner.compose) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) // `on_change` hands the callback an `&mut App`, not a // `Context`, so this is one of the call sites where a // `cx.listener` does not fit. @@ -745,12 +739,6 @@ impl AnalyticsView { } }), ) - .child( - div() - .w_full() - .text_color(moon(p.text_muted)) - .child(t!("analytics.tuner.compose_short").to_string()), - ) .child( h_flex() .w_full() diff --git a/crates/moon-ui-gpui/src/analytics/tuner/time/grid.rs b/crates/moon-ui-gpui/src/analytics/tuner/time/grid.rs index ddfa2980..ae168f8d 100644 --- a/crates/moon-ui-gpui/src/analytics/tuner/time/grid.rs +++ b/crates/moon-ui-gpui/src/analytics/tuner/time/grid.rs @@ -16,7 +16,7 @@ use gpui::*; use moon_ui::{ - MoonCheckbox, MoonCheckboxSize, MoonInput, MoonInputEvent, MoonInputState, MoonPalette, + MoonCheckbox, MoonInput, MoonInputEvent, MoonInputState, MoonPalette, MoonSize, MoonTooltipView, h_flex, v_flex, }; use rust_i18n::t; @@ -28,10 +28,6 @@ use crate::design; use crate::design::{moon, moon_alpha}; use moon_core::db::tuner::TimeWindow; -/// Width of the row-checkbox column, in `design::ui_px` units. The header spacer and the -/// slider lead-in reuse it so the field names stay in one line down the card; it is sized -/// above the compact checkbox's own box, which moonui draws at a fixed size. -pub(in crate::analytics::tuner) const CHECK_COL: f32 = 16.0; /// Field-name column: fits "WorkingWeekTime" on one line next to the checkbox. pub(in crate::analytics::tuner) const NAME_COL: f32 = 110.0; @@ -359,7 +355,6 @@ impl AnalyticsView { let header = self.shell_toolbar( TunerKind::Time, t!("analytics.time.autopick_title").to_string(), - p, cx, ); let cfg_row = self.shell_config_row(TunerKind::Time, p, window, cx); @@ -386,10 +381,10 @@ impl AnalyticsView { .bg(moon(p.table_head)) // Master checkbox over the rows' column — the filter tuner's "all on/off". .child( - div().w(design::ui_px(cx, CHECK_COL)).flex_none().child( + div().flex_none().child( MoonCheckbox::new("tt-en-all") .checked(self.time_tuner.enabled.iter().all(|&e| e)) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change({ let view = cx.entity(); move |ch: &bool, _w, app| { @@ -530,12 +525,11 @@ impl AnalyticsView { let check = div() .id(SharedString::from(format!("tt-en-w-{field}"))) .flex_none() - .w(design::ui_px(cx, CHECK_COL)) .tooltip(move |_w, cx| cx.new(|_| MoonTooltipView::new(tip.clone())).into()) .child( MoonCheckbox::new(SharedString::from(format!("tt-en-{field}"))) .checked(enabled) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change({ let view = cx.entity(); move |ch: &bool, _w, app| { diff --git a/crates/moon-ui-gpui/src/analytics/tuner/time/sliders.rs b/crates/moon-ui-gpui/src/analytics/tuner/time/sliders.rs index 53445ada..bd90f3aa 100644 --- a/crates/moon-ui-gpui/src/analytics/tuner/time/sliders.rs +++ b/crates/moon-ui-gpui/src/analytics/tuner/time/sliders.rs @@ -13,12 +13,12 @@ //! cursor is not lost once it leaves the track. use gpui::*; -use moon_ui::{MoonPalette, h_flex, v_flex}; +use moon_ui::{MoonCheckbox, MoonPalette, MoonSize, h_flex, v_flex}; use rust_i18n::t; use super::super::super::AnalyticsView; use super::super::super::calendar::split_i18n; -use super::grid::{CHECK_COL, NAME_COL}; +use super::grid::NAME_COL; use super::state::{WEEK_MIN, fmt_min, fmt_week_ep, parse_moh, parse_time}; use crate::design; use crate::design::{moon, moon_alpha}; @@ -437,11 +437,18 @@ impl AnalyticsView { h_flex() .w_full() .items_end() - // Gap 4 (not 6) plus a CHECK_COL lead-in: together they reproduce the grid - // row's checkbox column, so the slider labels stay under the field names. + // Gap 4 (not 6) plus a checkbox-wide lead-in: together they reproduce the grid + // row's checkbox column, so the slider labels stay under the field names. The + // lead-in is an invisible `Sm` checkbox rather than a stated width, so it keeps MoonUI's + // own box size at any UI zoom; hidden, it takes layout but paints nothing. .gap(design::ui_px(cx, 4.0)) .opacity(if dim { 0.5 } else { 1.0 }) - .child(div().w(design::ui_px(cx, CHECK_COL)).flex_none()) + .child( + div().flex_none().invisible().child( + MoonCheckbox::new(SharedString::from(format!("tt-slider-lead-{field}"))) + .size(MoonSize::Sm), + ), + ) .child( // Matches the grid's field-name column so the slider labels line up under it. div() diff --git a/crates/moon-ui-gpui/src/chart_tabs/apply_row.rs b/crates/moon-ui-gpui/src/chart_tabs/apply_row.rs index 08341344..db5a5c4d 100644 --- a/crates/moon-ui-gpui/src/chart_tabs/apply_row.rs +++ b/crates/moon-ui-gpui/src/chart_tabs/apply_row.rs @@ -15,8 +15,8 @@ use gpui::*; use moon_core::config::ChartTabKind; use moon_ui::{ - MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonCheckboxSize, MoonPalette, - h_flex, v_flex, + MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonPalette, MoonSize, h_flex, + v_flex, }; use rust_i18n::t; @@ -120,7 +120,7 @@ pub(super) fn render_apply_row( MoonCheckbox::new(SharedString::from(format!("{id_prefix}-apply-{index}"))) .label(label) .checked(targets.has(kind)) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |checked: &bool, _w, app| { let checked = *checked; toggle_entity.update(app, |this, cx| { diff --git a/crates/moon-ui-gpui/src/chart_tabs/candle_popup.rs b/crates/moon-ui-gpui/src/chart_tabs/candle_popup.rs index 136b93f1..586ccd5f 100644 --- a/crates/moon-ui-gpui/src/chart_tabs/candle_popup.rs +++ b/crates/moon-ui-gpui/src/chart_tabs/candle_popup.rs @@ -12,7 +12,7 @@ use moon_core::market::candles::{ CandleViewCfg, }; use moon_ui::{ - MoonCheckbox, MoonCheckboxSize, MoonPalette, MoonPopover, MoonPopoverPlacement, h_flex, v_flex, + MoonCheckbox, MoonPalette, MoonPopover, MoonPopoverPlacement, MoonSize, h_flex, v_flex, }; use rust_i18n::t; @@ -108,7 +108,7 @@ fn flag_cb( MoonCheckbox::new(SharedString::from(format!("{id}-{suffix}"))) .label(t!(label_key).to_string()) .checked(checked) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |ch: &bool, _w, app| { let v = *ch; write_cfg(&entity, app, |c| set(c, v)); diff --git a/crates/moon-ui-gpui/src/chart_tabs/graphics_popup.rs b/crates/moon-ui-gpui/src/chart_tabs/graphics_popup.rs index 9230e7dd..f5428a08 100644 --- a/crates/moon-ui-gpui/src/chart_tabs/graphics_popup.rs +++ b/crates/moon-ui-gpui/src/chart_tabs/graphics_popup.rs @@ -20,7 +20,7 @@ use gpui::*; use moon_core::config::ChartGraphicsCfg; use moon_ui::{ - MoonCheckbox, MoonCheckboxSize, MoonPalette, MoonPopover, MoonPopoverPlacement, h_flex, v_flex, + MoonCheckbox, MoonPalette, MoonPopover, MoonPopoverPlacement, MoonSize, h_flex, v_flex, }; use rust_i18n::t; @@ -241,7 +241,7 @@ fn render_graphics_popup( MoonCheckbox::new(SharedString::from(format!("{id}-real"))) .label(t!("chart.graphics.real_trades").to_string()) .checked(cfg.show_real_trades) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |ch: &bool, _w, app| { let v = *ch; write_cfg(&entity, app, |c| c.show_real_trades = v); @@ -252,7 +252,7 @@ fn render_graphics_popup( MoonCheckbox::new(SharedString::from(format!("{id}-emulator"))) .label(t!("chart.graphics.emulator_trades").to_string()) .checked(cfg.show_emulator_trades) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |ch: &bool, _w, app| { let v = *ch; write_cfg(&entity, app, |c| c.show_emulator_trades = v); @@ -262,32 +262,26 @@ fn render_graphics_popup( let entity = entity.clone(); MoonCheckbox::new(SharedString::from(format!("{id}-hide-closed-sell"))) .label(t!("chart.graphics.hide_closed_sell").to_string()) + .description(t!("chart.graphics.hide_closed_sell_hint").to_string()) .checked(cfg.hide_closed_sell_line) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |ch: &bool, _w, app| { let v = *ch; write_cfg(&entity, app, |c| c.hide_closed_sell_line = v); }) }; - let hide_sell_hint = div() - .text_size(design::t_caption(cx)) - .text_color(rgb(p.text_muted)) - .child(t!("chart.graphics.hide_closed_sell_hint").to_string()); let hide_move_cb = { let entity = entity.clone(); MoonCheckbox::new(SharedString::from(format!("{id}-hide-move-history"))) .label(t!("chart.graphics.hide_move_history").to_string()) + .description(t!("chart.graphics.hide_move_history_hint").to_string()) .checked(cfg.hide_order_move_history) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |ch: &bool, _w, app| { let v = *ch; write_cfg(&entity, app, |c| c.hide_order_move_history = v); }) }; - let hide_move_hint = div() - .text_size(design::t_caption(cx)) - .text_color(rgb(p.text_muted)) - .child(t!("chart.graphics.hide_move_history_hint").to_string()); // --- Trade marks: the live trade crosses and their per-trade volume bars. --- let marker_scale_row = { @@ -410,7 +404,7 @@ fn render_graphics_popup( MoonCheckbox::new(SharedString::from(format!("{id}-volume-sides"))) .label(t!("chart.graphics.volume_sides").to_string()) .checked(sides_on) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |ch: &bool, _w, app| { let v = *ch; write_cfg(&entity, app, |c| c.candle_volume_sides = v); @@ -585,9 +579,7 @@ fn render_graphics_popup( v_flex() .gap(design::ui_px(cx, 6.0)) .child(hide_sell_cb) - .child(hide_sell_hint) - .child(hide_move_cb) - .child(hide_move_hint), + .child(hide_move_cb), ), ) .child( diff --git a/crates/moon-ui-gpui/src/chart_tabs/layout_popup.rs b/crates/moon-ui-gpui/src/chart_tabs/layout_popup.rs index a1770c4c..06f9d42c 100644 --- a/crates/moon-ui-gpui/src/chart_tabs/layout_popup.rs +++ b/crates/moon-ui-gpui/src/chart_tabs/layout_popup.rs @@ -8,8 +8,8 @@ use gpui::*; use moon_ui::{ - MoonAccent, MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonCheckboxSize, - MoonInput, MoonInputState, MoonPalette, MoonSegmentItem, MoonSegmentedControl, h_flex, v_flex, + MoonAccent, MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonInput, + MoonInputState, MoonPalette, MoonSegmentItem, MoonSegmentedControl, MoonSize, h_flex, v_flex, }; use rust_i18n::t; @@ -315,7 +315,7 @@ where let exact_cb = MoonCheckbox::new(SharedString::from(format!("{id}-divider-exact"))) .label(t!("chart.layout.divider_exact").to_string()) .checked(divider_exact) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |ch: &bool, _w, app| on_toggle_exact(*ch, app)); // Shown only where it can act: FIT-stretch, whose slots share the space and so state no size // that could say when the charts have stopped fitting. @@ -359,49 +359,49 @@ where let orderbook_cb = MoonCheckbox::new(SharedString::from(format!("{id}-orderbook"))) .label(t!("chart.layout.orderbook").to_string()) .checked(orderbook_enabled) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |ch: &bool, _w, app| on_toggle_orderbook(*ch, app)); // "Liquidations" toggles liquidation-trade crosses on this tab's charts. let liquidations_cb = MoonCheckbox::new(SharedString::from(format!("{id}-liquidations"))) .label(t!("chart.layout.liquidations").to_string()) .checked(liquidations_enabled) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |ch: &bool, _w, app| on_toggle_liquidations(*ch, app)); // "Show control zone" toggles the dim order-zone fill while the order book is hidden. let show_zone_cb = MoonCheckbox::new(SharedString::from(format!("{id}-show-zone"))) .label(t!("chart.layout.show_zone").to_string()) .checked(show_zone) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |ch: &bool, _w, app| on_toggle_show_zone(*ch, app)); // "Auto-pin on order" pins a chart when placing a long or short order. let auto_pin_cb = MoonCheckbox::new(SharedString::from(format!("{id}-auto-pin"))) .label(t!("chart.layout.auto_pin").to_string()) .checked(auto_pin) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |ch: &bool, _w, app| on_toggle_auto_pin(*ch, app)); // "Time axis" toggles bottom time labels on this tab's charts. let time_axis_cb = MoonCheckbox::new(SharedString::from(format!("{id}-time-axis"))) .label(t!("chart.layout.time_axis").to_string()) .checked(time_axis_visible) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |ch: &bool, _w, app| on_toggle_time_axis(*ch, app)); // "Line labels" toggles values beside order lines, including size, percentage, and stop. let line_labels_cb = MoonCheckbox::new(SharedString::from(format!("{id}-line-labels"))) .label(t!("chart.layout.line_labels").to_string()) .checked(line_labels) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |ch: &bool, _w, app| on_toggle_line_labels(*ch, app)); // "Crosshair label" toggles the cursor readout for time, price, percentage, volume, and size. let cursor_labels_cb = MoonCheckbox::new(SharedString::from(format!("{id}-cursor-labels"))) .label(t!("chart.layout.cursor_labels").to_string()) .checked(cursor_labels) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |ch: &bool, _w, app| on_toggle_cursor_labels(*ch, app)); // "Detect flow" frame: how many charts detects may open on this tab, what a detect does once @@ -431,7 +431,7 @@ where let evict_cb = MoonCheckbox::new(SharedString::from(format!("{id}-max-charts-evict"))) .label(t!("chart.layout.max_charts_evict").to_string()) .checked(cap.evict) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |ch: &bool, _w, app| (cap.on_toggle_evict)(*ch, app)); v_flex() .gap(design::ui_px(cx, 6.0)) @@ -444,7 +444,7 @@ where let flash_cb = MoonCheckbox::new(SharedString::from(format!("{id}-no-arrival-flash"))) .label(t!("chart.layout.no_arrival_flash").to_string()) .checked(!flow.flash) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |ch: &bool, _w, app| (flow.on_toggle_flash)(!*ch, app)); popup_group("frame-detect-flow", t!("chart.layout.frame_detect_flow")).child( v_flex() diff --git a/crates/moon-ui-gpui/src/chart_tabs/main_stack/empty.rs b/crates/moon-ui-gpui/src/chart_tabs/main_stack/empty.rs index 0d434d70..0e5712d1 100644 --- a/crates/moon-ui-gpui/src/chart_tabs/main_stack/empty.rs +++ b/crates/moon-ui-gpui/src/chart_tabs/main_stack/empty.rs @@ -41,7 +41,7 @@ use gpui::{ SharedString, StatefulInteractiveElement, Styled, Window, div, px, rgb, }; use moon_core::config::layout::{EmptyBlock, EmptyPlaces, WindowLayout}; -use moon_ui::{MoonCheckbox, MoonCheckboxSize, MoonPalette, MoonPopover, MoonPopoverPlacement}; +use moon_ui::{MoonCheckbox, MoonPalette, MoonPopover, MoonPopoverPlacement, MoonSize}; use rust_i18n::t; use super::MainChartStack; @@ -678,7 +678,7 @@ fn settings_content( MoonCheckbox::new(id(switch.id)) .label(t!(switch.label).to_string()) .checked((switch.read)(&screen)) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |checked: &bool, _window, app| { let checked = *checked; view.update(app, |this, cx| this.set_switch(switch, checked, cx)); diff --git a/crates/moon-ui-gpui/src/chart_tabs/main_stack/empty/arrange.rs b/crates/moon-ui-gpui/src/chart_tabs/main_stack/empty/arrange.rs index c6c13a73..8d5c6c1d 100644 --- a/crates/moon-ui-gpui/src/chart_tabs/main_stack/empty/arrange.rs +++ b/crates/moon-ui-gpui/src/chart_tabs/main_stack/empty/arrange.rs @@ -268,7 +268,7 @@ fn row( div() .flex_1() .min_w_0() - .text_size(design::text_px(cx, COMPACT_CHECKBOX_FONT)) + .text_size(design::ui_px(cx, COMPACT_CHECKBOX_FONT)) .text_color(rgb(palette.text_soft)) .child(t!(block_label(block)).to_string()), ) diff --git a/crates/moon-ui-gpui/src/chart_tabs/main_stack/empty/detect.rs b/crates/moon-ui-gpui/src/chart_tabs/main_stack/empty/detect.rs index 66b7dcac..020d39db 100644 --- a/crates/moon-ui-gpui/src/chart_tabs/main_stack/empty/detect.rs +++ b/crates/moon-ui-gpui/src/chart_tabs/main_stack/empty/detect.rs @@ -26,7 +26,7 @@ use moon_core::config::layout::{EmptyPlaces, WindowLayout}; use moon_core::crowd::CrowdRule; use moon_core::crowd::detect::{DEFAULT_PROFIT, DEFAULT_TRADES, SEATS}; use moon_ui::{ - MoonCheckbox, MoonCheckboxSize, MoonInput, MoonInputEvent, MoonInputState, MoonPalette, h_flex, + MoonCheckbox, MoonInput, MoonInputEvent, MoonInputState, MoonPalette, MoonSize, h_flex, rgba_from, }; use rust_i18n::t; @@ -461,7 +461,7 @@ pub(super) fn block( .label(t!("crowd.settings.detect_evict", max = SEATS.to_string()).to_string()) .checked(cards.evict) .disabled(!enabled) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |checked: &bool, _window, app| { let checked = *checked; view.update(app, |this, cx| this.set_crowd_evict(checked, cx)); @@ -505,7 +505,7 @@ fn field_row( // soft text, and the same fade when dead. div() .flex_1() - .text_size(design::text_px(cx, COMPACT_CHECKBOX_FONT)) + .text_size(design::ui_px(cx, COMPACT_CHECKBOX_FONT)) .text_color(if enabled { rgba_from(palette.text_soft, 1.0) } else { diff --git a/crates/moon-ui-gpui/src/controls/coin_search.rs b/crates/moon-ui-gpui/src/controls/coin_search.rs index f92c8f0c..2754b519 100644 --- a/crates/moon-ui-gpui/src/controls/coin_search.rs +++ b/crates/moon-ui-gpui/src/controls/coin_search.rs @@ -21,8 +21,8 @@ use std::collections::{HashMap, HashSet}; use gpui::prelude::FluentBuilder; use gpui::*; use moon_ui::{ - MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonCheckboxSize, MoonDisclosure, - MoonDisclosureDirection, MoonInputState, MoonPalette, h_flex, + MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonDisclosure, + MoonDisclosureDirection, MoonInputState, MoonPalette, MoonSize, h_flex, }; use rust_i18n::t; @@ -980,7 +980,7 @@ where "{id}-{section}-cb-{i}" ))) .checked(checked) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change( move |_v: &bool, _w, app| { on_toggle_row(pick_core_id, market_toggle.clone(), app); @@ -1099,7 +1099,7 @@ where "{id}-{section}-cb-{i}" ))) .checked(checked) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change( move |_v: &bool, _w, app| { on_toggle_child(core, market_toggle.clone(), app); diff --git a/crates/moon-ui-gpui/src/controls/manual_strat/settings.rs b/crates/moon-ui-gpui/src/controls/manual_strat/settings.rs index fe436e15..904ab9e5 100644 --- a/crates/moon-ui-gpui/src/controls/manual_strat/settings.rs +++ b/crates/moon-ui-gpui/src/controls/manual_strat/settings.rs @@ -21,8 +21,8 @@ use gpui::*; use moon_core::config::MANUAL_STRAT_SLOTS; use moon_core::session::CoreId; use moon_ui::{ - MoonButton, MoonButtonIconSlot, MoonButtonSize, MoonButtonVariant, MoonCheckbox, - MoonCheckboxSize, MoonDropdown, MoonMenuItem, MoonMenuSize, MoonPalette, h_flex, v_flex, + MoonButton, MoonButtonIconSlot, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonDropdown, + MoonMenuItem, MoonMenuSize, MoonPalette, MoonSize, h_flex, v_flex, }; use rust_i18n::t; @@ -131,13 +131,13 @@ pub(super) fn slot_settings_content( .gap(gap) .child( div() - .w(px(design::font_w(cx, SLOT_COL_W))) + .min_w(px(design::font_w(cx, SLOT_COL_W))) .flex_none() .child( MoonCheckbox::new(SharedString::from(format!("ms-slot-show-{slot}"))) .label(format!("{}", slot + 1)) .checked(current.show) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |checked: &bool, _w, app| { let show = *checked; show_backend.update(app, |b, cx| { @@ -220,27 +220,18 @@ pub(super) fn slot_settings_content( // Moonbot's own stop rule, and the default. Local state, so it is offered whether or not // the core has reported anything. .child( - v_flex() - .gap(design::ui_px(cx, 2.0)) - .child( - MoonCheckbox::new("ms-mb-logic") - .label(t!("header.ms_mb_logic").to_string()) - .checked(mb_logic) - .size(MoonCheckboxSize::Compact) - .on_change(move |checked: &bool, _w, app| { - let on = *checked; - logic_backend.update(app, |b, cx| { - b.set_ms_mb_logic(core, on); - cx.notify(); - }); - }), - ) - .child( - div() - .text_size(design::t_caption(cx)) - .text_color(rgb(p.text_muted)) - .child(t!("header.ms_mb_logic_hint").to_string()), - ), + MoonCheckbox::new("ms-mb-logic") + .label(t!("header.ms_mb_logic").to_string()) + .description(t!("header.ms_mb_logic_hint").to_string()) + .checked(mb_logic) + .size(MoonSize::Sm) + .on_change(move |checked: &bool, _w, app| { + let on = *checked; + logic_backend.update(app, |b, cx| { + b.set_ms_mb_logic(core, on); + cx.notify(); + }); + }), ) // The core's own flag, not a local one: while it is OFF the core applies a manual // strategy's own sell price and the toolbar's TP/S do not reach a manual order at all. @@ -248,7 +239,7 @@ pub(super) fn slot_settings_content( MoonCheckbox::new("ms-ignore-strat-sell") .label(t!("header.ms_ignore_strat_sell").to_string()) .checked(on) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |checked: &bool, _w, app| { let on = *checked; sell_backend.update(app, |b, cx| { diff --git a/crates/moon-ui-gpui/src/controls/metric.rs b/crates/moon-ui-gpui/src/controls/metric.rs index fbc23f22..1de1f2f6 100644 --- a/crates/moon-ui-gpui/src/controls/metric.rs +++ b/crates/moon-ui-gpui/src/controls/metric.rs @@ -6,9 +6,9 @@ use gpui::*; use rust_i18n::t; use moon_ui::{ - MoonButton, MoonButtonSegment, MoonButtonSize, MoonButtonVariant, MoonCheckbox, - MoonCheckboxSize, MoonInput, MoonInputState, MoonPalette, MoonPopover, MoonPopoverPlacement, - MoonSlider, MoonSliderState, MoonToggle, MoonToggleLabelSide, MoonToggleSize, h_flex, v_flex, + MoonButton, MoonButtonSegment, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonInput, + MoonInputState, MoonPalette, MoonPopover, MoonPopoverPlacement, MoonSize, MoonSlider, + MoonSliderState, MoonToggle, MoonToggleLabelSide, MoonToggleSize, h_flex, v_flex, }; use moon_core::feed::ClientSettingsEdit; @@ -728,7 +728,7 @@ pub fn metric_popup_content( MoonCheckbox::new("toolbar-tp-ext") .label(t!("toolbar.tp_ext").to_string()) .checked(extended) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |ch: &bool, _w, app| { let ext = *ch; let is_live = { @@ -790,7 +790,7 @@ pub fn metric_popup_content( MoonCheckbox::new("toolbar-stop-market") .label(t!("toolbar.stop_market").to_string()) .checked(stop_market_on) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |ch: &bool, _w, app| { let on = *ch; let is_live = { @@ -814,7 +814,7 @@ pub fn metric_popup_content( MoonCheckbox::new("toolbar-hedge") .label(t!("toolbar.hedge").to_string()) .checked(hedge_on) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change({ let backend = backend.clone(); let group = group.clone(); diff --git a/crates/moon-ui-gpui/src/core_expert/pages/login.rs b/crates/moon-ui-gpui/src/core_expert/pages/login.rs index 4e3e19d2..e71d0a15 100644 --- a/crates/moon-ui-gpui/src/core_expert/pages/login.rs +++ b/crates/moon-ui-gpui/src/core_expert/pages/login.rs @@ -19,8 +19,8 @@ use crate::shell::editors::EditorStore; use super::super::CoreExpertView; use super::super::widgets::{ - action, caption, columns, dropdown, field, field_masked, flag, group, hint, labeled, link, - rows, text_block, text_line, + action, caption, columns, dropdown, field, field_masked, flag, flag_described, group, hint, + labeled, link, rows, text_block, text_line, }; /// Nothing on this page reaches the draft; every field stages through this. @@ -151,15 +151,15 @@ pub(super) fn body( t!("core_expert.log_change_password").to_string(), false, )) - .child(flag( + .child(flag_described( "exp-log-debug-data", t!("core_expert.log_debug_data").to_string(), + Some(t!("core_expert.log_debug_hint").to_string()), false, false, view, |_, _| {}, - )) - .child(hint(t!("core_expert.log_debug_hint").to_string(), p, cx)); + )); // --- Right: licence, support, and what Moonbot sends to its own server ----------------------- let support = group( diff --git a/crates/moon-ui-gpui/src/core_expert/pages/telegram.rs b/crates/moon-ui-gpui/src/core_expert/pages/telegram.rs index 74608950..f06a5b2d 100644 --- a/crates/moon-ui-gpui/src/core_expert/pages/telegram.rs +++ b/crates/moon-ui-gpui/src/core_expert/pages/telegram.rs @@ -21,8 +21,8 @@ use crate::shell::editors::{CoreDraftHost, EditorStore}; use super::super::CoreExpertView; use super::super::widgets::{ - action, action_live, caption, columns, field, flag, group, hint, list_box_select, rows, - text_block, + action, action_live, caption, columns, field, flag, flag_described, group, list_box_select, + rows, text_block, }; /// See [`super::scratch_specs`]. @@ -295,21 +295,15 @@ pub(super) fn body( .w_full() .items_start() .gap(design::ui_px(cx, 12.0)) - .child( - v_flex() - .flex_1() - .min_w_0() - .gap(design::ui_px(cx, 2.0)) - .child(flag( - "exp-tlg-premium", - t!("core_expert.tlg_premium").to_string(), - t.listen_moon_channel, - true, - view, - |d, on| d.telegram.listen_moon_channel = on, - )) - .child(hint(t!("core_expert.tlg_premium_paid").to_string(), p, cx)), - ) + .child(div().flex_1().min_w_0().child(flag_described( + "exp-tlg-premium", + t!("core_expert.tlg_premium").to_string(), + Some(t!("core_expert.tlg_premium_paid").to_string()), + t.listen_moon_channel, + true, + view, + |d, on| d.telegram.listen_moon_channel = on, + ))) .child(div().flex_1().min_w_0().child(flag( "exp-tlg-send-stats", t!("core_expert.tlg_send_stats").to_string(), diff --git a/crates/moon-ui-gpui/src/core_expert/render.rs b/crates/moon-ui-gpui/src/core_expert/render.rs index cce73e6c..c3aa2bae 100644 --- a/crates/moon-ui-gpui/src/core_expert/render.rs +++ b/crates/moon-ui-gpui/src/core_expert/render.rs @@ -9,8 +9,8 @@ use gpui::prelude::FluentBuilder; use gpui::*; use moon_ui::{ - MoonAlert, MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonCheckboxSize, - MoonPalette, MoonTabItem, MoonTabStrip, MoonWindowFrame, h_flex, v_flex, + MoonAlert, MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonPalette, MoonSize, + MoonTabItem, MoonTabStrip, MoonWindowFrame, h_flex, v_flex, }; use rust_i18n::t; @@ -154,7 +154,7 @@ impl CoreExpertView { MoonCheckbox::new("core-expert-mode") .label(t!("core_settings.expert").to_string()) .checked(expert) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |value, window, cx| { if *value { return; diff --git a/crates/moon-ui-gpui/src/core_expert/widgets.rs b/crates/moon-ui-gpui/src/core_expert/widgets.rs index 65aa1507..ea3d7c44 100644 --- a/crates/moon-ui-gpui/src/core_expert/widgets.rs +++ b/crates/moon-ui-gpui/src/core_expert/widgets.rs @@ -16,9 +16,9 @@ use gpui::prelude::FluentBuilder; use gpui::*; use moon_ui::{ - MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonCheckboxSize, MoonDropdown, - MoonGroupBox, MoonInput, MoonLink, MoonMenuItem, MoonMenuSize, MoonPalette, MoonRadio, - MoonRadioSize, MoonSlider, MoonStepper, MoonStepperSize, MoonText, MoonTone, h_flex, v_flex, + MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonDropdown, MoonGroupBox, + MoonInput, MoonLink, MoonMenuItem, MoonMenuSize, MoonPalette, MoonRadio, MoonRadioSize, + MoonSize, MoonSlider, MoonStepper, MoonStepperSize, MoonText, MoonTone, h_flex, v_flex, }; use rust_i18n::t; @@ -50,6 +50,20 @@ pub(super) fn flag( enabled: bool, view: &Entity, set: fn(&mut CoreConfig, bool), +) -> impl IntoElement { + flag_described(id, label, None, checked, enabled, view, set) +} + +/// [`flag`] with Moonbot's explanatory line for the row, drawn as the checkbox's own description +/// under its caption rather than as a separate [`hint`] beside it. +pub(super) fn flag_described( + id: &'static str, + label: String, + description: Option, + checked: bool, + enabled: bool, + view: &Entity, + set: fn(&mut CoreConfig, bool), ) -> impl IntoElement { let view = view.clone(); // Mixed across the selection: drawn EMPTY inside the mixed frame until the trader picks one, @@ -63,10 +77,13 @@ pub(super) fn flag( mixed, MoonCheckbox::new(SharedString::from(id)) .label(label) + .when_some(description, |this, description| { + this.description(description) + }) .checked(checked && !mixed) .tone(design::mixed_tone(mixed)) .disabled(!enabled) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |ch: &bool, _w, app| { let on = *ch; view.update(app, |this, cx| { diff --git a/crates/moon-ui-gpui/src/design.rs b/crates/moon-ui-gpui/src/design.rs index 80c577f6..4e9e3e0b 100644 --- a/crates/moon-ui-gpui/src/design.rs +++ b/crates/moon-ui-gpui/src/design.rs @@ -1085,15 +1085,18 @@ pub const ACTION_LABEL_BASE: f32 = 10.5; /// font: a key derived from a hand-copied version of these three lines would keep validating stale /// widths the day the resolution changes. fn measure_font(cx: &App, base_font_size: f32, weight: f32, mono: bool) -> (FontId, Pixels) { + let size = MoonTheme::active_tokens(cx).font(base_font_size); + measure_font_at(cx, px(size), weight, mono) +} + +/// Resolve the active theme font at an already rendered `size`. +fn measure_font_at(cx: &App, size: Pixels, weight: f32, mono: bool) -> (FontId, Pixels) { let tokens = MoonTheme::active_tokens(cx); let font = Font { weight: FontWeight(weight), ..font(tokens.font_family(mono)) }; - ( - cx.text_system().resolve_font(&font), - px(tokens.font(base_font_size)), - ) + (cx.text_system().resolve_font(&font), size) } /// Identity of the typography a text measurement was taken under. @@ -1134,6 +1137,37 @@ pub fn text_metrics_key(cx: &App, base_font_size: f32, weight: f32, mono: bool) /// Returns: /// The summed glyph-advance estimate in pixels. pub fn ui_text_width(cx: &App, text: &str, base_font_size: f32, weight: f32, mono: bool) -> f32 { + glyph_advance_width(cx, text, measure_font(cx, base_font_size, weight, mono)) +} + +/// Estimate text width for text that follows only the UI zoom, not the Font slider. +/// +/// For MoonUI controls whose tiers fix their text size, such as the `Sm`/`Md` `MoonCheckbox` +/// label: that text renders at `ui(base_font_size)` whatever the Font slider says, so measuring it +/// through [`ui_text_width`] would over-reserve by the slider's delta. Same estimate otherwise. +/// +/// Args: +/// cx: Application context providing active tokens and the text system. +/// text: Text to measure. +/// base_font_size: Design size before UI zoom. +/// weight: Font weight represented as the GPUI numeric value. +/// mono: Whether to use the theme's monospaced rather than UI font family. +/// +/// Returns: +/// The summed glyph-advance estimate in pixels. +pub fn ui_text_width_zoomed( + cx: &App, + text: &str, + base_font_size: f32, + weight: f32, + mono: bool, +) -> f32 { + let size = ui_px(cx, base_font_size); + glyph_advance_width(cx, text, measure_font_at(cx, size, weight, mono)) +} + +/// Sum the cached glyph advances of `text` in one resolved font and size. +fn glyph_advance_width(cx: &App, text: &str, (font_id, size): (FontId, Pixels)) -> f32 { // Counted, because the callers run this every frame: see `diag::UI_TEXT_WIDTH_CALLS`. let measured = crate::diag::timer(); crate::diag::bump(&crate::diag::UI_TEXT_WIDTH_CALLS); @@ -1141,7 +1175,6 @@ pub fn ui_text_width(cx: &App, text: &str, base_font_size: f32, weight: f32, mon &crate::diag::UI_TEXT_WIDTH_CHARS, text.chars().count() as u64, ); - let (font_id, size) = measure_font(cx, base_font_size, weight, mono); let size_bits = size.as_f32().to_bits(); let ts = cx.text_system(); let width: f32 = GLYPH_ADVANCE.with(|cache| { diff --git a/crates/moon-ui-gpui/src/figstyle/mod.rs b/crates/moon-ui-gpui/src/figstyle/mod.rs index 50cb23ae..65cd0407 100644 --- a/crates/moon-ui-gpui/src/figstyle/mod.rs +++ b/crates/moon-ui-gpui/src/figstyle/mod.rs @@ -30,7 +30,7 @@ use gpui::*; use moon_ui::{ - MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonCheckboxSize, MoonPalette, + MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonPalette, MoonSize, MoonTooltipView, h_flex, v_flex, }; @@ -527,7 +527,7 @@ fn fill_row( MoonCheckbox::new("figset-fill-off") .label(t!("chart.fig.no_fill").to_string()) .checked(!has_fill) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |off, _, app| { backend_off.update(app, |b, bcx| { if edit_style(b, &target_off, &authority_off, |s| { @@ -712,7 +712,7 @@ fn hotkey_cycle_row( .child( MoonCheckbox::new("figset-hotkey-cb") .checked(on) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .label(t!("chart.fig.hotkey").to_string()) .on_change(move |checked: &bool, _window, app| { edit_hotkey_cycle(&backend, tool, *checked, app); diff --git a/crates/moon-ui-gpui/src/panels/alerts/table.rs b/crates/moon-ui-gpui/src/panels/alerts/table.rs index 3de55e70..83e412bc 100644 --- a/crates/moon-ui-gpui/src/panels/alerts/table.rs +++ b/crates/moon-ui-gpui/src/panels/alerts/table.rs @@ -3,9 +3,9 @@ use super::*; use moon_ui::{ - MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonCheckboxSize, MoonDataCell, - MoonDataRow, MoonDataTable, MoonDataTableColumn, MoonDropdown, MoonMenuSize, MoonPopover, - MoonPopoverPlacement, MoonTone, h_flex, + MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonDataCell, MoonDataRow, + MoonDataTable, MoonDataTableColumn, MoonDropdown, MoonMenuSize, MoonPopover, + MoonPopoverPlacement, MoonSize, MoonTone, h_flex, }; use rust_i18n::t; @@ -242,7 +242,7 @@ fn alert_cell(row: &FigRow, ctx: &RowCtx) -> AnyElement { MoonCheckbox::new(SharedString::from(format!("al-arm-{core}-{id}"))) .checked(row.armed) .disabled(!editable) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |on: &bool, _w, app| { let (on, market) = (*on, market.clone()); ctx.commit_core(app, core, move |b| { diff --git a/crates/moon-ui-gpui/src/panels/arb_edit/body.rs b/crates/moon-ui-gpui/src/panels/arb_edit/body.rs index 4100c621..0e432405 100644 --- a/crates/moon-ui-gpui/src/panels/arb_edit/body.rs +++ b/crates/moon-ui-gpui/src/panels/arb_edit/body.rs @@ -5,7 +5,7 @@ use gpui::*; use moon_core::config::{ArbShow, ArbVenueCfg}; -use moon_ui::{MoonButtonVariant, MoonCheckbox, MoonCheckboxSize, MoonPalette, h_flex, v_flex}; +use moon_ui::{MoonButtonVariant, MoonCheckbox, MoonPalette, MoonSize, h_flex, v_flex}; use rust_i18n::t; use super::ArbEditState; @@ -68,7 +68,7 @@ pub(super) fn dialog_body(state: &Entity, cx: &mut App) -> AnyElem MoonCheckbox::new("arb-blocked") .label(t!("arb.mark_blocked").to_string()) .checked(on) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |v: &bool, _w, cx| { let v = *v; ArbEditState::write(&state, cx, |cfg| cfg.mark_blocked = v); diff --git a/crates/moon-ui-gpui/src/panels/assets/settings.rs b/crates/moon-ui-gpui/src/panels/assets/settings.rs index cc24c4c9..af034261 100644 --- a/crates/moon-ui-gpui/src/panels/assets/settings.rs +++ b/crates/moon-ui-gpui/src/panels/assets/settings.rs @@ -8,13 +8,12 @@ //! disagree about the shape of the list. use super::*; -use moon_ui::{ - MoonCheckbox, MoonCheckboxSize, MoonGroupBox, MoonPopover, MoonPopoverPlacement, MoonTheme, -}; +use moon_ui::{MoonCheckbox, MoonGroupBox, MoonPopover, MoonPopoverPlacement, MoonSize, MoonTheme}; use crate::panels::{ - COMPACT_CHECKBOX_FONT, COMPACT_CHECKBOX_GAP, COMPACT_CHECKBOX_MARK, POPUP_GROUP_CAPTION_FONT, - popup_close_button, popup_gear_trigger, popup_group, popup_group_inset_px, popup_title, + COMPACT_CHECKBOX_FONT, COMPACT_CHECKBOX_GAP, COMPACT_CHECKBOX_MARK, COMPACT_CHECKBOX_WEIGHT, + POPUP_GROUP_CAPTION_FONT, popup_close_button, popup_gear_trigger, popup_group, + popup_group_inset_px, popup_title, }; /// Caption of the popup's display-preferences group. @@ -164,11 +163,11 @@ fn settings_content_width(cx: &App) -> f32 { 600.0, true, ); - let label_width = design::ui_text_width( + let label_width = design::ui_text_width_zoomed( cx, &t!(GROUP_BY_VENUE_LABEL), COMPACT_CHECKBOX_FONT, - 400.0, + COMPACT_CHECKBOX_WEIGHT, false, ); let checkbox_leading = f32::from(design::ui_px( @@ -230,7 +229,7 @@ fn display_group(group_by_venue: bool, view: Entity) -> MoonGroupBox MoonCheckbox::new("assets-pref-group-by-venue") .label(t!(GROUP_BY_VENUE_LABEL).to_string()) .checked(group_by_venue) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |checked: &bool, _window, app| { let checked = *checked; view.update(app, |this, cx| this.write_group_by_venue(checked, cx)); diff --git a/crates/moon-ui-gpui/src/panels/common.rs b/crates/moon-ui-gpui/src/panels/common.rs index 0fdbb731..def087d9 100644 --- a/crates/moon-ui-gpui/src/panels/common.rs +++ b/crates/moon-ui-gpui/src/panels/common.rs @@ -343,20 +343,27 @@ pub(crate) const POPUP_GROUP_PAD: f32 = 6.0; /// all three. pub(crate) const POPUP_GROUP_INSET: f32 = 2.0 * (POPUP_GROUP_PAD + 1.0); -/// Compact `MoonCheckbox` mark width in design units. +/// `MoonSize::Sm` `MoonCheckbox` box width in design units. /// -/// The Compact checkbox's own geometry, which MoonUI exposes as a size variant rather than as -/// readable tokens: a settings popup that measures its content has to know how much room the mark -/// and its gap take before the label starts. Stated once here for the same reason -/// [`POPUP_GROUP_INSET`] is — two popups measuring the same control with numbers of their own -/// drift apart the first time either is nudged. -pub(crate) const COMPACT_CHECKBOX_MARK: f32 = 12.0; +/// The `Sm` checkbox's own geometry, which MoonUI exposes as a size tier rather than as readable +/// tokens: a settings popup that measures its content has to know how much room the box and its +/// gap take before the label starts. Stated once here for the same reason [`POPUP_GROUP_INSET`] +/// is — two popups measuring the same control with numbers of their own drift apart the first time +/// either is nudged. MIRRORS MoonUI's `MoonCheckboxMetrics::base_for_size(Size::Small)`. +pub(crate) const COMPACT_CHECKBOX_MARK: f32 = 16.0; -/// Design-unit gap a compact `MoonCheckbox` leaves between its mark and its label. -pub(crate) const COMPACT_CHECKBOX_GAP: f32 = 6.0; +/// Design-unit gap an `Sm` `MoonCheckbox` leaves between its box and its label. +pub(crate) const COMPACT_CHECKBOX_GAP: f32 = 8.0; -/// Compact `MoonCheckbox` label size before font scaling. -pub(crate) const COMPACT_CHECKBOX_FONT: f32 = 9.5; +/// `Sm` `MoonCheckbox` label size before UI zoom. +/// +/// MoonUI fixes a tier checkbox's text: it follows the UI zoom but not the Font slider. Size text +/// that matches this label with `design::ui_px` and measure it with `design::ui_text_width_zoomed`, +/// never through the font-scaled `text_px` / `ui_text_width`, which would add the slider's delta. +pub(crate) const COMPACT_CHECKBOX_FONT: f32 = 14.0; + +/// `Sm` `MoonCheckbox` label weight (medium), as GPUI's numeric font weight. +pub(crate) const COMPACT_CHECKBOX_WEIGHT: f32 = 500.0; /// Opacity a compact `MoonCheckbox` fades its label to while disabled. /// diff --git a/crates/moon-ui-gpui/src/panels/core_status/config_popup.rs b/crates/moon-ui-gpui/src/panels/core_status/config_popup.rs index 0203ee5f..a54a8543 100644 --- a/crates/moon-ui-gpui/src/panels/core_status/config_popup.rs +++ b/crates/moon-ui-gpui/src/panels/core_status/config_popup.rs @@ -9,8 +9,8 @@ use gpui::prelude::FluentBuilder; use gpui::*; use moon_ui::{ - MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonCheckboxSize, MoonDropdown, - MoonMenuSize, MoonPalette, MoonPopover, MoonPopoverPlacement, h_flex, v_flex, + MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonDropdown, MoonMenuSize, + MoonPalette, MoonPopover, MoonPopoverPlacement, MoonSize, h_flex, v_flex, }; use rust_i18n::t; @@ -803,7 +803,7 @@ fn enable_checkbox( let backend = backend.clone(); MoonCheckbox::new(SharedString::from(id)) .checked(checked) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |ch: &bool, _w, app| { let on = *ch; backend.update(app, |b, cx| { @@ -825,7 +825,7 @@ fn chart_checkbox( let backend = backend.clone(); MoonCheckbox::new(SharedString::from(id)) .checked(checked) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |ch: &bool, _w, app| { let on = *ch; backend.update(app, |b, cx| { diff --git a/crates/moon-ui-gpui/src/panels/detects/popup.rs b/crates/moon-ui-gpui/src/panels/detects/popup.rs index 9619e391..9d2b3f4d 100644 --- a/crates/moon-ui-gpui/src/panels/detects/popup.rs +++ b/crates/moon-ui-gpui/src/panels/detects/popup.rs @@ -9,9 +9,10 @@ use gpui::*; use moon_ui::{ - MoonAccent, MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonCheckboxSize, - MoonDropdown, MoonMenuSize, MoonNotification, MoonPalette, MoonPopover, MoonPopoverPlacement, - MoonSegmentItem, MoonSegmentedControl, MoonSlider, MoonWindowExt as _, h_flex, v_flex, + MoonAccent, MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonDropdown, + MoonMenuSize, MoonNotification, MoonPalette, MoonPopover, MoonPopoverPlacement, + MoonSegmentItem, MoonSegmentedControl, MoonSize, MoonSlider, MoonWindowExt as _, h_flex, + v_flex, }; use rust_i18n::t; @@ -421,7 +422,7 @@ fn content( MoonCheckbox::new("det-view-add-to-chart") .label(t!("detects.cfg.show_add_to_chart").to_string()) .checked(cfg.show_add_to_chart) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |checked: &bool, _w, app| { let checked = *checked; entity_atc.update(app, |this, cx| { diff --git a/crates/moon-ui-gpui/src/panels/label_edit/body.rs b/crates/moon-ui-gpui/src/panels/label_edit/body.rs index 5374609e..3d8e5938 100644 --- a/crates/moon-ui-gpui/src/panels/label_edit/body.rs +++ b/crates/moon-ui-gpui/src/panels/label_edit/body.rs @@ -14,8 +14,8 @@ use moon_core::config::{ }; use moon_core::util::fmt::DeltaSign; use moon_ui::{ - MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonCheckboxSize, MoonDropdown, - MoonInput, MoonMenuSize, MoonPalette, MoonWindowExt as _, h_flex, v_flex, + MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonDropdown, MoonInput, + MoonMenuSize, MoonPalette, MoonSize, MoonWindowExt as _, h_flex, v_flex, }; use rust_i18n::t; @@ -90,7 +90,7 @@ pub(super) fn dialog_body(state: &Entity, cx: &mut App) -> AnyEl MoonCheckbox::new("le-plate") .label(t!("chart_labels.plate").to_string()) .checked(on) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |v: &bool, _w, cx| { let v = *v; write_row(&state, cx, |s| s.row.plate = v); @@ -103,7 +103,7 @@ pub(super) fn dialog_body(state: &Entity, cx: &mut App) -> AnyEl .label(t!("chart_labels.show_name").to_string()) .checked(on && named) .disabled(!named) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |v: &bool, _w, cx| { let v = *v; write_row(&state, cx, |s| s.row.show_name = v); @@ -591,7 +591,7 @@ fn caption_settings( MoonCheckbox::new("le-bar") .label(t!("chart_labels.menu.bars").to_string()) .checked(on) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |v: &bool, _w, cx| { let v = *v; write_row(&state, cx, |s| s.row.parts[selected].bar = v); @@ -691,7 +691,7 @@ fn caption_settings( MoonCheckbox::new("le-value-only") .label(t!("chart_labels.value_only").to_string()) .checked(on) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |v: &bool, _w, cx| { let v = *v; write_row(&state, cx, |s| { @@ -748,7 +748,7 @@ fn caption_settings( MoonCheckbox::new("le-caption") .label(label.to_string()) .checked(on) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |v: &bool, _w, cx| { let v = *v; write_row(&state, cx, |s| { diff --git a/crates/moon-ui-gpui/src/panels/log/mod.rs b/crates/moon-ui-gpui/src/panels/log/mod.rs index ae8946a1..f7d964af 100644 --- a/crates/moon-ui-gpui/src/panels/log/mod.rs +++ b/crates/moon-ui-gpui/src/panels/log/mod.rs @@ -31,10 +31,10 @@ mod view; use crate::panels::line_list::{self, RowSelection}; use gpui::*; use moon_ui::{ - DockArea, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonCheckboxSize, MoonDropdown, - MoonInput, MoonInputEvent, MoonInputState, MoonMenuItem, MoonMenuSize, MoonPalette, - MoonScrollbarVisibility, MoonVirtualList, MoonVirtualListScrollHandle, Panel, PanelEvent, - PanelState, StyledExt, h_flex, v_flex, + DockArea, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonDropdown, MoonInput, + MoonInputEvent, MoonInputState, MoonMenuItem, MoonMenuSize, MoonPalette, + MoonScrollbarVisibility, MoonSize, MoonVirtualList, MoonVirtualListScrollHandle, Panel, + PanelEvent, PanelState, StyledExt, h_flex, v_flex, }; use rust_i18n::t; diff --git a/crates/moon-ui-gpui/src/panels/log/view.rs b/crates/moon-ui-gpui/src/panels/log/view.rs index cfe26347..d324f56c 100644 --- a/crates/moon-ui-gpui/src/panels/log/view.rs +++ b/crates/moon-ui-gpui/src/panels/log/view.rs @@ -74,7 +74,7 @@ impl Render for LogPanel { MoonCheckbox::new("log-errors-only") .label(t!("log.errors_only").to_string()) .checked(self.errors_only) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(cx.listener(|t, ch: &bool, _, cx| { if t.errors_only != *ch { t.errors_only = *ch; @@ -88,7 +88,7 @@ impl Render for LogPanel { MoonCheckbox::new("log-live") .label(t!("log.follow_tail").to_string()) .checked(self.following()) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(cx.listener(|t, ch: &bool, _, cx| { // A manual toggle invalidates any delayed automatic resumption. t.scroll_gen = t.scroll_gen.wrapping_add(1); diff --git a/crates/moon-ui-gpui/src/panels/mod.rs b/crates/moon-ui-gpui/src/panels/mod.rs index 545dfabb..77152da7 100644 --- a/crates/moon-ui-gpui/src/panels/mod.rs +++ b/crates/moon-ui-gpui/src/panels/mod.rs @@ -49,11 +49,12 @@ pub(crate) mod tab_menu; pub(crate) use arb_edit::open_arb_edit; pub(crate) use common::{ COMPACT_CHECKBOX_DISABLED_ALPHA, COMPACT_CHECKBOX_FONT, COMPACT_CHECKBOX_GAP, - COMPACT_CHECKBOX_MARK, FooterWeight, POPUP_GROUP_CAPTION_FONT, POPUP_GROUP_GAP, - POPUP_GROUP_INSET, RadioMark, RenderGate, data_table_host, detach_button, footer_caption, - footer_row, footer_text_style, footer_value, micro_button, micro_icon_button, num, panel_band, - pinned_scope_host, popup_apply_all_button, popup_close_button, popup_frame, popup_gear_trigger, - popup_group, popup_group_inset_px, popup_title, radio_items, side_label, toggle_variant, + COMPACT_CHECKBOX_MARK, COMPACT_CHECKBOX_WEIGHT, FooterWeight, POPUP_GROUP_CAPTION_FONT, + POPUP_GROUP_GAP, POPUP_GROUP_INSET, RadioMark, RenderGate, data_table_host, detach_button, + footer_caption, footer_row, footer_text_style, footer_value, micro_button, micro_icon_button, + num, panel_band, pinned_scope_host, popup_apply_all_button, popup_close_button, popup_frame, + popup_gear_trigger, popup_group, popup_group_inset_px, popup_title, radio_items, side_label, + toggle_variant, }; pub(crate) use label_edit::open_label_edit; pub(crate) use order_edit::open_order_edit; diff --git a/crates/moon-ui-gpui/src/panels/news/mod.rs b/crates/moon-ui-gpui/src/panels/news/mod.rs index 36e8db0a..dc5079c3 100644 --- a/crates/moon-ui-gpui/src/panels/news/mod.rs +++ b/crates/moon-ui-gpui/src/panels/news/mod.rs @@ -31,10 +31,10 @@ use std::rc::Rc; use gpui::prelude::FluentBuilder; use gpui::*; use moon_ui::{ - DockArea, MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonCheckboxSize, + DockArea, MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonContextMenuWindowExt as _, MoonDropdown, MoonInput, MoonInputEvent, MoonInputState, MoonMenuItem, MoonMenuSize, MoonNotification, MoonPalette, MoonPopover, MoonPopoverPlacement, - MoonTooltipView, MoonWindowExt as _, Panel, PanelEvent, PanelState, h_flex, v_flex, + MoonSize, MoonTooltipView, MoonWindowExt as _, Panel, PanelEvent, PanelState, h_flex, v_flex, }; use rust_i18n::t; @@ -759,7 +759,7 @@ impl NewsView { }), )); // "No tags" visibility toggle — untagged news carry nothing to colour, so it has no swatches. - let untagged = self.untagged_row(!settings.hide_untagged(), p, cx); + let untagged = self.untagged_row(!settings.hide_untagged(), cx); let tag_rows: Vec = rows .into_iter() .map(|(key, label)| { @@ -798,27 +798,18 @@ impl NewsView { /// The "no tags" row: a visibility checkbox for news that carry no tags at all (no colour picker). /// `shown` is the checkbox state (checked = show tagless news). - fn untagged_row(&self, shown: bool, p: MoonPalette, cx: &mut Context) -> AnyElement { + fn untagged_row(&self, shown: bool, cx: &mut Context) -> AnyElement { let checkbox = MoonCheckbox::new("news-untagged-vis") + .label(t!("news.tags.untagged").to_string()) .checked(shown) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(cx.listener(|this, checked: &bool, _w, cx| { this.set_hide_untagged(!*checked, cx); })); - h_flex() + div() .w_full() - .items_center() - .gap(design::ui_px(cx, 8.0)) .py(design::ui_px(cx, 2.0)) .child(checkbox) - .child( - div() - .flex_1() - .min_w(px(0.0)) - .text_size(design::t_body(cx)) - .text_color(rgb(p.text_muted)) - .child(t!("news.tags.untagged").to_string()), - ) .into_any_element() } @@ -835,9 +826,12 @@ impl NewsView { cx: &mut Context, ) -> AnyElement { let cb_key = key.clone(); + // User-defined tag identifiers are values rather than prose, so the label is mono. let checkbox = MoonCheckbox::new(SharedString::from(format!("news-tagvis-{key}"))) + .label(format!("#{label}")) + .mono(true) .checked(!hidden) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(cx.listener(move |this, checked: &bool, _w, cx| { this.toggle_tag_hidden(&cb_key, !*checked, cx); })); @@ -902,7 +896,7 @@ impl NewsView { let fixed_toggle = MoonCheckbox::new(SharedString::from(format!("nt-fixed-{key}"))) .label(t!("chart_labels.color_fixed").to_string()) .checked(fixed.is_some()) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(cx.listener(move |this, checked: &bool, _, cx| { let color = checked.then(|| format!("#{seed:06X}")); this.set_tag_color(&fixed_key, color.as_deref(), cx); @@ -925,23 +919,7 @@ impl NewsView { .w_full() .gap(design::ui_px(cx, 4.0)) .py(design::ui_px(cx, 2.0)) - .child( - h_flex() - .w_full() - .items_center() - .gap(design::ui_px(cx, 8.0)) - .child(checkbox) - .child( - // User-defined tag identifiers are values rather than prose. - div() - .flex_1() - .min_w(px(0.0)) - .font_family(design::mono()) - .text_size(design::t_body(cx)) - .text_color(rgb(p.text)) - .child(format!("#{label}")), - ), - ) + .child(checkbox) .child( h_flex() .items_center() @@ -1264,7 +1242,7 @@ impl Render for NewsView { MoonCheckbox::new("news-translate") .label(t!("news.translate").to_string()) .checked(self.translate) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(cx.listener(|this, ch: &bool, _w, cx| this.set_translate(*ch, cx))), ) .child( diff --git a/crates/moon-ui-gpui/src/panels/order_edit/body.rs b/crates/moon-ui-gpui/src/panels/order_edit/body.rs index 47c423fe..7c4d03b2 100644 --- a/crates/moon-ui-gpui/src/panels/order_edit/body.rs +++ b/crates/moon-ui-gpui/src/panels/order_edit/body.rs @@ -159,14 +159,16 @@ pub(super) fn dialog_body(state: &Entity, cx: &mut App) -> AnyEl apply: fn(&mut OrderEditState, bool)| -> AnyElement { let st = state.clone(); + // A floor, not a fixed width: it lines the rows' columns up, but a localized label can be + // longer than the column and must never be clipped by it. div() - .w(px(w)) + .min_w(px(w)) .flex_none() .child( MoonCheckbox::new(SharedString::from(id)) .label(label) .checked(checked) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |ch: &bool, _w, app| { let on = *ch; st.update(app, |s, cx| { diff --git a/crates/moon-ui-gpui/src/panels/order_edit/mod.rs b/crates/moon-ui-gpui/src/panels/order_edit/mod.rs index bf0b4208..25bd9026 100644 --- a/crates/moon-ui-gpui/src/panels/order_edit/mod.rs +++ b/crates/moon-ui-gpui/src/panels/order_edit/mod.rs @@ -9,8 +9,8 @@ use gpui::*; use moon_core::feed::{OrderRow, OrderStopsForm, StopGroupEdit, TakeProfitEdit, VStopEdit}; use moon_core::session::CoreId; use moon_ui::{ - MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonCheckboxSize, MoonInput, - MoonInputState, MoonNotification, MoonPalette, MoonTone, MoonWindowExt as _, h_flex, v_flex, + MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonInput, MoonInputState, + MoonNotification, MoonPalette, MoonSize, MoonTone, MoonWindowExt as _, h_flex, v_flex, }; use rust_i18n::t; diff --git a/crates/moon-ui-gpui/src/panels/report/columns.rs b/crates/moon-ui-gpui/src/panels/report/columns.rs index 3be51e55..1c52a295 100644 --- a/crates/moon-ui-gpui/src/panels/report/columns.rs +++ b/crates/moon-ui-gpui/src/panels/report/columns.rs @@ -589,7 +589,7 @@ fn deleted_cell(ri: usize, val: &Value) -> MoonDataCell { let checked = as_i64(val).unwrap_or(0) != 0; let cb = MoonCheckbox::new(SharedString::from(format!("rep-del-{ri}"))) .checked(checked) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .disabled(true); MoonDataCell::element( div() diff --git a/crates/moon-ui-gpui/src/panels/report/mod.rs b/crates/moon-ui-gpui/src/panels/report/mod.rs index ace011af..e512598c 100644 --- a/crates/moon-ui-gpui/src/panels/report/mod.rs +++ b/crates/moon-ui-gpui/src/panels/report/mod.rs @@ -54,12 +54,12 @@ use gpui::*; use moon_ui::MoonWindowExt as _; use moon_ui::{ DockArea, MoonButton, MoonButtonIconSlot, MoonButtonSize, MoonButtonVariant, MoonCheckbox, - MoonCheckboxSize, MoonCombobox, MoonComboboxEvent, MoonComboboxMenuChrome, MoonComboboxState, - MoonDataCell, MoonDataRow, MoonDataTable, MoonDataTableColumn, MoonDataTableState, - MoonDataTableWidthPolicy, MoonDateTimePicker, MoonDateTimePickerEvent, MoonDateTimePickerState, - MoonDropdown, MoonInput, MoonInputEvent, MoonInputState, MoonMenuItem, MoonMenuSize, - MoonNotification, MoonPalette, MoonScrollbarVisibility, MoonTone, MoonWindowFrame, Panel, - PanelEvent, PanelState, Root, StyledExt, h_flex, rgba_from, v_flex, + MoonCombobox, MoonComboboxEvent, MoonComboboxMenuChrome, MoonComboboxState, MoonDataCell, + MoonDataRow, MoonDataTable, MoonDataTableColumn, MoonDataTableState, MoonDataTableWidthPolicy, + MoonDateTimePicker, MoonDateTimePickerEvent, MoonDateTimePickerState, MoonDropdown, MoonInput, + MoonInputEvent, MoonInputState, MoonMenuItem, MoonMenuSize, MoonNotification, MoonPalette, + MoonScrollbarVisibility, MoonSize, MoonTone, MoonWindowFrame, Panel, PanelEvent, PanelState, + Root, StyledExt, h_flex, rgba_from, v_flex, }; use rusqlite::types::Value; use rust_i18n::t; diff --git a/crates/moon-ui-gpui/src/settings/badges.rs b/crates/moon-ui-gpui/src/settings/badges.rs index e03e6d6e..3f93cb17 100644 --- a/crates/moon-ui-gpui/src/settings/badges.rs +++ b/crates/moon-ui-gpui/src/settings/badges.rs @@ -9,8 +9,8 @@ use gpui::prelude::FluentBuilder; use gpui::*; use moon_ui::{ - MoonBadge, MoonBadgeSize, MoonBadgeVariant, MoonButton, MoonButtonSize, MoonCheckboxSize, - MoonColorPicker, MoonColorPickerState, MoonInput, MoonInputEvent, MoonInputState, MoonPalette, + MoonBadge, MoonBadgeSize, MoonBadgeVariant, MoonButton, MoonButtonSize, MoonColorPicker, + MoonColorPickerState, MoonInput, MoonInputEvent, MoonInputState, MoonPalette, MoonSize, MoonTooltipView, StyledExt, h_flex, rgba_from, v_flex, }; use rust_i18n::t; @@ -290,7 +290,7 @@ impl SettingsView { }, ) .label(t!("badges.col_active").to_string()) - .size(MoonCheckboxSize::Compact); + .size(MoonSize::Sm); let distinguish_chk = self .draft_checkbox( @@ -308,7 +308,7 @@ impl SettingsView { }, ) .label(t!("badges.distinguish").to_string()) - .size(MoonCheckboxSize::Compact); + .size(MoonSize::Sm); let outline_chk = self .draft_checkbox( @@ -326,7 +326,7 @@ impl SettingsView { }, ) .label(t!("badges.use_outline").to_string()) - .size(MoonCheckboxSize::Compact); + .size(MoonSize::Sm); // Keep everything on one row. Color pickers use `flex_none` at their natural 128px width // so they do not overlap the next badge. Outline colors appear to the right as L for long diff --git a/crates/moon-ui-gpui/src/settings/connections/tab.rs b/crates/moon-ui-gpui/src/settings/connections/tab.rs index 2591cc1e..8c5b0407 100644 --- a/crates/moon-ui-gpui/src/settings/connections/tab.rs +++ b/crates/moon-ui-gpui/src/settings/connections/tab.rs @@ -9,10 +9,9 @@ use std::sync::Arc; use gpui::*; use moon_ui::{ - MoonButton, MoonButtonIconSlot, MoonButtonSize, MoonButtonVariant, MoonCheckbox, - MoonCheckboxSize, MoonDropdown, MoonMenuSize, MoonPalette, MoonPopover, MoonPopoverPlacement, - MoonScrollbarVisibility, MoonSelect, MoonTooltipView, MoonVirtualList, StyledExt, h_flex, - v_flex, + MoonButton, MoonButtonIconSlot, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonDropdown, + MoonMenuSize, MoonPalette, MoonPopover, MoonPopoverPlacement, MoonScrollbarVisibility, + MoonSelect, MoonSize, MoonTooltipView, MoonVirtualList, StyledExt, h_flex, v_flex, }; use rust_i18n::t; @@ -330,7 +329,7 @@ fn group_header_row( .child( MoonCheckbox::new(SharedString::from(format!("grp-{name}"))) .checked(active) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change({ let weak = weak.clone(); move |ch: &bool, _window, cx| { diff --git a/crates/moon-ui-gpui/src/settings/connections/table.rs b/crates/moon-ui-gpui/src/settings/connections/table.rs index b17bb7b0..0d7b233b 100644 --- a/crates/moon-ui-gpui/src/settings/connections/table.rs +++ b/crates/moon-ui-gpui/src/settings/connections/table.rs @@ -14,8 +14,8 @@ use gpui::prelude::FluentBuilder; use gpui::*; use moon_ui::{ - MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonCheckboxSize, MoonColorPicker, - MoonDropdown, MoonInput, MoonInputState, MoonMenuItem, MoonMenuSize, MoonPalette, MoonText, + MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonColorPicker, MoonDropdown, + MoonInput, MoonInputState, MoonMenuItem, MoonMenuSize, MoonPalette, MoonSize, MoonText, MoonTone, MoonTooltipView, StyledExt, h_flex, }; use rust_i18n::t; @@ -268,7 +268,7 @@ fn srv_check( } false }) - .size(MoonCheckboxSize::Compact); + .size(MoonSize::Sm); if !label.is_empty() { checkbox = checkbox.label(label); } diff --git a/crates/moon-ui-gpui/src/settings/general.rs b/crates/moon-ui-gpui/src/settings/general.rs index ba8d7130..81760996 100644 --- a/crates/moon-ui-gpui/src/settings/general.rs +++ b/crates/moon-ui-gpui/src/settings/general.rs @@ -5,8 +5,8 @@ use gpui::*; use moon_ui::{ - MoonButton, MoonButtonSize, MoonCheckboxSize, MoonInput, MoonInputEvent, MoonInputState, - MoonMenuSize, MoonPalette, MoonSelect, MoonSlider, MoonSliderEvent, MoonSliderState, + MoonButton, MoonButtonSize, MoonCheckbox, MoonInput, MoonInputEvent, MoonInputState, + MoonMenuSize, MoonPalette, MoonSelect, MoonSize, MoonSlider, MoonSliderEvent, MoonSliderState, MoonTooltipView, StyledExt, h_flex, rgba_from, v_flex, }; use rust_i18n::t; @@ -65,29 +65,69 @@ fn labeled_select( /// Returns: /// The hint row, with a tooltip only when the visible text was shortened. fn settings_hint(key: &'static str, text: &str, muted: Hsla) -> AnyElement { - let sentence_end = [". ", "! ", "? "] - .into_iter() - .filter_map(|boundary| text.find(boundary).map(|index| index + 1)) - .min(); - let Some(sentence_end) = sentence_end else { - return div() - .text_color(muted) - .child(text.to_string()) - .into_any_element(); + let (shown, full) = hint_parts(text); + let Some(full) = full else { + return div().text_color(muted).child(shown).into_any_element(); }; - let full = text.to_string(); div() .id(key) .text_color(muted) - .child(format!("{} …", &text[..sentence_end])) - .tooltip(move |_window, cx| { - cx.new(|_| MoonTooltipView::new(full.clone()).max_width(420.0)) - .into() - }) + .child(shown) + .tooltip(hint_tooltip(full)) + .into_any_element() +} + +/// Attach a settings hint to its checkbox as the checkbox's description. +/// +/// The hint is shortened exactly as [`settings_hint`] shortens it. A shortened hint's full text +/// moves to the same wide tooltip, hosted on the whole control because the description is part of +/// the checkbox rather than an element of its own. +/// +/// Args: +/// checkbox: The labelled checkbox the hint explains. +/// key: Stable localization key used as the tooltip host ID. +/// text: Complete localized hint text. +/// +/// Returns: +/// The checkbox, wrapped in a tooltip host only when the visible text was shortened. +fn checkbox_with_hint(checkbox: MoonCheckbox, key: &'static str, text: &str) -> AnyElement { + let (shown, full) = hint_parts(text); + let checkbox = checkbox.description(shown); + let Some(full) = full else { + return checkbox.into_any_element(); + }; + + div() + .id(key) + .child(checkbox) + .tooltip(hint_tooltip(full)) .into_any_element() } +/// Split a hint into its visible text and, when that is shortened, the complete text. +/// +/// Multi-sentence text is cut after its first sentence, keeping the sentence-ending punctuation and +/// adding an ellipsis. Text without a sentence boundary is returned unchanged with no full text. +fn hint_parts(text: &str) -> (String, Option) { + let sentence_end = [". ", "! ", "? "] + .into_iter() + .filter_map(|boundary| text.find(boundary).map(|index| index + 1)) + .min(); + match sentence_end { + Some(end) => (format!("{} …", &text[..end]), Some(text.to_string())), + None => (text.to_string(), None), + } +} + +/// Build the standard wide settings tooltip showing a hint's complete text. +fn hint_tooltip(full: String) -> impl Fn(&mut Window, &mut App) -> AnyView + 'static { + move |_window, cx| { + cx.new(|_| MoonTooltipView::new(full.clone()).max_width(420.0)) + .into() + } +} + impl SettingsView { /// Adjust the draft log-retention period, clamped to `0..=365` days. fn adjust_ret(&mut self, delta: i32, cx: &mut Context) { @@ -316,7 +356,7 @@ impl SettingsView { )) .child(super::separator(p, cx)) // Place each core in a separate chart tab. - .child( + .child(checkbox_with_hint( self.draft_checkbox(cx, "split", split, |p, v| { if p.charts_split_by_core != v { p.charts_split_by_core = v; @@ -326,16 +366,13 @@ impl SettingsView { } }) .label(t!("general.charts_split_by_core").to_string()) - .size(MoonCheckboxSize::Normal), - ) - .child(settings_hint( + .size(MoonSize::Sm), "general.charts_split_by_core_hint", &t!("general.charts_split_by_core_hint"), - muted, )) .child(super::separator(p, cx)) // Restrict order and line controls to the order-book control zone. - .child( + .child(checkbox_with_hint( self.draft_checkbox(cx, "separate-zones", scz, |p, v| { if p.separate_control_zones != v { p.separate_control_zones = v; @@ -345,16 +382,14 @@ impl SettingsView { } }) .label(t!("general.separate_control_zones").to_string()) - .size(MoonCheckboxSize::Normal), - ) - .child(settings_hint( + .size(MoonSize::Sm), "general.separate_control_zones_hint", &t!("general.separate_control_zones_hint"), - muted, )) .child(super::separator(p, cx)) - // Close Main charts after window inactivity; zero disables the timeout. - .child( + // Close Main charts after window inactivity; zero disables the timeout. The hint defines + // "idle" for the checkbox, so it is the checkbox's description, above the stepper. + .child(checkbox_with_hint( self.draft_checkbox(cx, "idle-close", idle_secs > 0, move |p, v| { // Enabling restores the last remembered value; disabling stores zero. let want = if v { idle_restore } else { 0 }; @@ -372,8 +407,10 @@ impl SettingsView { } }) .label(t!("general.main_idle_close").to_string()) - .size(MoonCheckboxSize::Normal), - ) + .size(MoonSize::Sm), + "general.main_idle_close_hint", + &t!("general.main_idle_close_hint"), + )) .child( h_flex() .gap(design::ui_px(cx, 8.0)) @@ -397,15 +434,10 @@ impl SettingsView { Self::adjust_idle, )), ) - .child(settings_hint( - "general.main_idle_close_hint", - &t!("general.main_idle_close_hint"), - muted, - )) .child(super::separator(p, cx)) // Stack layout is now configured per tab from the chart-tabs layout popup. // File logging and retention period. - .child( + .child(checkbox_with_hint( self.draft_checkbox(cx, "logf", logf, |p, v| { if p.log_to_file != v { p.log_to_file = v; @@ -415,12 +447,9 @@ impl SettingsView { } }) .label(t!("general.log_to_file").to_string()) - .size(MoonCheckboxSize::Normal), - ) - .child(settings_hint( + .size(MoonSize::Sm), "general.log_to_file_hint", &t!("general.log_to_file_hint"), - muted, )) // Retention controls are enabled only while file logging is enabled; otherwise the // buttons are disabled and the value and labels are muted. diff --git a/crates/moon-ui-gpui/src/settings/hotkeys/tab.rs b/crates/moon-ui-gpui/src/settings/hotkeys/tab.rs index 39639364..234f6890 100644 --- a/crates/moon-ui-gpui/src/settings/hotkeys/tab.rs +++ b/crates/moon-ui-gpui/src/settings/hotkeys/tab.rs @@ -21,8 +21,8 @@ use moon_core::config::{ use moon_core::feed::CoreConfigState; use moon_core::session::CoreId; use moon_ui::{ - MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonCheckboxSize, MoonDropdown, - MoonHotkeyInput, MoonKbd, MoonKbdSize, MoonMenuItem, MoonMenuSize, MoonPalette, MoonTabItem, + MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonDropdown, MoonHotkeyInput, + MoonKbd, MoonKbdSize, MoonMenuItem, MoonMenuSize, MoonPalette, MoonSize, MoonTabItem, MoonTabStrip, MoonText, MoonTooltip, MoonTooltipView, h_flex, rgba_from, v_flex, }; use rust_i18n::t; @@ -850,7 +850,7 @@ impl SettingsView { let backend = self.backend.clone(); let checkbox = MoonCheckbox::new("same-hotkeys-for-move") .checked(hotkeys.same_hotkeys_for_move) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |value, _window, cx| { backend.update(cx, |b, bcx| { if let Some(p) = b.preview.as_mut() { diff --git a/crates/moon-ui-gpui/src/settings/import_preview.rs b/crates/moon-ui-gpui/src/settings/import_preview.rs index c5d39145..6a23e9ff 100644 --- a/crates/moon-ui-gpui/src/settings/import_preview.rs +++ b/crates/moon-ui-gpui/src/settings/import_preview.rs @@ -9,8 +9,8 @@ use std::collections::HashSet; use gpui::*; use moon_ui::{ - MoonButton, MoonCheckbox, MoonPalette, MoonScrollableElement, StyledExt, h_flex, rgba_from, - v_flex, + MoonButton, MoonCheckbox, MoonPalette, MoonScrollableElement, MoonSize, StyledExt, h_flex, + rgba_from, v_flex, }; use rust_i18n::t; @@ -344,6 +344,7 @@ impl SettingsView { // The All checkbox toggles every target at once. .child( MoonCheckbox::new("imp-core-all") + .size(MoonSize::Sm) .checked(all_on) .label(t!("import.all_cores").to_string()) .on_change(cx.listener(|this, ch: &bool, _, cx| { @@ -359,6 +360,7 @@ impl SettingsView { for (idx, (_, name, on)) in state.cores.iter().enumerate() { row = row.child( MoonCheckbox::new(SharedString::from(format!("imp-core-{idx}"))) + .size(MoonSize::Sm) .checked(*on) .label(name.clone()) .on_change(cx.listener(move |this, ch: &bool, _, cx| { @@ -497,6 +499,7 @@ impl SettingsView { .gap(design::ui_px(cx, 6.0)) .child( MoonCheckbox::new(SharedString::from(format!("imp-{}", item.id))) + .size(MoonSize::Sm) .checked(state_checked) .label(wording::caption(&item.label)) .on_change(cx.listener(move |this, ch: &bool, _, cx| { diff --git a/crates/moon-ui-gpui/src/settings/lines.rs b/crates/moon-ui-gpui/src/settings/lines.rs index fdf6269a..0f02384e 100644 --- a/crates/moon-ui-gpui/src/settings/lines.rs +++ b/crates/moon-ui-gpui/src/settings/lines.rs @@ -5,8 +5,8 @@ use gpui::*; use moon_ui::{ - MoonCheckboxSize, MoonColorPicker, MoonColorPickerState, MoonPalette, MoonSliderState, - StyledExt, h_flex, v_flex, + MoonColorPicker, MoonColorPickerState, MoonPalette, MoonSize, MoonSliderState, StyledExt, + h_flex, v_flex, }; use super::{SettingsView, separator, slider_row}; @@ -283,7 +283,7 @@ impl SettingsView { } }) .label(label) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) } /// Wrap [`super::collapse_block`] for the Lines tab, storing expansion by `key`. diff --git a/crates/moon-ui-gpui/src/settings/security.rs b/crates/moon-ui-gpui/src/settings/security.rs index 5bb0406f..06e80d5d 100644 --- a/crates/moon-ui-gpui/src/settings/security.rs +++ b/crates/moon-ui-gpui/src/settings/security.rs @@ -21,8 +21,8 @@ mod vault; use gpui::prelude::FluentBuilder; use gpui::*; use moon_ui::{ - MoonButton, MoonButtonSize, MoonCheckbox, MoonCheckboxSize, MoonInput, MoonInputEvent, - MoonInputState, MoonPalette, MoonProgress, h_flex, rgba_from, v_flex, + MoonButton, MoonButtonSize, MoonCheckbox, MoonInput, MoonInputEvent, MoonInputState, + MoonPalette, MoonProgress, MoonSize, h_flex, rgba_from, v_flex, }; use rust_i18n::t; @@ -298,7 +298,7 @@ impl SettingsView { ) -> MoonCheckbox { MoonCheckbox::new(id) .checked(checked) - .size(MoonCheckboxSize::Normal) + .size(MoonSize::Sm) // Nothing to attach a password to until the config file is open. .disabled(!self.security.vault.editable) .on_change(cx.listener(move |this, checked: &bool, _window, cx| { @@ -309,19 +309,14 @@ impl SettingsView { /// Build the launch-password group: checkbox, both fields, and the mismatch line. fn launch_group(&self, cx: &Context) -> impl IntoElement { - let p = MoonPalette::active(cx); let on = self.security.launch_on; let (value, confirm) = self.security.launch.read(cx); v_flex() .gap(design::ui_px(cx, 4.0)) .child( self.security_checkbox(cx, "sec-launch", on, |ed, v| ed.launch_on = v) - .label(t!("security.launch").to_string()), - ) - .child( - div() - .text_color(rgba_from(p.text_muted, 1.0)) - .child(t!("security.launch_hint").to_string()), + .label(t!("security.launch").to_string()) + .description(t!("security.launch_hint").to_string()), ) .when(on, |this| { this.child(password_row( @@ -353,12 +348,8 @@ impl SettingsView { .gap(design::ui_px(cx, 4.0)) .child( self.security_checkbox(cx, "sec-file", on, |ed, v| ed.file_on = v) - .label(t!("security.file").to_string()), - ) - .child( - div() - .text_color(rgba_from(p.text_muted, 1.0)) - .child(t!("security.file_hint").to_string()), + .label(t!("security.file").to_string()) + .description(t!("security.file_hint").to_string()), ) .when(on, |this| { this.child(password_row( diff --git a/crates/moon-ui-gpui/src/settings/storage.rs b/crates/moon-ui-gpui/src/settings/storage.rs index 33adf601..e1ea2047 100644 --- a/crates/moon-ui-gpui/src/settings/storage.rs +++ b/crates/moon-ui-gpui/src/settings/storage.rs @@ -7,7 +7,7 @@ //! on the UI thread would freeze the interface. use gpui::*; -use moon_ui::{MoonButton, MoonCheckboxSize, MoonPalette, StyledExt, h_flex, rgba_from, v_flex}; +use moon_ui::{MoonButton, MoonPalette, MoonSize, StyledExt, h_flex, rgba_from, v_flex}; use rust_i18n::t; use super::{SettingsView, StatusMsg, open_folder, section, separator}; @@ -280,7 +280,8 @@ impl SettingsView { moon_ui::MoonCheckbox::new("strat-db-enabled") .checked(enabled) .label(t!("storage.strategies_enabled").to_string()) - .size(MoonCheckboxSize::Normal) + .description(t!("storage.strategies_enabled_hint").to_string()) + .size(MoonSize::Sm) .on_change(cx.listener(|this, v: &bool, _, cx| { let v = *v; if this.storage.cfg.strategies.enabled != v { @@ -291,7 +292,6 @@ impl SettingsView { } })), ) - .child(hint(t!("storage.strategies_enabled_hint").to_string())) // MIXED NODE: same as the reports readout above — stays mono. .child( hint(format!( diff --git a/crates/moon-ui-gpui/src/settings/telegram.rs b/crates/moon-ui-gpui/src/settings/telegram.rs index 54ddd60f..82fb7329 100644 --- a/crates/moon-ui-gpui/src/settings/telegram.rs +++ b/crates/moon-ui-gpui/src/settings/telegram.rs @@ -6,8 +6,8 @@ use gpui::prelude::FluentBuilder; use gpui::*; use moon_ui::{ - MoonAccent, MoonButton, MoonCheckboxSize, MoonGroupBox, MoonInput, MoonInputEvent, - MoonInputState, MoonPalette, MoonSegmentItem, MoonSegmentedControl, h_flex, rgba_from, v_flex, + MoonAccent, MoonButton, MoonGroupBox, MoonInput, MoonInputEvent, MoonInputState, MoonPalette, + MoonSegmentItem, MoonSegmentedControl, MoonSize, h_flex, rgba_from, v_flex, }; use rust_i18n::t; @@ -402,12 +402,8 @@ impl SettingsView { } }) .label(t!("telegram.mini_app").to_string()) - .size(MoonCheckboxSize::Normal), - ) - .child( - div() - .text_color(muted) - .child(t!("telegram.mini_app_hint").to_string()), + .description(t!("telegram.mini_app_hint").to_string()) + .size(MoonSize::Sm), ) .child(div().text_color(rgba_from(p.text, 1.0)).child(mini_status)) .when_some(mini_url, |tab, url| { diff --git a/crates/moon-ui-gpui/src/settings/telegram/access.rs b/crates/moon-ui-gpui/src/settings/telegram/access.rs index 25ef50e4..16afd034 100644 --- a/crates/moon-ui-gpui/src/settings/telegram/access.rs +++ b/crates/moon-ui-gpui/src/settings/telegram/access.rs @@ -3,7 +3,7 @@ use gpui::prelude::FluentBuilder; use gpui::*; use moon_core::config::telegram_access::TelegramReportAccess; use moon_ui::{ - MoonButton, MoonCheckboxSize, MoonGroupBox, MoonInput, MoonPalette, h_flex, rgba_from, v_flex, + MoonButton, MoonGroupBox, MoonInput, MoonPalette, MoonSize, h_flex, rgba_from, v_flex, }; use rust_i18n::t; @@ -388,7 +388,7 @@ impl SettingsView { }, ) .label(label) - .size(MoonCheckboxSize::Normal), + .size(MoonSize::Sm), ); } content.when(count == 0, |content| { diff --git a/crates/moon-ui-gpui/src/settings/telegram/core_section.rs b/crates/moon-ui-gpui/src/settings/telegram/core_section.rs index 56a31fd8..f45c7396 100644 --- a/crates/moon-ui-gpui/src/settings/telegram/core_section.rs +++ b/crates/moon-ui-gpui/src/settings/telegram/core_section.rs @@ -9,8 +9,8 @@ use gpui::prelude::FluentBuilder; use gpui::*; use moon_ui::{ MoonButton, MoonButtonIconSlot, MoonButtonSize, MoonButtonVariant, MoonCheckbox, - MoonCheckboxSize, MoonDisclosureDirection, MoonDropdown, MoonGroupBox, MoonInput, - MoonInputState, MoonMenuItem, MoonMenuSize, MoonPalette, h_flex, rgba_from, v_flex, + MoonDisclosureDirection, MoonDropdown, MoonGroupBox, MoonInput, MoonInputState, MoonMenuItem, + MoonMenuSize, MoonPalette, MoonSize, h_flex, rgba_from, v_flex, }; use rust_i18n::t; @@ -293,7 +293,7 @@ impl SettingsView { .checked(enabled) .disabled(!live) .mono(false) - .size(MoonCheckboxSize::Normal) + .size(MoonSize::Sm) .on_change(cx.listener(move |this, ch: &bool, _, cx| { let v = *ch; if let Some(core) = this.telegram.core.picked { diff --git a/crates/moon-ui-gpui/src/settings/telegram/core_section/login_steps.rs b/crates/moon-ui-gpui/src/settings/telegram/core_section/login_steps.rs index b4c57074..1d9fb411 100644 --- a/crates/moon-ui-gpui/src/settings/telegram/core_section/login_steps.rs +++ b/crates/moon-ui-gpui/src/settings/telegram/core_section/login_steps.rs @@ -5,8 +5,8 @@ use gpui::*; use moon_ui::{ - MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonCheckboxSize, MoonInput, - MoonInputState, MoonPalette, MoonWindowExt as _, h_flex, rgba_from, v_flex, + MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonInput, MoonInputState, + MoonPalette, MoonSize, MoonWindowExt as _, h_flex, rgba_from, v_flex, }; use rust_i18n::t; @@ -471,7 +471,7 @@ impl SettingsView { .label(t!("telegram_core.terms_accept").to_string()) .checked(accepted) .mono(false) - .size(MoonCheckboxSize::Normal) + .size(MoonSize::Sm) .on_change(cx.listener(move |this, ch: &bool, _, cx| { this.telegram.core.terms_accepted = if *ch { Some((core, terms_for_click.clone())) diff --git a/crates/moon-ui-gpui/src/shell/core_settings_popup.rs b/crates/moon-ui-gpui/src/shell/core_settings_popup.rs index 2ba63c2d..944a3469 100644 --- a/crates/moon-ui-gpui/src/shell/core_settings_popup.rs +++ b/crates/moon-ui-gpui/src/shell/core_settings_popup.rs @@ -20,8 +20,8 @@ mod widgets; use gpui::prelude::FluentBuilder; use gpui::*; use moon_ui::{ - MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonCheckboxSize, MoonInputState, - MoonPalette, MoonSliderState, MoonTabItem, MoonTabStrip, h_flex, rgba_from, v_flex, + MoonButton, MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonInputState, MoonPalette, + MoonSize, MoonSliderState, MoonTabItem, MoonTabStrip, h_flex, rgba_from, v_flex, }; use rust_i18n::t; @@ -308,9 +308,7 @@ pub(crate) fn core_settings_content( /// Returns: /// The switch row. fn expert_switch(ctx: &TabCtx<'_>, view: &Entity, cx: &App) -> impl IntoElement { - let TabCtx { - backend, group, p, .. - } = *ctx; + let TabCtx { backend, group, .. } = *ctx; // Read rather than assumed: this popup is only drawn while the preference is off, but a // hardcoded tick is how the two faces would come to disagree if that ever stopped holding. let checked = backend.read(cx).core_settings_expert(); @@ -324,8 +322,9 @@ fn expert_switch(ctx: &TabCtx<'_>, view: &Entity, cx: &App) -> impl IntoE .child( MoonCheckbox::new("core-settings-expert") .label(t!("core_settings.expert").to_string()) + .description(t!("core_settings.expert_hint").to_string()) .checked(checked) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |value, window, app| { if !*value { return; @@ -342,11 +341,6 @@ fn expert_switch(ctx: &TabCtx<'_>, view: &Entity, cx: &App) -> impl IntoE ); }), ) - .child(widgets::caption( - t!("core_settings.expert_hint").to_string(), - p, - cx, - )) } /// Immediate actions above the tab strip: restart, emulator, cancel all orders. diff --git a/crates/moon-ui-gpui/src/shell/core_settings_popup/widgets.rs b/crates/moon-ui-gpui/src/shell/core_settings_popup/widgets.rs index 75892b4e..d93c770c 100644 --- a/crates/moon-ui-gpui/src/shell/core_settings_popup/widgets.rs +++ b/crates/moon-ui-gpui/src/shell/core_settings_popup/widgets.rs @@ -7,8 +7,8 @@ use gpui::prelude::FluentBuilder; use gpui::*; use moon_ui::{ - MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonCheckboxSize, MoonDropdown, MoonInput, - MoonMenuSize, MoonPalette, MoonSlider, h_flex, v_flex, + MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonDropdown, MoonInput, MoonMenuSize, + MoonPalette, MoonSize, MoonSlider, h_flex, v_flex, }; use rust_i18n::t; @@ -141,7 +141,7 @@ pub(super) fn cs_checkbox( MoonCheckbox::new(SharedString::from(id.to_string())) .label(label) .checked(checked) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |ch: &bool, _w, app| { let on = *ch; let b = backend.read(app); @@ -241,7 +241,7 @@ pub(super) fn flag( MoonCheckbox::new(SharedString::from(id)) .label(label) .checked(checked) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |ch: &bool, _w, app| { let on = *ch; view.update(app, |this, cx| { diff --git a/crates/moon-ui-gpui/src/shell/quiet_popup.rs b/crates/moon-ui-gpui/src/shell/quiet_popup.rs index b448db51..6e9718a7 100644 --- a/crates/moon-ui-gpui/src/shell/quiet_popup.rs +++ b/crates/moon-ui-gpui/src/shell/quiet_popup.rs @@ -10,7 +10,7 @@ //! The checkbox rows write straight through the backend, like the Core Status alert popup. use gpui::*; -use moon_ui::{MoonCheckbox, MoonCheckboxSize, MoonInput, MoonPalette, h_flex, v_flex}; +use moon_ui::{MoonCheckbox, MoonInput, MoonPalette, MoonSize, h_flex, v_flex}; use rust_i18n::t; use moon_core::config::quiet::QuietCfg; @@ -223,7 +223,7 @@ impl Shell { MoonCheckbox::new(SharedString::from(format!("header-{id}"))) .label(label) .checked(checked) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .mono(true) .on_change(move |value, _window, cx| { let value = *value; diff --git a/crates/moon-ui-gpui/src/shell/workspace/rail_settings.rs b/crates/moon-ui-gpui/src/shell/workspace/rail_settings.rs index b4bb80d2..edfccdda 100644 --- a/crates/moon-ui-gpui/src/shell/workspace/rail_settings.rs +++ b/crates/moon-ui-gpui/src/shell/workspace/rail_settings.rs @@ -8,7 +8,7 @@ use gpui::*; use moon_core::config::layout::WindowLayout; use moon_ui::{ - MoonCheckbox, MoonCheckboxSize, MoonPalette, MoonPopover, MoonPopoverPlacement, h_flex, v_flex, + MoonCheckbox, MoonPalette, MoonPopover, MoonPopoverPlacement, MoonSize, h_flex, v_flex, }; use rust_i18n::t; @@ -264,7 +264,7 @@ fn settings_content( ))) .label(t!(row.label).to_string()) .checked((row.read)(&prefs)) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |checked: &bool, _window, app| { let checked = *checked; backend.update(app, |backend, backend_cx| { diff --git a/crates/moon-ui-gpui/src/startup.rs b/crates/moon-ui-gpui/src/startup.rs index 5dcedcca..92d6a7ac 100644 --- a/crates/moon-ui-gpui/src/startup.rs +++ b/crates/moon-ui-gpui/src/startup.rs @@ -219,17 +219,14 @@ fn consume_report_commit(dirty: Option<&std::sync::atomic::AtomicBool>, on_commi } } +/// Fonts the terminal registers on top of MoonUI's own. +/// +/// Inter is not among them: `moon_ui::init` registers MoonUI's static Inter cuts (Regular, Medium, +/// SemiBold, Bold) under the `"Inter"` family the theme and `design::ui_font` name, and a second +/// `"Inter"` registered here would compete with them for every weight. Geist Mono stays, because +/// MoonUI ships only its Regular and Bold while the chart draws at 500 and 600. fn embedded_fonts() -> Vec> { vec![ - include_bytes!("../../../assets/fonts/Inter-400.ttf") - .as_slice() - .into(), - include_bytes!("../../../assets/fonts/Inter-500.ttf") - .as_slice() - .into(), - include_bytes!("../../../assets/fonts/Inter-600.ttf") - .as_slice() - .into(), include_bytes!("../../../assets/fonts/GeistMono-400.ttf") .as_slice() .into(), diff --git a/crates/moon-ui-gpui/src/strategies/mod.rs b/crates/moon-ui-gpui/src/strategies/mod.rs index 153cb1b6..52373df0 100644 --- a/crates/moon-ui-gpui/src/strategies/mod.rs +++ b/crates/moon-ui-gpui/src/strategies/mod.rs @@ -47,12 +47,12 @@ use gpui::prelude::FluentBuilder; use gpui::*; use moon_ui::{ MoonAlert, MoonBackgroundPolicy, MoonBadge, MoonBadgeSize, MoonBadgeVariant, MoonButton, - MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonCheckboxSize, MoonColorPicker, - MoonColorPickerEvent, MoonColorPickerState, MoonDropdown, MoonInput, MoonInputEvent, - MoonInputState, MoonMenuItem, MoonMenuSize, MoonPalette, MoonScrollbarVisibility, - MoonSegmentItem, MoonSegmentedControl, MoonTextArea, MoonTextAreaEvent, MoonTextAreaState, - MoonTone, MoonTreeEvent, MoonTreeItem, MoonTreeState, MoonVirtualList, - MoonVirtualListScrollHandle, MoonWindowExt as _, MoonWindowFrame, Root, h_flex, v_flex, + MoonButtonSize, MoonButtonVariant, MoonCheckbox, MoonColorPicker, MoonColorPickerEvent, + MoonColorPickerState, MoonDropdown, MoonInput, MoonInputEvent, MoonInputState, MoonMenuItem, + MoonMenuSize, MoonPalette, MoonScrollbarVisibility, MoonSegmentItem, MoonSegmentedControl, + MoonSize, MoonTextArea, MoonTextAreaEvent, MoonTextAreaState, MoonTone, MoonTreeEvent, + MoonTreeItem, MoonTreeState, MoonVirtualList, MoonVirtualListScrollHandle, MoonWindowExt as _, + MoonWindowFrame, Root, h_flex, v_flex, }; use crate::design::{moon, moon_alpha}; diff --git a/crates/moon-ui-gpui/src/strategies/params.rs b/crates/moon-ui-gpui/src/strategies/params.rs index e1581ed4..cdd8a5e3 100644 --- a/crates/moon-ui-gpui/src/strategies/params.rs +++ b/crates/moon-ui-gpui/src/strategies/params.rs @@ -1762,7 +1762,7 @@ impl StrategiesView { .checked(on) .indeterminate(differ) .disabled(!active) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(cx.listener(move |this, ch: &bool, _, cx| { this.stage_field_value( &keys, diff --git a/crates/moon-ui-gpui/src/strategies/settings.rs b/crates/moon-ui-gpui/src/strategies/settings.rs index c9078b40..05106e69 100644 --- a/crates/moon-ui-gpui/src/strategies/settings.rs +++ b/crates/moon-ui-gpui/src/strategies/settings.rs @@ -12,16 +12,17 @@ use moon_core::config::layout::{ STRATEGIES_TREE_TEXT_STEP_MIN, WindowLayout, clamp_strategies_tree_text_step, }; use moon_ui::{ - MoonCheckbox, MoonCheckboxSize, MoonGroupBox, MoonPalette, MoonPopover, MoonPopoverPlacement, + MoonCheckbox, MoonGroupBox, MoonPalette, MoonPopover, MoonPopoverPlacement, MoonSize, MoonStepper, MoonStepperSize, MoonTheme, h_flex, v_flex, }; use rust_i18n::t; use super::StrategiesView; -use crate::design::{self, moon}; +use crate::design; use crate::panels::{ - COMPACT_CHECKBOX_FONT, COMPACT_CHECKBOX_GAP, COMPACT_CHECKBOX_MARK, POPUP_GROUP_CAPTION_FONT, - popup_close_button, popup_gear_trigger, popup_group, popup_group_inset_px, popup_title, + COMPACT_CHECKBOX_FONT, COMPACT_CHECKBOX_GAP, COMPACT_CHECKBOX_MARK, COMPACT_CHECKBOX_WEIGHT, + POPUP_GROUP_CAPTION_FONT, popup_close_button, popup_gear_trigger, popup_group, + popup_group_inset_px, popup_title, }; #[cfg(test)] @@ -260,59 +261,31 @@ impl StrategiesView { self.write_pref(&PARAMS_FULL, value, cx); } - /// Build the filter-row active-only toggle: its label, then its compact checkbox. + /// Build the filter-row active-only toggle: a labelled `Sm` checkbox. /// - /// The label sits left of the mark because the row reads left to right into the settings gear - /// that follows it — which is also why this is not a labelled `MoonCheckbox`, the one thing that - /// component cannot place. Clicking either half writes the same preference, so the label is not - /// a dead zone beside a live checkbox, and the cluster carries one tooltip spelling the - /// preference out in full. + /// The caption is the checkbox's own MoonUI label, so a press on the box or the caption writes + /// the same preference, and the control carries one tooltip spelling the preference out in full. /// /// Args: - /// palette: Active MoonUI palette, resolved once by the caller. - /// cx: View context used to read the resolved preference and wire the callbacks. + /// cx: View context used to read the resolved preference and wire the callback. /// /// Returns: - /// The label and checkbox as one flex-none cluster. - pub(super) fn active_only_toggle( - &self, - palette: MoonPalette, - cx: &Context, - ) -> AnyElement { + /// The checkbox as one flex-none control. + pub(super) fn active_only_toggle(&self, cx: &Context) -> AnyElement { let checked = (ACTIVE_ONLY.read)(&self.prefs); let view = cx.entity(); - h_flex() + div() .id("strategies-active-only") .flex_none() - .items_center() - .gap(design::ui_px(cx, COMPACT_CHECKBOX_GAP)) .tooltip(crate::panels::common::text_tooltip( t!(ACTIVE_ONLY.label).to_string(), )) .child( - div() - .id("strategies-active-only-label") - .cursor_pointer() - .font_family(design::ui_font()) - .text_size(design::t_caption(cx)) - .text_color(moon(palette.text_soft)) - .child(t!("strat.active_only").to_string()) - // Reads the preference at click time rather than flipping the value this frame - // captured, so the label cannot write a stale flip. - .on_click({ - let view = view.clone(); - move |_, _window, app: &mut App| { - view.update(app, |this, cx| { - let next = !(ACTIVE_ONLY.read)(&this.prefs); - this.set_active_only(next, cx); - }); - } - }), - ) - .child( + // The caption is the checkbox's own label, so a press on either toggles it. MoonCheckbox::new("strategies-active-only-mark") + .label(t!("strat.active_only").to_string()) .checked(checked) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |value: &bool, _window, app| { let value = *value; view.update(app, |this, cx| this.set_active_only(value, cx)); @@ -411,18 +384,13 @@ fn settings_content_width(cx: &App) -> f32 { let group_width = design::ui_text_width(cx, &group, POPUP_GROUP_CAPTION_FONT, 600.0, true); let checkbox_label_width = POPUP_ROWS .iter() - .map(|row| popup_text_width(cx, &t!(row.label), COMPACT_CHECKBOX_FONT, 400.0)) + .map(|row| checkbox_face_width(cx, &t!(row.label), COMPACT_CHECKBOX_WEIGHT)) .fold(0.0_f32, f32::max); let checkbox_leading = f32::from(design::ui_px( cx, COMPACT_CHECKBOX_MARK + COMPACT_CHECKBOX_GAP, )); - let text_step_label_width = popup_text_width( - cx, - &t!("strat.settings.text_step"), - COMPACT_CHECKBOX_FONT, - 400.0, - ); + let text_step_label_width = checkbox_face_width(cx, &t!("strat.settings.text_step"), 400.0); // The stepper's two halves scale differently, so they are reserved differently: its buttons // reach `MoonButton::width`, which draws a RAW pixel width, while its value cell is // `ui()`-scaled. Reserving `ui(button*2 + value)` agreed with the rendered control only at @@ -463,6 +431,22 @@ fn popup_text_width(cx: &App, text: &str, base_size: f32, weight: f32) -> f32 { design::ui_text_width(cx, text, base_size, weight, false) } +/// Measure text set in the `Sm` checkbox label's face, in the popup's proportional family. +/// +/// That face follows the UI zoom but not the Font slider (see [`COMPACT_CHECKBOX_FONT`]), so it is +/// measured apart from [`popup_text_width`], which adds the slider's delta. +/// +/// Args: +/// cx: Application context providing active tokens and the text system. +/// text: Text to measure. +/// weight: Font weight represented as the GPUI numeric value. +/// +/// Returns: +/// The summed glyph-advance estimate in pixels. +fn checkbox_face_width(cx: &App, text: &str, weight: f32) -> f32 { + design::ui_text_width_zoomed(cx, text, COMPACT_CHECKBOX_FONT, weight, false) +} + /// Pure arithmetic core of [`settings_content_width`], free of `cx` and the GPUI text system. /// /// Split out so a later prover can assert on the `max`/`+` nesting directly: `title_w.max(group_ @@ -525,7 +509,7 @@ fn tree_text_step_row( .flex_1() .min_w_0() .truncate() - .text_size(design::text_px(cx, COMPACT_CHECKBOX_FONT)) + .text_size(design::ui_px(cx, COMPACT_CHECKBOX_FONT)) .child(t!("strat.settings.text_step").to_string()), ) .child( @@ -629,7 +613,7 @@ fn pref_group( MoonCheckbox::new(SharedString::from(format!("strategies-pref-{}", row.id))) .label(t!(row.label).to_string()) .checked((row.read)(&prefs)) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) .on_change(move |checked: &bool, _window, app| { let checked = *checked; target.update(app, |this, cx| this.write_pref(row, checked, cx)); diff --git a/crates/moon-ui-gpui/src/strategies/tree/checks.rs b/crates/moon-ui-gpui/src/strategies/tree/checks.rs index c625a39f..1cc11586 100644 --- a/crates/moon-ui-gpui/src/strategies/tree/checks.rs +++ b/crates/moon-ui-gpui/src/strategies/tree/checks.rs @@ -12,7 +12,7 @@ //! Both boxes are built here so their tone, size and id convention cannot drift apart, and both //! stage through [`stage_value`], the one rule deciding what a click leaves in `staged`. -use moon_ui::{MoonCheckbox, MoonCheckboxSize, MoonTone}; +use moon_ui::{MoonCheckbox, MoonSize, MoonTone}; use super::super::logic::{ strategy_core_is_visible, subtree_check_targets, subtree_displayed_all_checked, @@ -37,7 +37,7 @@ pub(super) fn row_checkbox(id: SharedString, checked: bool) -> MoonCheckbox { MoonCheckbox::new(id) .checked(checked) .tone(MoonTone::Positive) - .size(MoonCheckboxSize::Compact) + .size(MoonSize::Sm) } /// Decide what one checkbox click leaves in [`StrategiesView::staged`] for a single strategy. diff --git a/crates/moon-ui-gpui/src/strategies/tree/mod.rs b/crates/moon-ui-gpui/src/strategies/tree/mod.rs index d431fad8..359c6b2c 100644 --- a/crates/moon-ui-gpui/src/strategies/tree/mod.rs +++ b/crates/moon-ui-gpui/src/strategies/tree/mod.rs @@ -194,7 +194,7 @@ impl StrategiesView { .cleanable(true), ), ) - .child(self.active_only_toggle(p, cx)) + .child(self.active_only_toggle(cx)) .child(settings), ) .child( diff --git a/crates/moon-ui-gpui/tests/theme_contract/strategies.rs b/crates/moon-ui-gpui/tests/theme_contract/strategies.rs index 52461f80..2894eb96 100644 --- a/crates/moon-ui-gpui/tests/theme_contract/strategies.rs +++ b/crates/moon-ui-gpui/tests/theme_contract/strategies.rs @@ -329,12 +329,17 @@ fn persisted_active_filter_does_not_restore_retired_controls_or_hide_params() { tree_panel.contains("self.active_only_toggle("), "the pane must render the active-only toggle it delegates to settings.rs" ); - // Twice: the label and the mark are separate hit targets, and a half that stopped writing - // through the setter would look alive while persisting nothing. + // Once, through a labelled checkbox: the caption is MoonUI's own label, so the box and the + // caption are one hit target, and a separate caption handler would be a second writer to keep + // in step. assert_eq!( toggle.matches("set_active_only(").count(), - 2, - "both halves of the filter-row toggle must write through the persisted setter" + 1, + "the filter-row toggle must write through the persisted setter exactly once" + ); + assert!( + toggle.contains(".label(") && toggle.contains("strat.active_only"), + "the filter-row toggle must own its localized clickable label" ); assert!( !toggle.contains("prefs.active_only ="),