Lists · tree guides fall from the parent's chevron and run unbroken across rows (#2)
The chevron takes its indent as a margin, so no gap parts it from its guide column; the cursor's ring is an overlay, so the guides fill the row through its border. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a6119f1e4e
commit
5ff7c219ef
4 files changed
+45
-11
No files matched your search
+17
-11
@@ -48,14 +48,14 @@ pub(super) fn draw(
|
||||
}
|
||||
|
||||
/// A faint line down each level a row sits under.
|
||||
fn guides(depth: usize, cx: &App) -> impl IntoElement {
|
||||
fn guides(name: &str, depth: usize, cx: &App) -> impl IntoElement {
|
||||
let theme = cx.theme();
|
||||
div()
|
||||
.absolute()
|
||||
.inset_0()
|
||||
.px_2()
|
||||
.flex()
|
||||
.children((0..depth).map(|_| {
|
||||
.children((0..depth).map(|level| {
|
||||
div()
|
||||
.flex_none()
|
||||
.w(theme.tree_indent())
|
||||
@@ -64,6 +64,7 @@ fn guides(depth: usize, cx: &App) -> impl IntoElement {
|
||||
.justify_center()
|
||||
.child(
|
||||
div()
|
||||
.debug_selector(|| format!("tree-guide-{name}-{level}"))
|
||||
.h_full()
|
||||
.border_l_1()
|
||||
.border_color(theme.colors.border),
|
||||
@@ -121,8 +122,10 @@ fn row(rows: &Rows, ix: usize, window: &mut Window, cx: &mut App) -> AnyElement
|
||||
);
|
||||
let (dropped_on, dragged_over, shut) = (key.clone(), key.clone(), key.clone());
|
||||
let chevron = div()
|
||||
.debug_selector(|| format!("tree-chevron-{key}"))
|
||||
.flex_none()
|
||||
.w(indent)
|
||||
.ml(indent * item.depth as f32)
|
||||
.flex()
|
||||
.justify_center()
|
||||
.when(opens, |slot| {
|
||||
@@ -176,12 +179,6 @@ fn row(rows: &Rows, ix: usize, window: &mut Window, cx: &mut App) -> AnyElement
|
||||
.gap_1()
|
||||
.px_2()
|
||||
.rounded(theme.radius(Radius::Sm))
|
||||
.border_1()
|
||||
.border_color(if rows.current == Some(ix) {
|
||||
colors.focus
|
||||
} else {
|
||||
gpui::transparent_black()
|
||||
})
|
||||
.text_size(theme.text_size(TextSize::Sm))
|
||||
.text_color(colors.fg)
|
||||
.when(selected, |row| row.bg(colors.active))
|
||||
@@ -189,8 +186,7 @@ fn row(rows: &Rows, ix: usize, window: &mut Window, cx: &mut App) -> AnyElement
|
||||
.when(landing == Some(DropAt::Inside), |row| {
|
||||
row.bg(colors.selection)
|
||||
})
|
||||
.child(guides(item.depth, cx))
|
||||
.child(div().flex_none().w(indent * item.depth as f32))
|
||||
.child(guides(&key, item.depth, cx))
|
||||
.child(chevron)
|
||||
.children(
|
||||
checked
|
||||
@@ -218,6 +214,16 @@ fn row(rows: &Rows, ix: usize, window: &mut Window, cx: &mut App) -> AnyElement
|
||||
.child(Ellipsis::new(note))
|
||||
}))
|
||||
.children(landing.filter(|at| *at != DropAt::Inside).map(line))
|
||||
.when(rows.current == Some(ix), |row| {
|
||||
row.child(
|
||||
div()
|
||||
.absolute()
|
||||
.inset_0()
|
||||
.rounded(theme.radius(Radius::Sm))
|
||||
.border_1()
|
||||
.border_color(colors.focus),
|
||||
)
|
||||
})
|
||||
.on_click(move |event, window, cx| {
|
||||
window.focus(&focus, cx);
|
||||
if event.click_count() == 2 {
|
||||
@@ -289,7 +295,7 @@ fn waiting(rows: &Rows, ix: usize, depth: usize, cx: &App) -> AnyElement {
|
||||
.flex()
|
||||
.items_center()
|
||||
.px_2()
|
||||
.child(guides(depth, cx))
|
||||
.child(guides(&format!("waiting-{ix}"), depth, cx))
|
||||
.child(
|
||||
div()
|
||||
.flex_none()
|
||||
|
||||
@@ -220,3 +220,23 @@ fn a_drop_in_a_folders_middle_moves_the_node_inside(cx: &mut TestAppContext) {
|
||||
[format!("move readme {:?} ui", DropAt::Inside)]
|
||||
);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn guides_run_unbroken_under_the_parents_chevron(cx: &mut TestAppContext) {
|
||||
let (_, cx) = explorer(false, cx);
|
||||
let bounds = |name: &'static str, cx: &mut VisualTestContext| {
|
||||
cx.debug_bounds(name).unwrap_or_else(|| panic!("no {name}"))
|
||||
};
|
||||
let chevron = bounds("tree-chevron-src", cx);
|
||||
let (lib, ui) = (
|
||||
bounds("tree-guide-lib-0", cx),
|
||||
bounds("tree-guide-ui-0", cx),
|
||||
);
|
||||
assert_eq!(
|
||||
lib.center().x,
|
||||
chevron.center().x,
|
||||
"the guide falls from the chevron's middle"
|
||||
);
|
||||
assert_eq!(lib.bottom(), ui.top(), "one row's guide meets the next");
|
||||
assert_eq!(lib.size.height, px(28.0), "a guide takes its row's height");
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
# GitHub round, 2026-10-03
|
||||
|
||||
- [x] G1 PR #1: build on Windows with `escape_args`; review, verify, merge, answer CodeRabbit
|
||||
- [x] G2 Issue #2: tree guides line up under the chevron and run unbroken across rows
|
||||
- [ ] G3 Issue #3: Checkbox, Switch, Radio, Slider and Select name their role, label and state
|
||||
- [ ] G4 Push, comment on #2 and #3, close #2
|
||||
@@ -347,3 +347,5 @@
|
||||
| T48m | 1 | FAIL | the every-guide test never checked the title |
|
||||
| T48m | 2 | FAIL | the in-place link test used a hash link, which survives without preventDefault |
|
||||
| T48m | 3 | PASS | |
|
||||
| G1 | 1 | PASS | PR #1 merged; CodeRabbit's opt-out declined: Launch is argv |
|
||||
| G2 | 1 | PASS | |
|
||||
Reference in new issue
Block a user