Detailed changes
@@ -677,9 +677,15 @@ impl Sidebar {
label,
workspace,
highlight_positions,
- } => {
- self.render_project_header(ix, path_list, label, workspace, highlight_positions, cx)
- }
+ } => self.render_project_header(
+ ix,
+ path_list,
+ label,
+ workspace,
+ highlight_positions,
+ is_selected,
+ cx,
+ ),
ListEntry::Thread {
session_info,
icon,
@@ -730,6 +736,7 @@ impl Sidebar {
label: &SharedString,
workspace: &Entity<Workspace>,
highlight_positions: &[usize],
+ is_selected: bool,
cx: &mut Context<Self>,
) -> AnyElement {
let id = SharedString::from(format!("project-header-{}", ix));
@@ -770,6 +777,7 @@ impl Sidebar {
// TODO: if is_selected, draw a blue border around the item.
ListItem::new(id)
+ .selection_outlined(is_selected)
.group_name(&group)
.toggle_state(is_active_workspace)
.child(
@@ -1092,7 +1100,7 @@ impl Sidebar {
status: AgentThreadStatus,
workspace: &Entity<Workspace>,
highlight_positions: &[usize],
- _is_selected: bool,
+ is_selected: bool,
cx: &mut Context<Self>,
) -> AnyElement {
let has_notification = self.contents.is_thread_notified(&session_info.session_id);
@@ -1114,6 +1122,7 @@ impl Sidebar {
.status(status)
.notified(has_notification)
.selected(self.focused_thread.as_ref() == Some(&session_info.session_id))
+ .outlined(is_selected)
.on_click(cx.listener(move |this, _, window, cx| {
this.selection = None;
this.activate_thread(session_info.clone(), &workspace, window, cx);
@@ -1159,7 +1168,7 @@ impl Sidebar {
let count = format!("({})", remaining_count);
ListItem::new(id)
- .toggle_state(is_selected)
+ .selection_outlined(is_selected)
.child(
h_flex()
.px_1()
@@ -24,6 +24,7 @@ pub struct ThreadItem {
notified: bool,
status: AgentThreadStatus,
selected: bool,
+ outlined: bool,
hovered: bool,
added: Option<usize>,
removed: Option<usize>,
@@ -47,6 +48,7 @@ impl ThreadItem {
notified: false,
status: AgentThreadStatus::default(),
selected: false,
+ outlined: false,
hovered: false,
added: None,
removed: None,
@@ -90,6 +92,11 @@ impl ThreadItem {
self
}
+ pub fn outlined(mut self, outlined: bool) -> Self {
+ self.outlined = outlined;
+ self
+ }
+
pub fn added(mut self, added: usize) -> Self {
self.added = Some(added);
self
@@ -221,6 +228,9 @@ impl RenderOnce for ThreadItem {
}
})
.when(self.selected, |s| s.bg(clr.element_active))
+ .border_1()
+ .border_color(gpui::transparent_black())
+ .when(self.outlined, |s| s.border_color(clr.panel_focused_border))
.hover(|s| s.bg(clr.element_hover))
.on_hover(self.on_hover)
.child(
@@ -409,6 +419,29 @@ impl Component for ThreadItem {
)
.into_any_element(),
),
+ single_example(
+ "Outlined Item (Keyboard Selection)",
+ container()
+ .child(
+ ThreadItem::new("ti-7", "Implement keyboard navigation")
+ .icon(IconName::AiClaude)
+ .timestamp("4:00 PM")
+ .outlined(true),
+ )
+ .into_any_element(),
+ ),
+ single_example(
+ "Selected + Outlined",
+ container()
+ .child(
+ ThreadItem::new("ti-8", "Active and keyboard-focused thread")
+ .icon(IconName::AiGemini)
+ .timestamp("5:00 PM")
+ .selected(true)
+ .outlined(true),
+ )
+ .into_any_element(),
+ ),
];
Some(
@@ -42,6 +42,7 @@ pub struct ListItem {
selectable: bool,
always_show_disclosure_icon: bool,
outlined: bool,
+ selection_outlined: Option<bool>,
rounded: bool,
overflow_x: bool,
focused: Option<bool>,
@@ -71,6 +72,7 @@ impl ListItem {
selectable: true,
always_show_disclosure_icon: false,
outlined: false,
+ selection_outlined: None,
rounded: false,
overflow_x: false,
focused: None,
@@ -171,6 +173,11 @@ impl ListItem {
self
}
+ pub fn selection_outlined(mut self, outlined: bool) -> Self {
+ self.selection_outlined = Some(outlined);
+ self
+ }
+
pub fn rounded(mut self) -> Self {
self.rounded = true;
self
@@ -241,6 +248,13 @@ impl RenderOnce for ListItem {
})
})
.when(self.rounded, |this| this.rounded_sm())
+ .when_some(self.selection_outlined, |this, outlined| {
+ this.border_1()
+ .border_color(gpui::transparent_black())
+ .when(outlined, |this| {
+ this.border_color(cx.theme().colors().panel_focused_border)
+ })
+ })
.when_some(self.on_hover, |this, on_hover| this.on_hover(on_hover))
.child(
h_flex()