keymap editor: Add some adjustments to the UI (#37819)

Danilo Leal created

- Makes the keymap editor search container more consistent with the
project & file search corresponding elements
- Changes the keymap editor menu item in the user menu be called "Keymap
Editor", as opposed to "Key Binding", to match with the tab and action
name

Design note: Still a bit unsure about the extra space on the right for
the keymap editor. This makes it way more consistent with the other
search views, but it also just feels like space that could be used. On
the other hand, though, it's very unlikely anyone will ever use more
than 30% of the search bar width as search queries here are likely
pretty short; definitely much shorter than project search queries.

<img width="600" height="552" alt="Screenshot 2025-09-09 at 1β€― 02@2x"
src="https://github.com/user-attachments/assets/9825a129-2c5a-4852-9837-c586b88e9332"
/>


Release Notes:

- N/A

Change summary

crates/keymap_editor/src/keymap_editor.rs                 | 283 +++++---
crates/keymap_editor/src/ui_components/keystroke_input.rs |  30 
crates/search/src/project_search.rs                       |   5 
crates/search/src/search_bar.rs                           |   4 
crates/title_bar/src/title_bar.rs                         |   2 
crates/ui_input/src/ui_input.rs                           |   2 
6 files changed, 178 insertions(+), 148 deletions(-)

Detailed changes

crates/keymap_editor/src/keymap_editor.rs πŸ”—

@@ -1576,33 +1576,6 @@ impl Render for KeymapEditor {
                     .child(
                         h_flex()
                             .gap_2()
-                            .child(
-                                right_click_menu("open-keymap-menu")
-                                    .menu(|window, cx| {
-                                        ContextMenu::build(window, cx, |menu, _, _| {
-                                            menu.header("Open Keymap JSON")
-                                                .action("User", zed_actions::OpenKeymap.boxed_clone())
-                                                .action("Zed Default", zed_actions::OpenDefaultKeymap.boxed_clone())
-                                                .action("Vim Default", vim::OpenDefaultKeymap.boxed_clone())
-                                        })
-                                    })
-                                    .anchor(gpui::Corner::TopLeft)
-                                    .trigger(|open, _, _|
-                                        IconButton::new(
-                                            "OpenKeymapJsonButton",
-                                            IconName::Json
-                                        )
-                                        .shape(ui::IconButtonShape::Square)
-                                        .when(!open, |this|
-                                            this.tooltip(move |window, cx| {
-                                                Tooltip::with_meta("Open Keymap JSON", Some(&zed_actions::OpenKeymap),"Right click to view more options", window, cx)
-                                            })
-                                        )
-                                        .on_click(|_, window, cx| {
-                                            window.dispatch_action(zed_actions::OpenKeymap.boxed_clone(), cx);
-                                        })
-                                    )
-                            )
                             .child(
                                 div()
                                     .key_context({
@@ -1617,73 +1590,139 @@ impl Render for KeymapEditor {
                                     .py_1()
                                     .border_1()
                                     .border_color(theme.colors().border)
-                                    .rounded_lg()
+                                    .rounded_md()
                                     .child(self.filter_editor.clone()),
                             )
                             .child(
-                                IconButton::new(
-                                    "KeymapEditorToggleFiltersIcon",
-                                    IconName::Keyboard,
-                                )
-                                .shape(ui::IconButtonShape::Square)
-                                .tooltip({
-                                    let focus_handle = focus_handle.clone();
-
-                                    move |window, cx| {
-                                        Tooltip::for_action_in(
-                                            "Search by Keystroke",
-                                            &ToggleKeystrokeSearch,
-                                            &focus_handle.clone(),
-                                            window,
-                                            cx,
+                                h_flex()
+                                    .gap_1()
+                                    .min_w_64()
+                                    .child(
+                                        IconButton::new(
+                                            "KeymapEditorToggleFiltersIcon",
+                                            IconName::Keyboard,
                                         )
-                                    }
-                                })
-                                .toggle_state(matches!(
-                                    self.search_mode,
-                                    SearchMode::KeyStroke { .. }
-                                ))
-                                .on_click(|_, window, cx| {
-                                    window.dispatch_action(ToggleKeystrokeSearch.boxed_clone(), cx);
-                                }),
-                            )
-                            .child(
-                                IconButton::new("KeymapEditorConflictIcon", IconName::Warning)
-                                    .shape(ui::IconButtonShape::Square)
-                                    .when(
-                                        self.keybinding_conflict_state.any_user_binding_conflicts(),
-                                        |this| {
-                                            this.indicator(Indicator::dot().color(Color::Warning))
-                                        },
+                                        .icon_size(IconSize::Small)
+                                        .tooltip({
+                                            let focus_handle = focus_handle.clone();
+
+                                            move |window, cx| {
+                                                Tooltip::for_action_in(
+                                                    "Search by Keystroke",
+                                                    &ToggleKeystrokeSearch,
+                                                    &focus_handle.clone(),
+                                                    window,
+                                                    cx,
+                                                )
+                                            }
+                                        })
+                                        .toggle_state(matches!(
+                                            self.search_mode,
+                                            SearchMode::KeyStroke { .. }
+                                        ))
+                                        .on_click(|_, window, cx| {
+                                            window.dispatch_action(
+                                                ToggleKeystrokeSearch.boxed_clone(),
+                                                cx,
+                                            );
+                                        }),
                                     )
-                                    .tooltip({
-                                        let filter_state = self.filter_state;
-                                        let focus_handle = focus_handle.clone();
-
-                                        move |window, cx| {
-                                            Tooltip::for_action_in(
-                                                match filter_state {
-                                                    FilterState::All => "Show Conflicts",
-                                                    FilterState::Conflicts => "Hide Conflicts",
+                                    .child(
+                                        IconButton::new("KeymapEditorConflictIcon", IconName::Warning)
+                                            .icon_size(IconSize::Small)
+                                            .when(
+                                                self.keybinding_conflict_state
+                                                    .any_user_binding_conflicts(),
+                                                |this| {
+                                                    this.indicator(
+                                                        Indicator::dot().color(Color::Warning),
+                                                    )
                                                 },
-                                                &ToggleConflictFilter,
-                                                &focus_handle.clone(),
-                                                window,
-                                                cx,
                                             )
-                                        }
-                                    })
-                                    .selected_icon_color(Color::Warning)
-                                    .toggle_state(matches!(
-                                        self.filter_state,
-                                        FilterState::Conflicts
-                                    ))
-                                    .on_click(|_, window, cx| {
-                                        window.dispatch_action(
-                                            ToggleConflictFilter.boxed_clone(),
-                                            cx,
-                                        );
-                                    }),
+                                            .tooltip({
+                                                let filter_state = self.filter_state;
+                                                let focus_handle = focus_handle.clone();
+
+                                                move |window, cx| {
+                                                    Tooltip::for_action_in(
+                                                        match filter_state {
+                                                            FilterState::All => "Show Conflicts",
+                                                            FilterState::Conflicts => {
+                                                                "Hide Conflicts"
+                                                            }
+                                                        },
+                                                        &ToggleConflictFilter,
+                                                        &focus_handle.clone(),
+                                                        window,
+                                                        cx,
+                                                    )
+                                                }
+                                            })
+                                            .selected_icon_color(Color::Warning)
+                                            .toggle_state(matches!(
+                                                self.filter_state,
+                                                FilterState::Conflicts
+                                            ))
+                                            .on_click(|_, window, cx| {
+                                                window.dispatch_action(
+                                                    ToggleConflictFilter.boxed_clone(),
+                                                    cx,
+                                                );
+                                            }),
+                                    )
+                                    .child(
+                                        div()
+                                            .ml_1()
+                                            .pl_2()
+                                            .border_l_1()
+                                            .border_color(cx.theme().colors().border_variant)
+                                            .child(
+                                                right_click_menu("open-keymap-menu")
+                                                    .menu(|window, cx| {
+                                                        ContextMenu::build(window, cx, |menu, _, _| {
+                                                            menu.header("Open Keymap JSON")
+                                                                .action(
+                                                                    "User",
+                                                                    zed_actions::OpenKeymap.boxed_clone(),
+                                                                )
+                                                                .action(
+                                                                    "Zed Default",
+                                                                    zed_actions::OpenDefaultKeymap
+                                                                        .boxed_clone(),
+                                                                )
+                                                                .action(
+                                                                    "Vim Default",
+                                                                    vim::OpenDefaultKeymap.boxed_clone(),
+                                                                )
+                                                        })
+                                                    })
+                                                    .anchor(gpui::Corner::TopLeft)
+                                                    .trigger(|open, _, _| {
+                                                        IconButton::new(
+                                                            "OpenKeymapJsonButton",
+                                                            IconName::Json,
+                                                        )
+                                                        .icon_size(IconSize::Small)
+                                                        .when(!open, |this| {
+                                                            this.tooltip(move |window, cx| {
+                                                                Tooltip::with_meta(
+                                                                    "Open keymap.json",
+                                                                    Some(&zed_actions::OpenKeymap),
+                                                                    "Right click to view more options",
+                                                                    window,
+                                                                    cx,
+                                                                )
+                                                            })
+                                                        })
+                                                        .on_click(|_, window, cx| {
+                                                            window.dispatch_action(
+                                                                zed_actions::OpenKeymap.boxed_clone(),
+                                                                cx,
+                                                            );
+                                                        })
+                                                    }),
+                                            ),
+                                    )
                             ),
                     )
                     .when_some(
@@ -1694,48 +1733,42 @@ impl Render for KeymapEditor {
                         |this, exact_match| {
                             this.child(
                                 h_flex()
-                                    .map(|this| {
-                                        if self
-                                            .keybinding_conflict_state
-                                            .any_user_binding_conflicts()
-                                        {
-                                            this.pr(rems_from_px(54.))
-                                        } else {
-                                            this.pr_7()
-                                        }
-                                    })
                                     .gap_2()
                                     .child(self.keystroke_editor.clone())
                                     .child(
-                                        IconButton::new(
-                                            "keystrokes-exact-match",
-                                            IconName::CaseSensitive,
-                                        )
-                                        .tooltip({
-                                            let keystroke_focus_handle =
-                                                self.keystroke_editor.read(cx).focus_handle(cx);
-
-                                            move |window, cx| {
-                                                Tooltip::for_action_in(
-                                                    "Toggle Exact Match Mode",
-                                                    &ToggleExactKeystrokeMatching,
-                                                    &keystroke_focus_handle,
-                                                    window,
-                                                    cx,
+                                        h_flex()
+                                            .min_w_64()
+                                            .child(
+                                                IconButton::new(
+                                                    "keystrokes-exact-match",
+                                                    IconName::CaseSensitive,
                                                 )
-                                            }
-                                        })
-                                        .shape(IconButtonShape::Square)
-                                        .toggle_state(exact_match)
-                                        .on_click(
-                                            cx.listener(|_, _, window, cx| {
-                                                window.dispatch_action(
-                                                    ToggleExactKeystrokeMatching.boxed_clone(),
-                                                    cx,
-                                                );
-                                            }),
-                                        ),
-                                    ),
+                                                .tooltip({
+                                                    let keystroke_focus_handle =
+                                                        self.keystroke_editor.read(cx).focus_handle(cx);
+
+                                                    move |window, cx| {
+                                                        Tooltip::for_action_in(
+                                                            "Toggle Exact Match Mode",
+                                                            &ToggleExactKeystrokeMatching,
+                                                            &keystroke_focus_handle,
+                                                            window,
+                                                            cx,
+                                                        )
+                                                    }
+                                                })
+                                                .shape(IconButtonShape::Square)
+                                                .toggle_state(exact_match)
+                                                .on_click(
+                                                    cx.listener(|_, _, window, cx| {
+                                                        window.dispatch_action(
+                                                            ToggleExactKeystrokeMatching.boxed_clone(),
+                                                            cx,
+                                                        );
+                                                    }),
+                                                ),
+                                            ),
+                                    )
                             )
                         },
                     ),

crates/keymap_editor/src/ui_components/keystroke_input.rs πŸ”—

@@ -461,7 +461,7 @@ impl Render for KeystrokeInput {
         let is_focused = self.outer_focus_handle.contains_focused(window, cx);
         let is_recording = self.is_recording(window);
 
-        let horizontal_padding = rems_from_px(64.);
+        let width = rems_from_px(64.);
 
         let recording_bg_color = colors
             .editor_background
@@ -528,6 +528,9 @@ impl Render for KeystrokeInput {
         h_flex()
             .id("keystroke-input")
             .track_focus(&self.outer_focus_handle)
+            .key_context(Self::key_context())
+            .on_action(cx.listener(Self::start_recording))
+            .on_action(cx.listener(Self::clear_keystrokes))
             .py_2()
             .px_3()
             .gap_2()
@@ -535,7 +538,7 @@ impl Render for KeystrokeInput {
             .w_full()
             .flex_1()
             .justify_between()
-            .rounded_sm()
+            .rounded_md()
             .overflow_hidden()
             .map(|this| {
                 if is_recording {
@@ -545,16 +548,16 @@ impl Render for KeystrokeInput {
                 }
             })
             .border_1()
-            .border_color(colors.border_variant)
-            .when(is_focused, |parent| {
-                parent.border_color(colors.border_focused)
+            .map(|this| {
+                if is_focused {
+                    this.border_color(colors.border_focused)
+                } else {
+                    this.border_color(colors.border_variant)
+                }
             })
-            .key_context(Self::key_context())
-            .on_action(cx.listener(Self::start_recording))
-            .on_action(cx.listener(Self::clear_keystrokes))
             .child(
                 h_flex()
-                    .w(horizontal_padding)
+                    .w(width)
                     .gap_0p5()
                     .justify_start()
                     .flex_none()
@@ -573,14 +576,13 @@ impl Render for KeystrokeInput {
                     .id("keystroke-input-inner")
                     .track_focus(&self.inner_focus_handle)
                     .on_modifiers_changed(cx.listener(Self::on_modifiers_changed))
-                    .size_full()
                     .when(!self.search, |this| {
                         this.focus(|mut style| {
                             style.border_color = Some(colors.border_focused);
                             style
                         })
                     })
-                    .w_full()
+                    .size_full()
                     .min_w_0()
                     .justify_center()
                     .flex_wrap()
@@ -589,7 +591,7 @@ impl Render for KeystrokeInput {
             )
             .child(
                 h_flex()
-                    .w(horizontal_padding)
+                    .w(width)
                     .gap_0p5()
                     .justify_end()
                     .flex_none()
@@ -641,9 +643,7 @@ impl Render for KeystrokeInput {
                                 "Clear Keystrokes",
                                 &ClearKeystrokes,
                             ))
-                            .when(!is_recording || !is_focused, |this| {
-                                this.icon_color(Color::Muted)
-                            })
+                            .when(!is_focused, |this| this.icon_color(Color::Muted))
                             .on_click(cx.listener(|this, _event, window, cx| {
                                 this.clear_keystrokes(&ClearKeystrokes, window, cx);
                             })),

crates/search/src/project_search.rs πŸ”—

@@ -36,10 +36,7 @@ use std::{
     pin::pin,
     sync::Arc,
 };
-use ui::{
-    Icon, IconButton, IconButtonShape, IconName, KeyBinding, Label, LabelCommon, LabelSize,
-    Toggleable, Tooltip, h_flex, prelude::*, utils::SearchInputWidth, v_flex,
-};
+use ui::{IconButtonShape, KeyBinding, Toggleable, Tooltip, prelude::*, utils::SearchInputWidth};
 use util::{ResultExt as _, paths::PathMatcher};
 use workspace::{
     DeploySearch, ItemNavHistory, NewSearch, ToolbarItemEvent, ToolbarItemLocation,

crates/search/src/search_bar.rs πŸ”—

@@ -41,15 +41,15 @@ pub(super) fn render_action_button(
 
 pub(crate) fn input_base_styles(border_color: Hsla, map: impl FnOnce(Div) -> Div) -> Div {
     h_flex()
-        .min_w_32()
         .map(map)
+        .min_w_32()
         .h_8()
         .pl_2()
         .pr_1()
         .py_1()
         .border_1()
         .border_color(border_color)
-        .rounded_lg()
+        .rounded_md()
 }
 
 pub(crate) fn render_text_input(

crates/title_bar/src/title_bar.rs πŸ”—

@@ -693,7 +693,7 @@ impl TitleBar {
                             "Settings Profiles",
                             zed_actions::settings_profile_selector::Toggle.boxed_clone(),
                         )
-                        .action("Key Bindings", Box::new(keymap_editor::OpenKeymapEditor))
+                        .action("Keymap Editor", Box::new(keymap_editor::OpenKeymapEditor))
                         .action(
                             "Themes…",
                             zed_actions::theme_selector::Toggle::default().boxed_clone(),

crates/ui_input/src/ui_input.rs πŸ”—

@@ -168,7 +168,7 @@ impl Render for SingleLineInput {
                     .py_1p5()
                     .flex_grow()
                     .text_color(style.text_color)
-                    .rounded_sm()
+                    .rounded_md()
                     .bg(style.background_color)
                     .border_1()
                     .border_color(style.border_color)