settings_ui: Fix focus bugs (#40806)

Closes #40608


Release Notes:

- settings_ui: Fixed an issue where tabbing to the nav bar from the
search bar while the nav bar was scrolled would result in the first
_visible_ nav entry being selected, instead of the literal first nav
entry
- settings_ui: Fixed an issue where scrolling the selected nav entry off
screen would cause the keyboard shortcut hint for the focus nav / focus
content binding to dissapear
- settings_ui: Fixed an issue where text input controls could not be
focused via the keyboard
This commit is contained in:
Ben Kunkle
2025-10-21 12:25:07 -04:00
committed by GitHub
parent d7ffc37b14
commit cf8422f7fd
2 changed files with 37 additions and 8 deletions
+5 -4
View File
@@ -62,10 +62,6 @@ impl RenderOnce for SettingsEditor {
}
});
if let Some(tab_index) = self.tab_index {
editor.focus_handle(cx).tab_index(tab_index);
}
let weak_editor = editor.downgrade();
let theme_colors = cx.theme().colors();
@@ -78,6 +74,11 @@ impl RenderOnce for SettingsEditor {
.border_1()
.border_color(theme_colors.border)
.bg(theme_colors.editor_background)
.when_some(self.tab_index, |this, tab_index| {
let focus_handle = editor.focus_handle(cx).tab_index(tab_index).tab_stop(true);
this.track_focus(&focus_handle)
.focus(|s| s.border_color(theme_colors.border_focused))
})
.child(editor)
.when_some(self.confirm, |this, confirm| {
this.on_action::<menu::Confirm>({
+32 -4
View File
@@ -1821,6 +1821,9 @@ impl SettingsWindow {
.read(cx)
.handle
.contains_focused(window, cx)
|| self
.visible_navbar_entries()
.any(|(_, entry)| entry.focus_handle.is_focused(window))
{
"Focus Content"
} else {
@@ -2020,7 +2023,13 @@ impl SettingsWindow {
.border_t_1()
.border_color(cx.theme().colors().border_variant)
.children(
KeyBinding::for_action(&ToggleFocusNav, window, cx).map(|this| {
KeyBinding::for_action_in(
&ToggleFocusNav,
&self.navbar_focus_handle.focus_handle(cx),
window,
cx,
)
.map(|this| {
KeybindingHint::new(
this,
cx.theme().colors().surface_background.opacity(0.5),
@@ -2123,6 +2132,17 @@ impl SettingsWindow {
.any(|(index, _)| index == nav_entry_index)
}
fn focus_and_scroll_to_first_visible_nav_entry(
&self,
window: &mut Window,
cx: &mut Context<Self>,
) {
if let Some(nav_entry_index) = self.visible_navbar_entries().next().map(|(index, _)| index)
{
self.focus_and_scroll_to_nav_entry(nav_entry_index, window, cx);
}
}
fn focus_and_scroll_to_nav_entry(
&self,
nav_entry_index: usize,
@@ -2735,9 +2755,17 @@ impl Render for SettingsWindow {
let prev_index = this.focused_file_index(window, cx).saturating_sub(1);
this.focus_file_at_index(prev_index, window);
}))
.on_action(|_: &menu::SelectNext, window, _| {
window.focus_next();
})
.on_action(cx.listener(|this, _: &menu::SelectNext, window, cx| {
if this
.search_bar
.focus_handle(cx)
.contains_focused(window, cx)
{
this.focus_and_scroll_to_first_visible_nav_entry(window, cx);
} else {
window.focus_next();
}
}))
.on_action(|_: &menu::SelectPrevious, window, _| {
window.focus_prev();
})