Skip to content

Settings editor - add focus next/previous setting commands#326375

Open
soreavis wants to merge 6 commits into
microsoft:mainfrom
soreavis:feature/52815-focus-next-previous-setting
Open

Settings editor - add focus next/previous setting commands#326375
soreavis wants to merge 6 commits into
microsoft:mainfrom
soreavis:feature/52815-focus-next-previous-setting

Conversation

@soreavis

Copy link
Copy Markdown

This implements the two commands @roblourens specced in #52815 (comment): settings.action.focusNextSetting and settings.action.focusPreviousSetting. They move focus directly to the next/previous setting's value control (input, checkbox, dropdown), skipping group headers, and they work no matter whether focus is currently in the search input, on a tree row, or inside a setting's control — so pressing the shortcut exactly N times from the top reaches the Nth setting's control, which was the acceptance test in that comment. With nothing focused yet, the backwards command starts from the last setting; at the first/last setting the commands are a no-op (no wrap), matching the tree's own navigation.

Implementation notes. Navigation walks the tree model (settingsTree.navigate) instead of the DOM the 2018 comment described, because the tree is virtualized and off-screen settings have no DOM; the target is revealed first and then its control is focused via the same data-key + CONTROL_SELECTOR pattern onDidClickSetting uses. Focusing the control directly announces the control's own label, the same as the existing Enter → focusSettingControl path. The commands are in the palette (f1) like focusLevelUp and the accessible diff viewer commands, since they're meant to be discoverable and rebindable.

On the keybinding: the spec suggested cmd+down/up, but that can't work — the settings dropdowns swallow every up/down keydown regardless of modifiers before the keybinding service sees them (SelectBoxList on desktop, selectBoxCustom.ts keydown handler stops arrow/Space/Enter with EventHelper.stop; SelectBoxNative on iOS web does the same), so stepping would break at every enum setting. Cmd+arrows are also already taken inside the settings editor by widget navigation (search ↔ TOC) and list scrolling. F7 / Shift+F7 follows the accessible diff viewer / wordHighlight.next "go to next item" precedent and passes through the search box, text inputs, checkboxes, and dropdowns (verified on macOS). Can change the default or ship the commands unbound if you'd rather.

Verified in a dev build on macOS: from a fresh editor the first press lands on the first setting (skipping the Commonly Used header), six presses reach the sixth setting stepping through two dropdowns with the list auto-scrolling, Shift+F7 steps back, Shift+F7 with nothing focused lands on the last setting, and the commands stop at the ends. Consistent with the sibling settings focus commands (#106897, #321571), no automated test is added — the navigation runs entirely through the existing tree model.

Fixes #52815

Add settings.action.focusNextSetting (F7) and
settings.action.focusPreviousSetting (Shift+F7), which move focus
directly to the next/previous setting's value control, skipping group
headers. They work no matter whether focus is in the search input, on
a tree row, or inside a setting's control, so pressing the shortcut N
times from the top reaches the Nth setting's control.

Navigation walks the tree model rather than the DOM since the tree is
virtualized; the target row is revealed first so its control can be
focused (same pattern as revealing a setting link target).

Fixes microsoft#52815
Copilot AI review requested due to automatic review settings July 17, 2026 16:21
@vs-code-engineering

Copy link
Copy Markdown
Contributor

📬 CODENOTIFY

The following users are being notified based on files changed in this PR:

@rzhao271

Matched files:

  • src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts
  • src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds keyboard commands for moving focus between setting controls in the Settings editor.

Changes:

  • Adds next/previous setting-control navigation.
  • Registers F7 and Shift+F7 commands.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
settingsEditor2.ts Implements adjacent-setting focus navigation.
preferences.contribution.ts Registers commands and keybindings.

Comment thread src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts
Comment thread src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts Outdated
Comment thread src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts Outdated
soreavis added 2 commits July 17, 2026 18:35
Delayer.isTriggered is a method; referencing it without calling it made
the expression always truthy, so isSearchUpToDate() always returned
false and focusing the first setting from search never ran.
…ting

Guard the navigation behind isSearchUpToDate() so a pending search
cannot be navigated stale, query the focused row's control instead of
looking it up by setting key (which can match a Commonly Used
duplicate), and trim the anchor comment to one line.
@soreavis

Copy link
Copy Markdown
Author

Addressed all three: navigation now returns early while isSearchUpToDate() is false, the control lookup targets the focused row (.focused + CONTROL_SELECTOR, same as focusSettings) instead of going by setting key — which also sidesteps the Commonly Used duplicate-key case — and the anchor comment is down to one line.

One thing surfaced while wiring the guard: isSearchUpToDate() never actually worked — Delayer.isTriggered is a method and the expression referenced it without calling it, so the check was always false and focusFirstSettingFromSearch was a silent no-op. Fixed in 94a76d2 (one character); that also restores the Down-from-search navigation from #321571.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment thread src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts
The previously focused setting's container keeps its focused class
until DOM focus moves, so a global .focused selector could match the
old control first when navigating forward. Scope the lookup to the
target row via its data-id, which is also unique for Commonly Used
duplicates.
@soreavis

soreavis commented Jul 17, 2026

Copy link
Copy Markdown
Author

Committed fix — the previous container keeps focused until blur, so moving forward could grab the old control. Switched the lookup to the target row's data-id (d452267) and verified forward stepping lands in the right row every time.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment thread src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts Outdated
The settings tree retains its focus when the user moves to the search
input or the TOC, so navigation would continue from the previously
visited setting. Start from the first/last setting instead unless focus
is in the settings tree or a setting control.
@soreavis
soreavis requested a review from Copilot July 17, 2026 16:58
@soreavis

Copy link
Copy Markdown
Author

Committed fix (bc0e9d1) — the anchor now only uses the retained tree focus when the focus context is the tree or a control; from the search input or the TOC, navigation starts at the first/last setting. Verified both ways: step, refocus search, F7 restarts at the top; stepping from a focused control still continues.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

Comment thread src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts Outdated
Comment thread src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts Outdated
Interpolating the setting id into the selector could throw for a key
containing a quote. Use the list's focused-row trait class, which
targets a single row (avoiding the stale focused container on the
previously visited setting) without a dynamic attribute value.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

@soreavis

Copy link
Copy Markdown
Author

Good point on the unescaped key. Took a slightly different route than the suggestion though — a plain .focused ${CONTROL_SELECTOR} brings back the earlier problem where the previously visited setting keeps its focused class and gets matched first. Scoping to .monaco-list-row.focused (a960d53) uses the list's single focused-row trait instead, so there's no interpolated key and no stale match. Verified forward stepping still lands on each target row.

@roblourens

Copy link
Copy Markdown
Member

I tested this and it seems fine to me, but yielding to @rzhao271 as he owns this area

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add settings editor commands to focus next and previous settings

4 participants