diff --git a/assets/icons/menu_alt.svg b/assets/icons/menu_alt.svg
index f73102e286..87add13216 100644
--- a/assets/icons/menu_alt.svg
+++ b/assets/icons/menu_alt.svg
@@ -1 +1,3 @@
-
+
diff --git a/assets/icons/menu_alt_temp.svg b/assets/icons/menu_alt_temp.svg
new file mode 100644
index 0000000000..87add13216
--- /dev/null
+++ b/assets/icons/menu_alt_temp.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/icons/x_circle_filled.svg b/assets/icons/x_circle_filled.svg
new file mode 100644
index 0000000000..52215acda8
--- /dev/null
+++ b/assets/icons/x_circle_filled.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/icons/zed_agent.svg b/assets/icons/zed_agent.svg
new file mode 100644
index 0000000000..b6e120a0b6
--- /dev/null
+++ b/assets/icons/zed_agent.svg
@@ -0,0 +1,27 @@
+
diff --git a/crates/agent2/src/native_agent_server.rs b/crates/agent2/src/native_agent_server.rs
index f8cf3dd602..74d24efb13 100644
--- a/crates/agent2/src/native_agent_server.rs
+++ b/crates/agent2/src/native_agent_server.rs
@@ -27,16 +27,15 @@ impl AgentServer for NativeAgentServer {
}
fn empty_state_headline(&self) -> &'static str {
- "Native Agent"
+ ""
}
fn empty_state_message(&self) -> &'static str {
- "How can I help you today?"
+ ""
}
fn logo(&self) -> ui::IconName {
- // Using the ZedAssistant icon as it's the native built-in agent
- ui::IconName::ZedAssistant
+ ui::IconName::ZedAgent
}
fn connect(
diff --git a/crates/agent_servers/src/gemini.rs b/crates/agent_servers/src/gemini.rs
index e1ecaf0bb5..813f8b1fe0 100644
--- a/crates/agent_servers/src/gemini.rs
+++ b/crates/agent_servers/src/gemini.rs
@@ -26,7 +26,7 @@ impl AgentServer for Gemini {
}
fn empty_state_message(&self) -> &'static str {
- "Ask questions, edit files, run commands.\nBe specific for the best results."
+ "Ask questions, edit files, run commands"
}
fn logo(&self) -> ui::IconName {
diff --git a/crates/agent_ui/src/acp/entry_view_state.rs b/crates/agent_ui/src/acp/entry_view_state.rs
index 0b0b8471a7..98af9bf838 100644
--- a/crates/agent_ui/src/acp/entry_view_state.rs
+++ b/crates/agent_ui/src/acp/entry_view_state.rs
@@ -189,6 +189,7 @@ pub enum ViewEvent {
MessageEditorEvent(Entity, MessageEditorEvent),
}
+#[derive(Debug)]
pub enum Entry {
UserMessage(Entity),
Content(HashMap),
diff --git a/crates/agent_ui/src/acp/thread_view.rs b/crates/agent_ui/src/acp/thread_view.rs
index 05f626d48e..4862bb0aa6 100644
--- a/crates/agent_ui/src/acp/thread_view.rs
+++ b/crates/agent_ui/src/acp/thread_view.rs
@@ -21,11 +21,11 @@ use file_icons::FileIcons;
use fs::Fs;
use gpui::{
Action, Animation, AnimationExt, AnyView, App, BorderStyle, ClickEvent, ClipboardItem,
- EdgesRefinement, Empty, Entity, FocusHandle, Focusable, Hsla, Length, ListOffset, ListState,
- MouseButton, PlatformDisplay, SharedString, Stateful, StyleRefinement, Subscription, Task,
- TextStyle, TextStyleRefinement, Transformation, UnderlineStyle, WeakEntity, Window,
- WindowHandle, div, linear_color_stop, linear_gradient, list, percentage, point, prelude::*,
- pulsating_between,
+ EdgesRefinement, ElementId, Empty, Entity, FocusHandle, Focusable, Hsla, Length, ListOffset,
+ ListState, MouseButton, PlatformDisplay, SharedString, Stateful, StyleRefinement, Subscription,
+ Task, TextStyle, TextStyleRefinement, Transformation, UnderlineStyle, WeakEntity, Window,
+ WindowHandle, div, ease_in_out, linear_color_stop, linear_gradient, list, percentage, point,
+ prelude::*, pulsating_between,
};
use language::Buffer;
@@ -170,7 +170,7 @@ impl AcpThreadView {
project.clone(),
thread_store.clone(),
text_thread_store.clone(),
- "Message the agent - @ to include context",
+ "Message the agent — @ to include context",
prevent_slash_commands,
editor::EditorMode::AutoHeight {
min_lines: MIN_EDITOR_LINES,
@@ -928,29 +928,41 @@ impl AcpThreadView {
None
};
- div()
+ v_flex()
.id(("user_message", entry_ix))
- .py_4()
+ .pt_2()
+ .pb_4()
.px_2()
+ .gap_1p5()
+ .w_full()
+ .children(rules_item)
.children(message.id.clone().and_then(|message_id| {
message.checkpoint.as_ref()?.show.then(|| {
- Button::new("restore-checkpoint", "Restore Checkpoint")
- .icon(IconName::Undo)
- .icon_size(IconSize::XSmall)
- .icon_position(IconPosition::Start)
- .label_size(LabelSize::XSmall)
- .on_click(cx.listener(move |this, _, _window, cx| {
- this.rewind(&message_id, cx);
- }))
+ h_flex()
+ .gap_2()
+ .child(Divider::horizontal())
+ .child(
+ Button::new("restore-checkpoint", "Restore Checkpoint")
+ .icon(IconName::Undo)
+ .icon_size(IconSize::XSmall)
+ .icon_position(IconPosition::Start)
+ .label_size(LabelSize::XSmall)
+ .icon_color(Color::Muted)
+ .color(Color::Muted)
+ .on_click(cx.listener(move |this, _, _window, cx| {
+ this.rewind(&message_id, cx);
+ }))
+ )
+ .child(Divider::horizontal())
})
}))
- .children(rules_item)
.child(
div()
.relative()
.child(
div()
- .p_3()
+ .py_3()
+ .px_2()
.rounded_lg()
.shadow_md()
.bg(cx.theme().colors().editor_background)
@@ -1080,12 +1092,20 @@ impl AcpThreadView {
if let Some(editing_index) = self.editing_message.as_ref()
&& *editing_index < entry_ix
{
- div()
- .child(primary)
- .opacity(0.2)
+ let backdrop = div()
+ .id(("backdrop", entry_ix))
+ .size_full()
+ .absolute()
+ .inset_0()
+ .bg(cx.theme().colors().panel_background)
+ .opacity(0.8)
.block_mouse_except_scroll()
- .id("overlay")
- .on_click(cx.listener(Self::cancel_editing))
+ .on_click(cx.listener(Self::cancel_editing));
+
+ div()
+ .relative()
+ .child(primary)
+ .child(backdrop)
.into_any_element()
} else {
primary
@@ -1100,7 +1120,7 @@ impl AcpThreadView {
}
fn tool_card_border_color(&self, cx: &Context) -> Hsla {
- cx.theme().colors().border.opacity(0.6)
+ cx.theme().colors().border.opacity(0.8)
}
fn tool_name_font_size(&self) -> Rems {
@@ -1299,23 +1319,14 @@ impl AcpThreadView {
tool_call.status,
ToolCallStatus::WaitingForConfirmation { .. }
);
- let is_edit = matches!(tool_call.kind, acp::ToolKind::Edit);
- let has_diff = tool_call
- .content
- .iter()
- .any(|content| matches!(content, ToolCallContent::Diff { .. }));
- let has_nonempty_diff = tool_call.content.iter().any(|content| match content {
- ToolCallContent::Diff(diff) => diff.read(cx).has_revealed_range(cx),
- _ => false,
- });
- let use_card_layout = needs_confirmation || is_edit || has_diff;
+ let is_edit =
+ matches!(tool_call.kind, acp::ToolKind::Edit) || tool_call.diffs().next().is_some();
+ let use_card_layout = needs_confirmation || is_edit;
let is_collapsible = !tool_call.content.is_empty() && !use_card_layout;
- let is_open = tool_call.content.is_empty()
- || needs_confirmation
- || has_nonempty_diff
- || self.expanded_tool_calls.contains(&tool_call.id);
+ let is_open =
+ needs_confirmation || is_edit || self.expanded_tool_calls.contains(&tool_call.id);
let gradient_overlay = |color: Hsla| {
div()
@@ -1336,41 +1347,49 @@ impl AcpThreadView {
cx.theme().colors().panel_background
};
- let tool_output_display = match &tool_call.status {
- ToolCallStatus::WaitingForConfirmation { options, .. } => v_flex()
- .w_full()
- .children(tool_call.content.iter().map(|content| {
- div()
- .child(
- self.render_tool_call_content(entry_ix, content, tool_call, window, cx),
- )
- .into_any_element()
- }))
- .child(self.render_permission_buttons(
- options,
- entry_ix,
- tool_call.id.clone(),
- tool_call.content.is_empty(),
- cx,
- )),
- ToolCallStatus::Pending
- | ToolCallStatus::InProgress
- | ToolCallStatus::Completed
- | ToolCallStatus::Failed
- | ToolCallStatus::Canceled => {
- v_flex()
+ let tool_output_display = if is_open {
+ match &tool_call.status {
+ ToolCallStatus::WaitingForConfirmation { options, .. } => {
+ v_flex()
+ .w_full()
+ .children(tool_call.content.iter().map(|content| {
+ div()
+ .child(self.render_tool_call_content(
+ entry_ix, content, tool_call, window, cx,
+ ))
+ .into_any_element()
+ }))
+ .child(self.render_permission_buttons(
+ options,
+ entry_ix,
+ tool_call.id.clone(),
+ tool_call.content.is_empty(),
+ cx,
+ ))
+ .into_any()
+ }
+ ToolCallStatus::Pending | ToolCallStatus::InProgress
+ if is_edit && tool_call.content.is_empty() =>
+ {
+ self.render_diff_loading(cx).into_any()
+ }
+ ToolCallStatus::Pending
+ | ToolCallStatus::InProgress
+ | ToolCallStatus::Completed
+ | ToolCallStatus::Failed
+ | ToolCallStatus::Canceled => v_flex()
.w_full()
.children(tool_call.content.iter().map(|content| {
- div()
- .child(
- self.render_tool_call_content(
- entry_ix, content, tool_call, window, cx,
- ),
- )
- .into_any_element()
+ div().child(
+ self.render_tool_call_content(entry_ix, content, tool_call, window, cx),
+ )
}))
+ .into_any(),
+ ToolCallStatus::Rejected => Empty.into_any(),
}
- ToolCallStatus::Rejected => v_flex().size_0(),
+ .into()
+ } else {
+ None
};
v_flex()
@@ -1390,9 +1409,13 @@ impl AcpThreadView {
.map(|this| {
if use_card_layout {
this.pl_2()
- .pr_1()
+ .pr_1p5()
.py_1()
.rounded_t_md()
+ .when(is_open, |this| {
+ this.border_b_1()
+ .border_color(self.tool_card_border_color(cx))
+ })
.bg(self.tool_card_header_bg(cx))
} else {
this.opacity(0.8).hover(|style| style.opacity(1.))
@@ -1403,6 +1426,7 @@ impl AcpThreadView {
.group(&card_header_id)
.relative()
.w_full()
+ .min_h_6()
.text_size(self.tool_name_font_size())
.child(self.render_tool_call_icon(
card_header_id,
@@ -1456,11 +1480,7 @@ impl AcpThreadView {
.overflow_x_scroll()
.child(self.render_markdown(
tool_call.label.clone(),
- default_markdown_style(
- needs_confirmation || is_edit || has_diff,
- window,
- cx,
- ),
+ default_markdown_style(false, window, cx),
)),
)
.child(gradient_overlay(gradient_color))
@@ -1480,7 +1500,7 @@ impl AcpThreadView {
)
.children(status_icon),
)
- .when(is_open, |this| this.child(tool_output_display))
+ .children(tool_output_display)
}
fn render_tool_call_content(
@@ -1501,7 +1521,7 @@ impl AcpThreadView {
Empty.into_any_element()
}
}
- ToolCallContent::Diff(diff) => self.render_diff_editor(entry_ix, diff, cx),
+ ToolCallContent::Diff(diff) => self.render_diff_editor(entry_ix, diff, tool_call, cx),
ToolCallContent::Terminal(terminal) => {
self.render_terminal_tool_call(entry_ix, terminal, tool_call, window, cx)
}
@@ -1645,21 +1665,69 @@ impl AcpThreadView {
})))
}
+ fn render_diff_loading(&self, cx: &Context) -> AnyElement {
+ let bar = |n: u64, width_class: &str| {
+ let bg_color = cx.theme().colors().element_active;
+ let base = h_flex().h_1().rounded_full();
+
+ let modified = match width_class {
+ "w_4_5" => base.w_3_4(),
+ "w_1_4" => base.w_1_4(),
+ "w_2_4" => base.w_2_4(),
+ "w_3_5" => base.w_3_5(),
+ "w_2_5" => base.w_2_5(),
+ _ => base.w_1_2(),
+ };
+
+ modified.with_animation(
+ ElementId::Integer(n),
+ Animation::new(Duration::from_secs(2)).repeat(),
+ move |tab, delta| {
+ let delta = (delta - 0.15 * n as f32) / 0.7;
+ let delta = 1.0 - (0.5 - delta).abs() * 2.;
+ let delta = ease_in_out(delta.clamp(0., 1.));
+ let delta = 0.1 + 0.9 * delta;
+
+ tab.bg(bg_color.opacity(delta))
+ },
+ )
+ };
+
+ v_flex()
+ .p_3()
+ .gap_1()
+ .rounded_b_md()
+ .bg(cx.theme().colors().editor_background)
+ .child(bar(0, "w_4_5"))
+ .child(bar(1, "w_1_4"))
+ .child(bar(2, "w_2_4"))
+ .child(bar(3, "w_3_5"))
+ .child(bar(4, "w_2_5"))
+ .into_any_element()
+ }
+
fn render_diff_editor(
&self,
entry_ix: usize,
diff: &Entity,
+ tool_call: &ToolCall,
cx: &Context,
) -> AnyElement {
+ let tool_progress = matches!(
+ &tool_call.status,
+ ToolCallStatus::InProgress | ToolCallStatus::Pending
+ );
+
v_flex()
.h_full()
- .border_t_1()
- .border_color(self.tool_card_border_color(cx))
.child(
if let Some(entry) = self.entry_view_state.read(cx).entry(entry_ix)
&& let Some(editor) = entry.editor_for_diff(diff)
+ && diff.read(cx).has_revealed_range(cx)
{
editor.clone().into_any_element()
+ } else if tool_progress {
+ self.render_diff_loading(cx)
} else {
Empty.into_any()
},
@@ -1924,11 +1992,11 @@ impl AcpThreadView {
.justify_center()
.child(div().opacity(0.3).child(logo))
.child(
- h_flex().absolute().right_1().bottom_0().child(
- Icon::new(IconName::XCircle)
- .color(Color::Error)
- .size(IconSize::Small),
- ),
+ h_flex()
+ .absolute()
+ .right_1()
+ .bottom_0()
+ .child(Icon::new(IconName::XCircleFilled).color(Color::Error)),
)
.into_any_element()
}
@@ -1982,12 +2050,12 @@ impl AcpThreadView {
Some(
v_flex()
- .pt_2()
.px_2p5()
.gap_1()
.when_some(user_rules_text, |parent, user_rules_text| {
parent.child(
h_flex()
+ .group("user-rules")
.w_full()
.child(
Icon::new(IconName::Reader)
@@ -2008,6 +2076,7 @@ impl AcpThreadView {
.shape(ui::IconButtonShape::Square)
.icon_size(IconSize::XSmall)
.icon_color(Color::Ignored)
+ .visible_on_hover("user-rules")
// TODO: Figure out a way to pass focus handle here so we can display the `OpenRulesLibrary` keybinding
.tooltip(Tooltip::text("View User Rules"))
.on_click(move |_event, window, cx| {
@@ -2024,6 +2093,7 @@ impl AcpThreadView {
.when_some(rules_file_text, |parent, rules_file_text| {
parent.child(
h_flex()
+ .group("project-rules")
.w_full()
.child(
Icon::new(IconName::File)
@@ -2044,7 +2114,8 @@ impl AcpThreadView {
.icon_size(IconSize::XSmall)
.icon_color(Color::Ignored)
.on_click(cx.listener(Self::handle_open_rules))
- .tooltip(Tooltip::text("View Rules")),
+ .visible_on_hover("project-rules")
+ .tooltip(Tooltip::text("View Project Rules")),
),
)
})
@@ -2119,11 +2190,9 @@ impl AcpThreadView {
.items_center()
.justify_center()
.child(self.render_error_agent_logo())
- .child(
- h_flex().mt_4().mb_1().justify_center().child(
- Headline::new("Authentication Required").size(HeadlineSize::Medium),
- ),
- )
+ .child(h_flex().mt_4().mb_1().justify_center().child(
+ Headline::new(self.agent.empty_state_headline()).size(HeadlineSize::Medium),
+ ))
.into_any(),
)
.children(description.map(|desc| {
@@ -2838,10 +2907,10 @@ impl AcpThreadView {
.child(
h_flex()
.flex_none()
+ .flex_wrap()
.justify_between()
.child(
h_flex()
- .gap_1()
.child(self.render_follow_toggle(cx))
.children(self.render_burn_mode_toggle(cx)),
)
@@ -2883,7 +2952,7 @@ impl AcpThreadView {
h_flex()
.flex_shrink_0()
.gap_0p5()
- .mr_1()
+ .mr_1p5()
.child(
Label::new(used)
.size(LabelSize::Small)
@@ -2904,7 +2973,11 @@ impl AcpThreadView {
}
}),
)
- .child(Label::new("/").size(LabelSize::Small).color(Color::Muted))
+ .child(
+ Label::new("/")
+ .size(LabelSize::Small)
+ .color(Color::Custom(cx.theme().colors().text_muted.opacity(0.5))),
+ )
.child(Label::new(max).size(LabelSize::Small).color(Color::Muted)),
)
}
diff --git a/crates/agent_ui/src/agent_panel.rs b/crates/agent_ui/src/agent_panel.rs
index 297bb5f3e8..c89dc56795 100644
--- a/crates/agent_ui/src/agent_panel.rs
+++ b/crates/agent_ui/src/agent_panel.rs
@@ -65,8 +65,8 @@ use theme::ThemeSettings;
use time::UtcOffset;
use ui::utils::WithRemSize;
use ui::{
- Banner, Callout, ContextMenu, ContextMenuEntry, Divider, ElevationIndex, KeyBinding,
- PopoverMenu, PopoverMenuHandle, ProgressBar, Tab, Tooltip, prelude::*,
+ Banner, Callout, ContextMenu, ContextMenuEntry, ElevationIndex, KeyBinding, PopoverMenu,
+ PopoverMenuHandle, ProgressBar, Tab, Tooltip, prelude::*,
};
use util::ResultExt as _;
use workspace::{
@@ -245,17 +245,16 @@ impl AgentType {
match self {
Self::Zed | Self::TextThread => "Zed Agent",
Self::NativeAgent => "Agent 2",
- Self::Gemini => "Google Gemini",
+ Self::Gemini => "Gemini CLI",
Self::ClaudeCode => "Claude Code",
}
}
- fn icon(self) -> IconName {
+ fn icon(self) -> Option {
match self {
- Self::Zed | Self::TextThread => IconName::AiZed,
- Self::NativeAgent => IconName::ZedAssistant,
- Self::Gemini => IconName::AiGemini,
- Self::ClaudeCode => IconName::AiClaude,
+ Self::Zed | Self::NativeAgent | Self::TextThread => None,
+ Self::Gemini => Some(IconName::AiGemini),
+ Self::ClaudeCode => Some(IconName::AiClaude),
}
}
}
@@ -2158,12 +2157,17 @@ impl AgentPanel {
})
}
- fn render_recent_entries_menu(&self, cx: &mut Context) -> impl IntoElement {
+ fn render_recent_entries_menu(
+ &self,
+ icon: IconName,
+ corner: Corner,
+ cx: &mut Context,
+ ) -> impl IntoElement {
let focus_handle = self.focus_handle(cx);
PopoverMenu::new("agent-nav-menu")
.trigger_with_tooltip(
- IconButton::new("agent-nav-menu", IconName::MenuAlt).icon_size(IconSize::Small),
+ IconButton::new("agent-nav-menu", icon).icon_size(IconSize::Small),
{
let focus_handle = focus_handle.clone();
move |window, cx| {
@@ -2177,7 +2181,7 @@ impl AgentPanel {
}
},
)
- .anchor(Corner::TopLeft)
+ .anchor(corner)
.with_handle(self.assistant_navigation_menu_handle.clone())
.menu({
let menu = self.assistant_navigation_menu.clone();
@@ -2304,7 +2308,9 @@ impl AgentPanel {
.pl(DynamicSpacing::Base04.rems(cx))
.child(self.render_toolbar_back_button(cx))
.into_any_element(),
- _ => self.render_recent_entries_menu(cx).into_any_element(),
+ _ => self
+ .render_recent_entries_menu(IconName::MenuAlt, Corner::TopLeft, cx)
+ .into_any_element(),
})
.child(self.render_title_view(window, cx)),
)
@@ -2390,7 +2396,7 @@ impl AgentPanel {
.item(
ContextMenuEntry::new("New Thread")
.action(NewThread::default().boxed_clone())
- .icon(IconName::ZedAssistant)
+ .icon(IconName::Thread)
.icon_color(Color::Muted)
.handler({
let workspace = workspace.clone();
@@ -2443,7 +2449,7 @@ impl AgentPanel {
.header("External Agents")
.when(cx.has_flag::(), |menu| {
menu.item(
- ContextMenuEntry::new("New Gemini Thread")
+ ContextMenuEntry::new("New Gemini CLI Thread")
.icon(IconName::AiGemini)
.icon_color(Color::Muted)
.handler({
@@ -2503,16 +2509,18 @@ impl AgentPanel {
let selected_agent_label = self.selected_agent.label().into();
let selected_agent = div()
.id("selected_agent_icon")
- .px(DynamicSpacing::Base02.rems(cx))
- .child(Icon::new(self.selected_agent.icon()).color(Color::Muted))
- .tooltip(move |window, cx| {
- Tooltip::with_meta(
- selected_agent_label.clone(),
- None,
- "Selected Agent",
- window,
- cx,
- )
+ .when_some(self.selected_agent.icon(), |this, icon| {
+ this.px(DynamicSpacing::Base02.rems(cx))
+ .child(Icon::new(icon).color(Color::Muted))
+ .tooltip(move |window, cx| {
+ Tooltip::with_meta(
+ selected_agent_label.clone(),
+ None,
+ "Selected Agent",
+ window,
+ cx,
+ )
+ })
})
.into_any_element();
@@ -2535,31 +2543,23 @@ impl AgentPanel {
ActiveView::History | ActiveView::Configuration => {
self.render_toolbar_back_button(cx).into_any_element()
}
- _ => h_flex()
- .gap_1()
- .child(self.render_recent_entries_menu(cx))
- .child(Divider::vertical())
- .child(selected_agent)
- .into_any_element(),
+ _ => selected_agent.into_any_element(),
})
.child(self.render_title_view(window, cx)),
)
.child(
h_flex()
- .h_full()
- .gap_2()
- .children(self.render_token_count(cx))
- .child(
- h_flex()
- .h_full()
- .gap(DynamicSpacing::Base02.rems(cx))
- .pl(DynamicSpacing::Base04.rems(cx))
- .pr(DynamicSpacing::Base06.rems(cx))
- .border_l_1()
- .border_color(cx.theme().colors().border)
- .child(new_thread_menu)
- .child(self.render_panel_options_menu(window, cx)),
- ),
+ .flex_none()
+ .gap(DynamicSpacing::Base02.rems(cx))
+ .pl(DynamicSpacing::Base04.rems(cx))
+ .pr(DynamicSpacing::Base06.rems(cx))
+ .child(new_thread_menu)
+ .child(self.render_recent_entries_menu(
+ IconName::MenuAltTemp,
+ Corner::TopRight,
+ cx,
+ ))
+ .child(self.render_panel_options_menu(window, cx)),
)
}
diff --git a/crates/icons/src/icons.rs b/crates/icons/src/icons.rs
index 8bd76cbecf..38f02c2206 100644
--- a/crates/icons/src/icons.rs
+++ b/crates/icons/src/icons.rs
@@ -155,6 +155,7 @@ pub enum IconName {
Maximize,
Menu,
MenuAlt,
+ MenuAltTemp,
Mic,
MicMute,
Minimize,
@@ -245,6 +246,8 @@ pub enum IconName {
Warning,
WholeWord,
XCircle,
+ XCircleFilled,
+ ZedAgent,
ZedAssistant,
ZedBurnMode,
ZedBurnModeOn,
diff --git a/crates/markdown/src/markdown.rs b/crates/markdown/src/markdown.rs
index 7939e97e48..a161ddd074 100644
--- a/crates/markdown/src/markdown.rs
+++ b/crates/markdown/src/markdown.rs
@@ -1084,7 +1084,13 @@ impl Element for MarkdownElement {
cx,
);
el.child(
- div().absolute().top_1().right_0p5().w_5().child(codeblock),
+ h_flex()
+ .w_5()
+ .absolute()
+ .top_1()
+ .right_1()
+ .justify_center()
+ .child(codeblock),
)
});
}