Wire ↑↓↵ keyboard navigation in the command overlay
The footer chips already advertised ↑↓ to navigate and ↵ to open; they now match reality. - chrome::command_match exposes COMMAND_ACTIONS / matching_actions alongside the tab/history/bookmark match helpers and a CommandSelection enum + visible_command_rows that returns the flat ordered list of activatable rows. command_overlay drops its private copies of the action const and matcher and consumes them from the shared module so render and key handling share one source of truth. - ElyShell tracks command_selected_index with command_select_next / command_select_prev (cyclic, no notify when index doesn't change) and activate_selected_command which dispatches the right shell call for the currently selected CommandSelection variant and dismisses the overlay. Dismissing command mode resets the index to 0. - The shell root captures key_down via on_command_overlay_key_down. When the live snapshot's command_query starts with '>', up / down / enter run the matching helper and the event stops propagating so the omnibar input doesn't move its caret. - Each rendered row receives a `selected` flag. The selected row gets the design's tinted bg + accent-bar on the left edge so the active result is unambiguous at any keyboard step.
This commit is contained in:
@@ -2,11 +2,12 @@ use ely_browser_core::BrowserSnapshot;
|
||||
use ely_design_system::{colors, spacing};
|
||||
use ely_domain::{BrowserTab, DEFAULT_SIDEBAR_WIDTH_PX, HIDDEN_SIDEBAR_WIDTH_PX};
|
||||
use gpui::{
|
||||
AnyElement, Context, InteractiveElement, IntoElement, MouseMoveEvent, ParentElement, Render,
|
||||
SharedString, StatefulInteractiveElement, Styled, Window, div, prelude::FluentBuilder, px,
|
||||
rgb, rgba,
|
||||
AnyElement, Context, InteractiveElement, IntoElement, KeyDownEvent, MouseMoveEvent,
|
||||
ParentElement, Render, SharedString, StatefulInteractiveElement, Styled, Window, div,
|
||||
prelude::FluentBuilder, px, rgb, rgba,
|
||||
};
|
||||
|
||||
use super::chrome::command_match::visible_command_rows;
|
||||
use super::chrome::{
|
||||
panel_bg, panel_shadow, render_command_overlay,
|
||||
render_topbar as render_topbar_chrome, render_wallpaper,
|
||||
@@ -67,6 +68,7 @@ impl ElyShell {
|
||||
.on_action(cx.listener(Self::on_zoom_in))
|
||||
.on_action(cx.listener(Self::on_zoom_out))
|
||||
.on_mouse_move(cx.listener(Self::on_window_mouse_move))
|
||||
.capture_key_down(cx.listener(Self::on_command_overlay_key_down))
|
||||
.text_color(rgb(colors::INK))
|
||||
.child(render_wallpaper(snapshot.appearance.wallpaper()))
|
||||
.child(
|
||||
@@ -88,7 +90,7 @@ impl ElyShell {
|
||||
.when(hover_expanded, |el| {
|
||||
el.child(self.render_hidden_sidebar_overlay(&snapshot, cx))
|
||||
})
|
||||
.children(render_command_overlay(&snapshot, cx))
|
||||
.children(render_command_overlay(self, &snapshot, cx))
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
@@ -167,6 +169,40 @@ impl ElyShell {
|
||||
self.render_expanded_sidebar(snapshot, sidebar_width, cx)
|
||||
}
|
||||
|
||||
fn on_command_overlay_key_down(
|
||||
&mut self,
|
||||
event: &KeyDownEvent,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
let key = event.keystroke.key.as_str();
|
||||
if !matches!(key, "up" | "down" | "enter") {
|
||||
return;
|
||||
}
|
||||
|
||||
let total_rows = match &self.state {
|
||||
ShellState::Ready(core) => match core.snapshot() {
|
||||
Ok(snapshot) => {
|
||||
let Some(stripped) = snapshot.command_query.strip_prefix('>') else {
|
||||
return;
|
||||
};
|
||||
let needle = stripped.trim().to_lowercase();
|
||||
visible_command_rows(&snapshot, &needle).len()
|
||||
}
|
||||
Err(_) => return,
|
||||
},
|
||||
ShellState::StartupError(_) => return,
|
||||
};
|
||||
|
||||
match key {
|
||||
"up" => self.command_select_prev(total_rows, cx),
|
||||
"down" => self.command_select_next(total_rows, cx),
|
||||
"enter" => self.activate_selected_command(window, cx),
|
||||
_ => {}
|
||||
}
|
||||
cx.stop_propagation();
|
||||
}
|
||||
|
||||
fn on_window_mouse_move(
|
||||
&mut self,
|
||||
event: &MouseMoveEvent,
|
||||
|
||||
Reference in New Issue
Block a user