debugger: Polish breakpoint list UI (#41598)

Anthony Eid created

This PR fixes breakpoint icon alignment to also be at the end of a
rendered entry and enables editing breakpoint qualities when there's no
active session.

The alignment issue was caused by some icons being invisible, so the
layout phase always accounted for the space they would take up. Only
laying out the icons when they are visible fixed the issue.

#### Before
<img width="1014" height="316" alt="image"
src="https://github.com/user-attachments/assets/9a9ced06-e219-4d9d-8793-6bdfdaca48e8"
/>

#### After
[
<img width="502" height="167" alt="Screenshot 2025-10-30 at 3 21 17 PM"
src="https://github.com/user-attachments/assets/23744868-e354-461c-a940-9b6812e1bcf4"
/>
](url)

Release Notes:

- Breakpoint list: Allow adding conditions, logs, and hit conditions to
breakpoints when there's no active session

Change summary

crates/debugger_ui/src/session/running/breakpoint_list.rs | 89 ++++----
1 file changed, 45 insertions(+), 44 deletions(-)

Detailed changes

crates/debugger_ui/src/session/running/breakpoint_list.rs 🔗

@@ -549,7 +549,7 @@ impl BreakpointList {
             .session
             .as_ref()
             .map(|session| SupportedBreakpointProperties::from(session.read(cx).capabilities()))
-            .unwrap_or_else(SupportedBreakpointProperties::empty);
+            .unwrap_or_else(SupportedBreakpointProperties::all);
         let strip_mode = self.strip_mode;
 
         uniform_list(
@@ -1408,8 +1408,10 @@ impl RenderOnce for BreakpointOptionsStrip {
         h_flex()
             .gap_px()
             .mr_3() // Space to avoid overlapping with the scrollbar
-            .child(
-                div()
+            .justify_end()
+            .when(has_logs || self.is_selected, |this| {
+                this.child(
+                    div()
                     .map(self.add_focus_styles(
                         ActiveBreakpointStripMode::Log,
                         supports_logs,
@@ -1438,45 +1440,46 @@ impl RenderOnce for BreakpointOptionsStrip {
                             )
                         }),
                     )
-                    .when(!has_logs && !self.is_selected, |this| this.invisible()),
-            )
-            .child(
-                div()
-                    .map(self.add_focus_styles(
-                        ActiveBreakpointStripMode::Condition,
-                        supports_condition,
-                        window,
-                        cx,
-                    ))
-                    .child(
-                        IconButton::new(
-                            SharedString::from(format!("{id}-condition-toggle")),
-                            IconName::SplitAlt,
-                        )
-                        .shape(ui::IconButtonShape::Square)
-                        .style(style_for_toggle(
+                )
+            })
+            .when(has_condition || self.is_selected, |this| {
+                this.child(
+                    div()
+                        .map(self.add_focus_styles(
                             ActiveBreakpointStripMode::Condition,
-                            has_condition,
+                            supports_condition,
+                            window,
+                            cx,
                         ))
-                        .icon_size(IconSize::Small)
-                        .icon_color(color_for_toggle(has_condition))
-                        .when(has_condition, |this| this.indicator(Indicator::dot().color(Color::Info)))
-                        .disabled(!supports_condition)
-                        .toggle_state(self.is_toggled(ActiveBreakpointStripMode::Condition))
-                        .on_click(self.on_click_callback(ActiveBreakpointStripMode::Condition))
-                        .tooltip(|_window, cx|  {
-                            Tooltip::with_meta(
-                                "Set Condition",
-                                None,
-                                "Set condition to evaluate when a breakpoint is hit. Program execution will stop only when the condition is met.",
-                                cx,
+                        .child(
+                            IconButton::new(
+                                SharedString::from(format!("{id}-condition-toggle")),
+                                IconName::SplitAlt,
                             )
-                        }),
-                    )
-                    .when(!has_condition && !self.is_selected, |this| this.invisible()),
-            )
-            .child(
-                div()
+                            .shape(ui::IconButtonShape::Square)
+                            .style(style_for_toggle(
+                                ActiveBreakpointStripMode::Condition,
+                                has_condition,
+                            ))
+                            .icon_size(IconSize::Small)
+                            .icon_color(color_for_toggle(has_condition))
+                            .when(has_condition, |this| this.indicator(Indicator::dot().color(Color::Info)))
+                            .disabled(!supports_condition)
+                            .toggle_state(self.is_toggled(ActiveBreakpointStripMode::Condition))
+                            .on_click(self.on_click_callback(ActiveBreakpointStripMode::Condition))
+                            .tooltip(|_window, cx|  {
+                                Tooltip::with_meta(
+                                    "Set Condition",
+                                    None,
+                                    "Set condition to evaluate when a breakpoint is hit. Program execution will stop only when the condition is met.",
+                                    cx,
+                                )
+                            }),
+                        )
+                )
+            })
+            .when(has_hit_condition || self.is_selected, |this| {
+                this.child(div()
                     .map(self.add_focus_styles(
                         ActiveBreakpointStripMode::HitCondition,
                         supports_hit_condition,
@@ -1507,10 +1510,8 @@ impl RenderOnce for BreakpointOptionsStrip {
                                 cx,
                             )
                         }),
-                    )
-                    .when(!has_hit_condition && !self.is_selected, |this| {
-                        this.invisible()
-                    }),
-            )
+                    ))
+
+            })
     }
 }