diff --git a/TASKS.md b/TASKS.md index 59c1dd1..0728901 100644 --- a/TASKS.md +++ b/TASKS.md @@ -420,3 +420,4 @@ Per-component lines live in `tasks/`. Tags there: | T38a | 2 | PASS | | | T38b | 1 | PASS | | | T39a | 1 | FAIL | a larger text size cut the density strip at 280px; ten palette colors had no name; the density and sliders untested | +| T39a | 2 | FAIL | segments split the strip equally and cut a longer label; the thumb lost its padding's height | diff --git a/src/buttons/segmented.rs b/src/buttons/segmented.rs index 2e59da1..7ee2d4d 100644 --- a/src/buttons/segmented.rs +++ b/src/buttons/segmented.rs @@ -110,8 +110,9 @@ impl RenderOnce for SegmentedControl { }| { div() .absolute() - .top_0p5() - .bottom_0p5() + .top_0() + .bottom_0() + .debug_selector(|| "segment-thumb".into()) .rounded(theme.radius(Radius::Md)) .bg(colors.surface) .border_1() @@ -135,13 +136,13 @@ impl RenderOnce for SegmentedControl { let on = ix == chosen; let fg = if on { colors.fg } else { colors.fg_muted }; let (focus, reveal) = stops.remove(0); - let named = value.clone(); + let (named, labeled) = (value.clone(), value.clone()); let (change, measure) = (self.on_change.clone(), state.clone()); let segment = div() .id(("segment", ix)) .relative() .flex() - .flex_1() + .flex_auto() .min_w_0() .items_center() .justify_center() @@ -176,15 +177,20 @@ impl RenderOnce for SegmentedControl { segment.child(Icon::new(icon).size(icon_size).color(fg)) }) .when(!label.is_empty(), |segment| { - segment.child(div().min_w_0().child(Ellipsis::new(label))) - }) - .child(measure_item(measure, ix, Axis::Horizontal)); + segment.child( + div() + .min_w_0() + .debug_selector(move || format!("segment-label {labeled}")) + .child(Ellipsis::new(label)), + ) + }); div() .relative() .flex() - .flex_1() + .flex_auto() .min_w_0() .child(segment) + .child(measure_item(measure, ix, Axis::Horizontal)) .child(reveal) }); let control = div() diff --git a/src/settings/tests/theme.rs b/src/settings/tests/theme.rs index 4c12ef2..8b50931 100644 --- a/src/settings/tests/theme.rs +++ b/src/settings/tests/theme.rs @@ -118,3 +118,36 @@ fn the_density_strip_fits_a_narrow_box_with_larger_text(cx: &mut TestAppContext) .expect("the last segment"); assert!(last.right() <= frame.right(), "{last:?} inside {frame:?}"); } + +/// At 280px and the base size the strip has room, so each label keeps its whole width: eleven letters to seven. +#[gpui::test] +fn a_label_gives_way_only_when_the_strip_lacks_room(cx: &mut TestAppContext) { + let (_, cx) = desk(narrow, cx); + settle(cx); + let compact = cx + .debug_bounds("segment-label Compact") + .expect("Compact's label"); + let comfortable = cx + .debug_bounds("segment-label Comfortable") + .expect("Comfortable's label"); + let ratio = comfortable.size.width / compact.size.width; + assert!( + (ratio - 11.0 / 7.0).abs() < 0.01, + "{comfortable:?} to {compact:?}" + ); +} + +/// The thumb covers the chosen segment, top to bottom and side to side. +#[gpui::test] +fn the_thumb_covers_the_chosen_segment(cx: &mut TestAppContext) { + let (_, cx) = desk(editor, cx); + for _ in 0..3 { + std::thread::sleep(std::time::Duration::from_millis(2)); + settle(cx); + } + let thumb = cx.debug_bounds("segment-thumb").expect("the thumb"); + let chosen = cx + .debug_bounds("segment Standard") + .expect("the chosen segment"); + assert_eq!(thumb, chosen); +}