keymap editor: Add some adjustments to the UI (#37819)
- 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
This commit is contained in:
@@ -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))
|
||||
},
|
||||
)
|
||||
.tooltip({
|
||||
let filter_state = self.filter_state;
|
||||
let focus_handle = focus_handle.clone();
|
||||
.icon_size(IconSize::Small)
|
||||
.tooltip({
|
||||
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,
|
||||
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,
|
||||
);
|
||||
}),
|
||||
)
|
||||
.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),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
})
|
||||
.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,
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
)
|
||||
)
|
||||
},
|
||||
),
|
||||
|
||||
@@ -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);
|
||||
})),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user