debugger: Add refinements to the UI (#35940)

Took a little bit of time to add just a handful of small tweaks to the
debugger UI so it looks slightly more polished. This PR includes
adjustments to size, focus styles, and more in icon buttons, overall
spacing nudges in each section pane, making tooltip labels title case
(for overall consistency), and some icon SVG iteration.

Release Notes:

- N/A
This commit is contained in:
Danilo Leal 2025-08-10 15:23:27 -03:00 committed by GitHub
parent 95e302fa68
commit f3d6deb5a3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 263 additions and 204 deletions

View file

@ -36,7 +36,7 @@ use settings::Settings;
use std::sync::{Arc, LazyLock};
use task::{DebugScenario, TaskContext};
use tree_sitter::{Query, StreamingIterator as _};
use ui::{ContextMenu, Divider, PopoverMenuHandle, Tooltip, prelude::*};
use ui::{ContextMenu, Divider, PopoverMenuHandle, Tab, Tooltip, prelude::*};
use util::{ResultExt, debug_panic, maybe};
use workspace::SplitDirection;
use workspace::item::SaveOptions;
@ -642,12 +642,14 @@ impl DebugPanel {
}
})
};
let documentation_button = || {
IconButton::new("debug-open-documentation", IconName::CircleHelp)
.icon_size(IconSize::Small)
.on_click(move |_, _, cx| cx.open_url("https://zed.dev/docs/debugger"))
.tooltip(Tooltip::text("Open Documentation"))
};
let logs_button = || {
IconButton::new("debug-open-logs", IconName::Notepad)
.icon_size(IconSize::Small)
@ -658,16 +660,18 @@ impl DebugPanel {
};
Some(
div.border_b_1()
.border_color(cx.theme().colors().border)
.p_1()
div.w_full()
.py_1()
.px_1p5()
.justify_between()
.w_full()
.border_b_1()
.border_color(cx.theme().colors().border)
.when(is_side, |this| this.gap_1())
.child(
h_flex()
.justify_between()
.child(
h_flex().gap_2().w_full().when_some(
h_flex().gap_1().w_full().when_some(
active_session
.as_ref()
.map(|session| session.read(cx).running_state()),
@ -679,6 +683,7 @@ impl DebugPanel {
let capabilities = running_state.read(cx).capabilities(cx);
let supports_detach =
running_state.read(cx).session().read(cx).is_attached();
this.map(|this| {
if thread_status == ThreadStatus::Running {
this.child(
@ -686,8 +691,7 @@ impl DebugPanel {
"debug-pause",
IconName::DebugPause,
)
.icon_size(IconSize::XSmall)
.shape(ui::IconButtonShape::Square)
.icon_size(IconSize::Small)
.on_click(window.listener_for(
&running_state,
|this, _, _window, cx| {
@ -698,7 +702,7 @@ impl DebugPanel {
let focus_handle = focus_handle.clone();
move |window, cx| {
Tooltip::for_action_in(
"Pause program",
"Pause Program",
&Pause,
&focus_handle,
window,
@ -713,8 +717,7 @@ impl DebugPanel {
"debug-continue",
IconName::DebugContinue,
)
.icon_size(IconSize::XSmall)
.shape(ui::IconButtonShape::Square)
.icon_size(IconSize::Small)
.on_click(window.listener_for(
&running_state,
|this, _, _window, cx| this.continue_thread(cx),
@ -724,7 +727,7 @@ impl DebugPanel {
let focus_handle = focus_handle.clone();
move |window, cx| {
Tooltip::for_action_in(
"Continue program",
"Continue Program",
&Continue,
&focus_handle,
window,
@ -737,8 +740,7 @@ impl DebugPanel {
})
.child(
IconButton::new("debug-step-over", IconName::ArrowRight)
.icon_size(IconSize::XSmall)
.shape(ui::IconButtonShape::Square)
.icon_size(IconSize::Small)
.on_click(window.listener_for(
&running_state,
|this, _, _window, cx| {
@ -750,7 +752,7 @@ impl DebugPanel {
let focus_handle = focus_handle.clone();
move |window, cx| {
Tooltip::for_action_in(
"Step over",
"Step Over",
&StepOver,
&focus_handle,
window,
@ -764,8 +766,7 @@ impl DebugPanel {
"debug-step-into",
IconName::ArrowDownRight,
)
.icon_size(IconSize::XSmall)
.shape(ui::IconButtonShape::Square)
.icon_size(IconSize::Small)
.on_click(window.listener_for(
&running_state,
|this, _, _window, cx| {
@ -777,7 +778,7 @@ impl DebugPanel {
let focus_handle = focus_handle.clone();
move |window, cx| {
Tooltip::for_action_in(
"Step in",
"Step In",
&StepInto,
&focus_handle,
window,
@ -789,7 +790,6 @@ impl DebugPanel {
.child(
IconButton::new("debug-step-out", IconName::ArrowUpRight)
.icon_size(IconSize::Small)
.shape(ui::IconButtonShape::Square)
.on_click(window.listener_for(
&running_state,
|this, _, _window, cx| {
@ -801,7 +801,7 @@ impl DebugPanel {
let focus_handle = focus_handle.clone();
move |window, cx| {
Tooltip::for_action_in(
"Step out",
"Step Out",
&StepOut,
&focus_handle,
window,
@ -813,7 +813,7 @@ impl DebugPanel {
.child(Divider::vertical())
.child(
IconButton::new("debug-restart", IconName::RotateCcw)
.icon_size(IconSize::XSmall)
.icon_size(IconSize::Small)
.on_click(window.listener_for(
&running_state,
|this, _, window, cx| {
@ -835,7 +835,7 @@ impl DebugPanel {
)
.child(
IconButton::new("debug-stop", IconName::Power)
.icon_size(IconSize::XSmall)
.icon_size(IconSize::Small)
.on_click(window.listener_for(
&running_state,
|this, _, _window, cx| {
@ -890,7 +890,7 @@ impl DebugPanel {
thread_status != ThreadStatus::Stopped
&& thread_status != ThreadStatus::Running,
)
.icon_size(IconSize::XSmall)
.icon_size(IconSize::Small)
.on_click(window.listener_for(
&running_state,
|this, _, _, cx| {
@ -915,7 +915,6 @@ impl DebugPanel {
},
),
)
.justify_around()
.when(is_side, |this| {
this.child(new_session_button())
.child(logs_button())
@ -924,7 +923,7 @@ impl DebugPanel {
)
.child(
h_flex()
.gap_2()
.gap_0p5()
.when(is_side, |this| this.justify_between())
.child(
h_flex().when_some(
@ -954,12 +953,15 @@ impl DebugPanel {
)
})
})
.when(!is_side, |this| this.gap_2().child(Divider::vertical()))
.when(!is_side, |this| {
this.gap_0p5().child(Divider::vertical())
})
},
),
)
.child(
h_flex()
.gap_0p5()
.children(self.render_session_menu(
self.active_session(),
self.running_state(cx),
@ -1702,6 +1704,7 @@ impl Render for DebugPanel {
this.child(active_session)
} else {
let docked_to_bottom = self.position(window, cx) == DockPosition::Bottom;
let welcome_experience = v_flex()
.when_else(
docked_to_bottom,
@ -1767,54 +1770,58 @@ impl Render for DebugPanel {
);
}),
);
let breakpoint_list =
v_flex()
.group("base-breakpoint-list")
.items_start()
.when_else(
docked_to_bottom,
|this| this.min_w_1_3().h_full(),
|this| this.w_full().h_2_3(),
)
.p_1()
.child(
h_flex()
.pl_1()
.w_full()
.justify_between()
.child(Label::new("Breakpoints").size(LabelSize::Small))
.child(h_flex().visible_on_hover("base-breakpoint-list").child(
let breakpoint_list = v_flex()
.group("base-breakpoint-list")
.when_else(
docked_to_bottom,
|this| this.min_w_1_3().h_full(),
|this| this.size_full().h_2_3(),
)
.child(
h_flex()
.track_focus(&self.breakpoint_list.focus_handle(cx))
.h(Tab::container_height(cx))
.p_1p5()
.w_full()
.justify_between()
.border_b_1()
.border_color(cx.theme().colors().border_variant)
.child(Label::new("Breakpoints").size(LabelSize::Small))
.child(
h_flex().visible_on_hover("base-breakpoint-list").child(
self.breakpoint_list.read(cx).render_control_strip(),
))
.track_focus(&self.breakpoint_list.focus_handle(cx)),
)
.child(Divider::horizontal())
.child(self.breakpoint_list.clone());
),
),
)
.child(self.breakpoint_list.clone());
this.child(
v_flex()
.h_full()
.size_full()
.gap_1()
.items_center()
.justify_center()
.child(
div()
.when_else(docked_to_bottom, Div::h_flex, Div::v_flex)
.size_full()
.map(|this| {
if docked_to_bottom {
this.items_start()
.child(breakpoint_list)
.child(Divider::vertical())
.child(welcome_experience)
.child(Divider::vertical())
} else {
this.items_end()
.child(welcome_experience)
.child(Divider::horizontal())
.child(breakpoint_list)
}
}),
),
.map(|this| {
if docked_to_bottom {
this.child(
h_flex()
.size_full()
.child(breakpoint_list)
.child(Divider::vertical())
.child(welcome_experience)
.child(Divider::vertical()),
)
} else {
this.child(
v_flex()
.size_full()
.child(welcome_experience)
.child(Divider::horizontal())
.child(breakpoint_list),
)
}
}),
)
}
})