Navigation: the chosen tab follows a strip that changes width
The strip scrolled its chosen tab in once, at its first width; a panel opening beside it then narrowed it and pushed the tab out of view (ElyTable on a 30-sheet workbook). The strip now follows its chosen tab whenever the choice or its width changes, checked at paint with the width just laid out; a manual scroll stays until either changes. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2 files changed
+33
-13
No files matched your search
+9
-12
@@ -108,20 +108,16 @@ impl RenderOnce for Tabs {
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
// A wide strip scrolls; the chosen tab scrolls in once.
|
||||
// The chosen tab scrolls in per choice and width.
|
||||
let scroll = window
|
||||
.use_keyed_state((self.id.clone(), "scroll"), cx, |_, _| ScrollHandle::new())
|
||||
.read(cx)
|
||||
.clone();
|
||||
let followed =
|
||||
window.use_keyed_state(
|
||||
(self.id.clone(), "followed"),
|
||||
cx,
|
||||
|_, _| None::<SharedString>,
|
||||
);
|
||||
let follow = (axis == Axis::Horizontal
|
||||
&& followed.read(cx).as_ref() != Some(&self.selected))
|
||||
.then(|| (followed, self.selected.clone(), scroll.clone()));
|
||||
let followed = window.use_keyed_state((self.id.clone(), "followed"), cx, |_, _| {
|
||||
None::<(SharedString, Pixels)>
|
||||
});
|
||||
let follow =
|
||||
(axis == Axis::Horizontal).then(|| (followed, self.selected.clone(), scroll.clone()));
|
||||
let focus = tab_stop((self.id.clone(), "focus").into(), true, window, cx);
|
||||
let focused = focus.is_focused(window);
|
||||
let tabs = Rc::new(self.tabs);
|
||||
@@ -295,10 +291,11 @@ impl RenderOnce for Tabs {
|
||||
.children(follow.map(|(followed, selected, scroll)| {
|
||||
canvas(
|
||||
move |_, window, cx| {
|
||||
if scroll.bounds().size.width <= Pixels::ZERO {
|
||||
let now = (selected, scroll.bounds().size.width);
|
||||
if now.1 <= Pixels::ZERO || followed.read(cx).as_ref() == Some(&now) {
|
||||
return;
|
||||
}
|
||||
followed.update(cx, |followed, _| *followed = Some(selected));
|
||||
followed.update(cx, |followed, _| *followed = Some(now));
|
||||
if let Some(ix) = chosen {
|
||||
scroll.scroll_to_item(ix);
|
||||
window.request_animation_frame();
|
||||
|
||||
@@ -184,6 +184,7 @@ fn tabs_whose_choice_closed_mark_none_and_arrows_start_at_the_ends(cx: &mut Test
|
||||
struct Sheets {
|
||||
chosen: SharedString,
|
||||
clicked: Option<SharedString>,
|
||||
width: f32,
|
||||
}
|
||||
|
||||
impl Render for Sheets {
|
||||
@@ -191,7 +192,7 @@ impl Render for Sheets {
|
||||
let view = cx.entity();
|
||||
let tabs = (0..30).map(|ix| Choice::new(format!("s{ix}"), format!("Sheet {ix}")));
|
||||
div()
|
||||
.w(px(300.0))
|
||||
.w(px(self.width))
|
||||
.child(
|
||||
Tabs::new("sheets", tabs, self.chosen.clone()).on_change(move |value, _, cx| {
|
||||
view.update(cx, |view, _| view.clicked = Some(value.clone()))
|
||||
@@ -216,6 +217,7 @@ fn a_wide_strip_scrolls_its_chosen_tab_in_and_the_wheel_reaches_the_rest(cx: &mu
|
||||
let (view, cx) = cx.add_window_view(|_, _| Sheets {
|
||||
chosen: "s29".into(),
|
||||
clicked: None,
|
||||
width: 300.0,
|
||||
});
|
||||
settle(cx);
|
||||
assert!(
|
||||
@@ -242,3 +244,24 @@ fn a_wide_strip_scrolls_its_chosen_tab_in_and_the_wheel_reaches_the_rest(cx: &mu
|
||||
settle(cx);
|
||||
assert!(picked_at(10.0, &view, cx) > 15, "a new choice scrolls in");
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn a_strip_that_narrows_keeps_its_chosen_tab_in_view(cx: &mut TestAppContext) {
|
||||
setup(cx);
|
||||
let (view, cx) = cx.add_window_view(|_, _| Sheets {
|
||||
chosen: "s29".into(),
|
||||
clicked: None,
|
||||
width: 700.0,
|
||||
});
|
||||
settle(cx);
|
||||
view.update(cx, |view, cx| {
|
||||
view.width = 250.0;
|
||||
cx.notify();
|
||||
});
|
||||
settle(cx);
|
||||
assert!(picked_at(10.0, &view, cx) > 25, "the strip shows its end");
|
||||
view.update(cx, |view, _| view.clicked = None);
|
||||
click_at(245.0, cx);
|
||||
let clicked = view.read_with(cx, |view, _| view.clicked.clone());
|
||||
assert_eq!(clicked, None, "the chosen tab ends the strip");
|
||||
}
|
||||
Reference in new issue
Block a user