Improve keymap error formatting and add settings button icon (#42037)

Johnny Klucinec and Danilo Leal created

Closes https://github.com/zed-industries/zed/issues/41938

For some error messages relating to the keymap file, the font size was
too large. This was due to the error message being a child
`MarkdownString` instead of a `SharedString`. A `.text_xs()` method is
being applied to this notification, but it appears not to affect the
markdown text. I found that the H5 text size in markdown is the same
size as other error messages, so I made each element (that had text)
that size. There was also a special case for bullet points.

I also added a gear icon to the settings button, so it was more in line
with other app notifications.

Error message (text too large):

![keymap-broke](https://github.com/user-attachments/assets/2c205a3a-ae28-419f-95c4-093340760d03)

Expected behavior (notification with correct text sizing and icon):

![keymap-fixed](https://github.com/user-attachments/assets/f8a1396b-177f-4287-b390-c3804b70f1d2)

Example behavior:

![settings](https://github.com/user-attachments/assets/09397954-781f-44be-88ad-08035fe66f0c)

Release Notes:

- Improved UI for keymap error messages.

---------

Co-authored-by: Danilo Leal <daniloleal09@gmail.com>

Change summary

crates/settings/src/keymap_file.rs |  8 +++++---
crates/zed/src/zed.rs              | 19 +++++++++++--------
2 files changed, 16 insertions(+), 11 deletions(-)

Detailed changes

crates/settings/src/keymap_file.rs 🔗

@@ -303,19 +303,21 @@ impl KeymapFile {
         if errors.is_empty() {
             KeymapFileLoadResult::Success { key_bindings }
         } else {
-            let mut error_message = "Errors in user keymap file.\n".to_owned();
+            let mut error_message = "Errors in user keymap file.".to_owned();
+
             for (context, section_errors) in errors {
                 if context.is_empty() {
-                    let _ = write!(error_message, "\n\nIn section without context predicate:");
+                    let _ = write!(error_message, "\nIn section without context predicate:");
                 } else {
                     let _ = write!(
                         error_message,
-                        "\n\nIn section with {}:",
+                        "\nIn section with {}:",
                         MarkdownInlineCode(&format!("context = \"{}\"", context))
                     );
                 }
                 let _ = write!(error_message, "{section_errors}");
             }
+
             KeymapFileLoadResult::SomeFailedToLoad {
                 key_bindings,
                 error_message: MarkdownString(error_message),

crates/zed/src/zed.rs 🔗

@@ -32,8 +32,8 @@ use git_ui::project_diff::ProjectDiffToolbar;
 use gpui::{
     Action, App, AppContext as _, AsyncWindowContext, Context, DismissEvent, Element, Entity,
     Focusable, KeyBinding, ParentElement, PathPromptOptions, PromptLevel, ReadGlobal, SharedString,
-    Styled, Task, TitlebarOptions, UpdateGlobal, WeakEntity, Window, WindowKind, WindowOptions,
-    actions, image_cache, point, px, retain_all,
+    Task, TitlebarOptions, UpdateGlobal, WeakEntity, Window, WindowKind, WindowOptions, actions,
+    image_cache, point, px, retain_all,
 };
 use image_viewer::ImageInfo;
 use language::Capability;
@@ -1690,6 +1690,7 @@ fn show_keymap_file_json_error(
         cx.new(|cx| {
             MessageNotification::new(message.clone(), cx)
                 .primary_message("Open Keymap File")
+                .primary_icon(IconName::Settings)
                 .primary_on_click(|window, cx| {
                     window.dispatch_action(zed_actions::OpenKeymapFile.boxed_clone(), cx);
                     cx.emit(DismissEvent);
@@ -1748,16 +1749,18 @@ fn show_markdown_app_notification<F>(
                 cx.new(move |cx| {
                     MessageNotification::new_from_builder(cx, move |window, cx| {
                         image_cache(retain_all("notification-cache"))
-                            .text_xs()
-                            .child(markdown_preview::markdown_renderer::render_parsed_markdown(
-                                &parsed_markdown.clone(),
-                                Some(workspace_handle.clone()),
-                                window,
-                                cx,
+                            .child(div().text_ui(cx).child(
+                                markdown_preview::markdown_renderer::render_parsed_markdown(
+                                    &parsed_markdown.clone(),
+                                    Some(workspace_handle.clone()),
+                                    window,
+                                    cx,
+                                ),
                             ))
                             .into_any()
                     })
                     .primary_message(primary_button_message)
+                    .primary_icon(IconName::Settings)
                     .primary_on_click_arc(primary_button_on_click)
                 })
             })