Lists: ListItem::editor draws a field in the title's place, for a row renamed in place; the title stays the row's name
CI / site (push) Successful in 29s
CI / platforms (windows-latest) (push) Successful in 4m52s
CI / crate (push) Failing after 15m34s
CI / platforms (ubuntu-24.04) (push) Canceled after 0s

This commit is contained in:
ZacharyZhang-NY committed 2026-10-19 19:10:43 -04:00
1 parent de961eb164
commit 7f7a715d79
4 files changed
+66 -4

No files matched your search

+15 -4
View File
@@ -19,6 +19,8 @@ type OnClick = Rc<dyn Fn(&ClickEvent, &mut Window, &mut App)>;
pub struct ListItem {
id: ElementId,
title: SharedString,
/// A field drawn in the title's place.
editor: Option<AnyElement>,
description: Option<SharedString>,
detail: Option<SharedString>,
leading: Option<AnyElement>,
@@ -39,6 +41,7 @@ impl ListItem {
Self {
id: id.into(),
title: title.into(),
editor: None,
description: None,
detail: None,
leading: None,
@@ -72,6 +75,12 @@ impl ListItem {
self
}
/// A field in place of the title, as a row renamed in place has it; the title stays the row's name.
pub fn editor(mut self, editor: impl IntoElement) -> Self {
self.editor = Some(editor.into_any_element());
self
}
/// A second line, quieter than the title.
pub fn description(mut self, text: impl Into<SharedString>) -> Self {
self.description = Some(text.into());
@@ -191,8 +200,9 @@ impl RenderOnce for ListItem {
.min_w_0()
.flex()
.flex_col()
.child(
line(self.title)
.child(match self.editor {
Some(editor) => div().min_w_0().child(editor).into_any_element(),
None => line(self.title)
.text_size(theme.text_size(TextSize::Base))
.when(self.strong, |title| title.font_weight(FontWeight::SEMIBOLD))
.when(self.struck, |title| title.line_through())
@@ -200,8 +210,9 @@ impl RenderOnce for ListItem {
colors.fg_muted
} else {
colors.fg
}),
)
})
.into_any_element(),
})
.children(self.description.map(|text| {
line(text.clone())
.debug_selector(|| format!("item-description-{text}"))
+49
View File
@@ -0,0 +1,49 @@
use gpui::{
Context, InteractiveElement, IntoElement, ParentElement, Render, Styled, TestAppContext,
Window, div, px,
};
use super::{settle, setup};
use crate::lists::{List, ListItem};
/// Two rows, the first renamed in place.
struct Renaming;
impl Render for Renaming {
fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
let field = div()
.debug_selector(|| "row-editor".into())
.h(px(12.0))
.w_full();
div().w(px(240.0)).child(
List::new()
.child(
ListItem::new("renamed", "Old name")
.description("~/work")
.selected(true)
.editor(field),
)
.child(ListItem::new("other", "Other").description("~/other")),
)
}
}
#[gpui::test]
fn an_editor_takes_the_title_s_place_in_its_row(cx: &mut TestAppContext) {
setup(cx);
let (_, cx) = cx.add_window_view(|_, _| Renaming);
settle(cx);
let row = cx
.debug_bounds("item-selected-Old name")
.expect("the renamed row");
let field = cx.debug_bounds("row-editor").expect("its editor");
let line = cx
.debug_bounds("item-description-~/work")
.expect("its description");
assert!(row.contains(&field.center()), "{field:?} in {row:?}");
assert!(
field.bottom() <= line.top(),
"the editor stands over the description"
);
assert!(cx.debug_bounds("item-description-~/other").is_some());
}
+1
View File
@@ -18,6 +18,7 @@ use crate::{
theme::Theme,
};
mod editor;
mod keys;
fn setup(cx: &mut TestAppContext) {