Improve LSP notification design (#22828)

Danilo Leal created

Mostly just fine-tuning the styles and modernizing some of the component
usage. Visually, it doesn't change that _much_, but it still polishes it
up a bit.

| Before | After |
|--------|--------|
| <img width="1426" alt="Screenshot 2025-01-08 at 11 25 01 AM"
src="https://github.com/user-attachments/assets/df074f88-08c0-47c2-bd98-1a8b6dbadc99"
/> | <img width="1426" alt="Screenshot 2025-01-08 at 11 23 24 AM"
src="https://github.com/user-attachments/assets/250e3aee-fd1b-4b32-b305-e58b4fede75a"
/> |

Release Notes:

- N/A

Change summary

assets/icons/copy.svg                 |  5 +
crates/workspace/src/notifications.rs | 95 +++++++++-------------------
2 files changed, 35 insertions(+), 65 deletions(-)

Detailed changes

assets/icons/copy.svg 🔗

@@ -1 +1,4 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-copy"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M18.4286 9H10.5714C9.70355 9 9 9.70355 9 10.5714V18.4286C9 19.2964 9.70355 20 10.5714 20H18.4286C19.2964 20 20 19.2964 20 18.4286V10.5714C20 9.70355 19.2964 9 18.4286 9Z" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M5.57143 15C4.70714 15 4 14.2929 4 13.4286V5.57143C4 4.70714 4.70714 4 5.57143 4H13.4286C14.2929 4 15 4.70714 15 5.57143" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

crates/workspace/src/notifications.rs 🔗

@@ -5,7 +5,6 @@ use gpui::{
     EventEmitter, Global, PromptLevel, Render, ScrollHandle, Task, View, ViewContext,
     VisualContext, WindowContext,
 };
-use language::DiagnosticSeverity;
 
 use std::{any::TypeId, ops::DerefMut, time::Duration};
 use ui::{prelude::*, Tooltip};
@@ -266,89 +265,57 @@ impl Render for LanguageServerPrompt {
             return div().id("language_server_prompt_notification");
         };
 
-        h_flex()
+        let (icon, color) = match request.level {
+            PromptLevel::Info => (IconName::Info, Color::Accent),
+            PromptLevel::Warning => (IconName::Warning, Color::Warning),
+            PromptLevel::Critical => (IconName::XCircle, Color::Error),
+        };
+
+        div()
             .id("language_server_prompt_notification")
+            .group("language_server_prompt_notification")
             .occlude()
-            .elevation_3(cx)
-            .items_start()
-            .justify_between()
-            .p_2()
-            .gap_2()
             .w_full()
             .max_h(vh(0.8, cx))
+            .elevation_3(cx)
             .overflow_y_scroll()
             .track_scroll(&self.scroll_handle)
-            .group("")
             .child(
                 v_flex()
-                    .w_full()
+                    .p_3()
                     .overflow_hidden()
                     .child(
                         h_flex()
-                            .w_full()
                             .justify_between()
                             .child(
                                 h_flex()
-                                    .flex_grow()
-                                    .children(
-                                        match request.level {
-                                            PromptLevel::Info => None,
-                                            PromptLevel::Warning => {
-                                                Some(DiagnosticSeverity::WARNING)
-                                            }
-                                            PromptLevel::Critical => {
-                                                Some(DiagnosticSeverity::ERROR)
-                                            }
-                                        }
-                                        .map(|severity| {
-                                            svg()
-                                                .size(cx.text_style().font_size)
-                                                .flex_none()
-                                                .mr_1()
-                                                .mt(px(-2.0))
-                                                .map(|icon| {
-                                                    if severity == DiagnosticSeverity::ERROR {
-                                                        icon.path(IconName::Warning.path())
-                                                            .text_color(Color::Error.color(cx))
-                                                    } else {
-                                                        icon.path(IconName::Warning.path())
-                                                            .text_color(Color::Warning.color(cx))
-                                                    }
-                                                })
-                                        }),
-                                    )
-                                    .child(
-                                        Label::new(request.lsp_name.clone())
-                                            .size(LabelSize::Default),
-                                    ),
+                                    .gap_2()
+                                    .child(Icon::new(icon).color(color))
+                                    .child(Label::new(request.lsp_name.clone())),
                             )
                             .child(
-                                ui::IconButton::new("close", ui::IconName::Close)
-                                    .on_click(cx.listener(|_, _, cx| cx.emit(gpui::DismissEvent))),
+                                h_flex()
+                                    .child(
+                                        IconButton::new("copy", IconName::Copy)
+                                            .on_click({
+                                                let message = request.message.clone();
+                                                move |_, cx| {
+                                                    cx.write_to_clipboard(
+                                                        ClipboardItem::new_string(message.clone()),
+                                                    )
+                                                }
+                                            })
+                                            .tooltip(|cx| Tooltip::text("Copy Description", cx)),
+                                    )
+                                    .child(IconButton::new("close", IconName::Close).on_click(
+                                        cx.listener(|_, _, cx| cx.emit(gpui::DismissEvent)),
+                                    )),
                             ),
                     )
-                    .child(
-                        v_flex()
-                            .child(
-                                h_flex().absolute().right_0().rounded_md().child(
-                                    ui::IconButton::new("copy", ui::IconName::Copy)
-                                        .on_click({
-                                            let message = request.message.clone();
-                                            move |_, cx| {
-                                                cx.write_to_clipboard(ClipboardItem::new_string(
-                                                    message.clone(),
-                                                ))
-                                            }
-                                        })
-                                        .tooltip(|cx| Tooltip::text("Copy", cx))
-                                        .visible_on_hover(""),
-                                ),
-                            )
-                            .child(Label::new(request.message.to_string()).size(LabelSize::Small)),
-                    )
+                    .child(Label::new(request.message.to_string()).size(LabelSize::Small))
                     .children(request.actions.iter().enumerate().map(|(ix, action)| {
                         let this_handle = cx.view().clone();
-                        ui::Button::new(ix, action.title.clone())
+                        Button::new(ix, action.title.clone())
                             .size(ButtonSize::Large)
                             .on_click(move |_, cx| {
                                 let this_handle = this_handle.clone();