Skip to content

Settings search: find any setting from the sidebar, with ⌘F - #1018

Merged
zeronsh[bot] merged 3 commits into
zeronsh:mainfrom
alexandre-vl:zeron/settings-search
Oct 27, 2026
Merged

zeronsh[bot] merged 3 commits into
zeronsh:mainfrom
alexandre-vl:zeron/settings-search

Conversation

@alexandre-vl

@alexandre-vl alexandre-vl commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Closes #1017

The problem

Settings spans 12 pages, 53 settings rows and 24 shortcuts, with no way to search them: you guess the page, then scan it. Some rows sit where nobody would look, and ⌘K only offers Open settings. Details in #1017.

The change

Search settings, a field under Back. ⌘F (Ctrl+F) focuses it from anywhere in Settings, and its hits replace the section list.

  • Index (settings/search.rs): a table beside the pages giving each row's page, block, title and the words people search by that the title lacks. It also lists every shortcut where it's recorded, and every page. the_index_and_the_pages_agree draws every page and fails when a page shows a row the index lacks, or the index lists a row its page doesn't anchor.
  • Ranking follows the palette's thread search. Every word must match: title 100, the row's own terms 40, block 30, page 20, half again at a word start, and an exact title outranks the rest. A word nothing spells may match one a single edit off (two from 8 letters, never under 4), always below real matches. Cloud and Billing aren't searched while they're hidden.
  • Landing (settings/search/reveal.rs): a pick opens the page, glides the row a third of the way down (motion::SCROLL_GLIDE), then washes it with the accent (150 ms in, 900 ms held, 600 ms out). Rows wear a SearchAnchor and each page one page_reveal, so pages keep no state, listeners or timers for it. Reduced motion jumps. Scrolling mid-glide hands the page back. A hidden row (Autosave delay, Microphone…) lands on its toggle, and a row that hasn't drawn after 1.5 s is let go.
  • Keyboard: ↑↓ walk the hits; Enter or a click opens one, and the field keeps the keyboard for the next pick. Escape clears the query, then closes Settings. Leaving Settings any way clears it.

Screens

Dark Light
Query "theme", dark Query "theme", light
Landed on Math size, dark Landed on Math size, light
Idle, ⌘F hint Typo Shortcuts No results
Idle field Query "notifcations" Query "sidebar" Query "teleport"

theme lists titles, then the page. notifcations still finds Notifications and its rows. math size + Enter glides Appearance to its last row, which glows. Captured by the new settings-search-fixture example: the production Shell offscreen, with real ⌘F and Enter key dispatch (README).

Tests

  • settings::search (12): ranking, typos, highlights, hidden pages.
  • settings::search::reveal (10): landing math, glide, hand-back, reduced motion, fallback, seek limit, window scoping. One drives a real scroll container.
  • shell::settings_search (6), on the real Shell: the keyboard flow end to end, shortcut hits, the keyboard kept across a pick (Appshots, a click), Enter on the clear button, leaving Settings any way, and the index/pages agreement.
  • Full -p zeron-ui --lib on this head (macOS): 1856 passed, 0 failed, plus attachments:: 33 passed with --test-threads=1. One earlier run failed pull_requests::tests::pull_request_repository_picker_keeps_selection_and_cancels_detection by 0.5px. That test isn't touched here, and it fails 1 in 5 isolated runs.

Not verified: the glide's smoothness in an interactive window (the frames are offscreen), and Cloud and Billing rows, which draw only with an account. Screen readers don't hear the active hit: focus stays in the input, which isn't the rows' ancestor, so gpui ignores aria_active_descendant. The ⌘K palette shares this.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

@zeronsh
zeronsh Bot force-pushed the zeron/settings-search branch 2 times, most recently from 159a6dc to 49cb14b Compare October 27, 2026 03:23
alexandre-vl and others added 3 commits October 27, 2026 03:28
A field under Back searches every Settings page: its 53 settings rows,
each shortcut where it is recorded, and the pages. Hits replace the
section list; a pick opens the page, glides the row into view and
washes it with the accent.

- settings/search.rs: the index kept beside the pages, ranked after the
  palette's thread search, with typos below every real match.
- settings/search/reveal.rs: rows carry a SearchAnchor and each page a
  page_reveal, so landing keeps no state on the pages.
- shell/settings_search.rs: the field, its hits, ⌘F, keys and focus.
- the_index_and_the_pages_agree holds the index and the pages in step.
- docs/screenshots/settings-search: frames from the new fixture example.
⌘F moved focus to the search field even while a dialog was open over the
page (theme import, device rename, Delete all, a provider login, the sync
overlay or the account menu), leaving the dialog without the keyboard.
Each page now says whether it has a surface Escape would close, read-only
beside dismiss_on_escape, and ⌘F waits until it closes.

Also keep the field's magnifier from shrinking, as the Files search does,
and write the typo matcher's sentinel as a byte string for clippy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: zeronsh[bot] <346184242+zeronsh[bot]@users.noreply.github.com>
Providers gained Native subagents (zeronsh#1046), and its per-provider Completion
and Updates rows were never indexed. Index all four; a hit lands on the row
when its provider is expanded, else on the provider list to pick one. The
agreement test now also draws an expanded provider with every section
loaded, so a new per-provider row fails it like any other page's.

The clear button gets a tooltip and focus ring like the other icon-only
buttons, the empty state is the palette's, and the magnifier takes a nav
glyph's slot so the query lines up with the section names. ⌘F now only
waits for an account menu that is open, not one playing its exit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: zeronsh[bot] <346184242+zeronsh[bot]@users.noreply.github.com>
@zeronsh
zeronsh Bot force-pushed the zeron/settings-search branch from 49cb14b to 0a5ae8f Compare October 27, 2026 03:29

@zeronsh zeronsh Bot 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.

Security audit clean: UI code, tests and screenshots only. No dependency, build.rs or CI changes, no network or process calls, no unsafe, and the PNGs carry no trailing data. Rebased onto main and added follow-ups: the Providers rows (Native subagents from #1046, Completion, Update policy) are indexed and anchored, and the agreement test now draws an expanded provider. The clear button gets a tooltip and focus ring, the empty state is the palette's, the field lines up with the nav, and ⌘F no longer waits on a closing account menu. ⌘F is bound only inside Settings; nothing else in the app uses it, and the shortcut recorders and user bindings still take it first. Local: cargo test -p zeron-ui --lib 2006 passed, 0 failed; app and fixture build; no clippy warnings on added lines.

@zeronsh
zeronsh Bot merged commit bf6d71a into zeronsh:main Oct 27, 2026
17 of 18 checks passed
zeronsh Bot added a commit to alexandre-vl/zeron that referenced this pull request Oct 27, 2026
Appshots is hidden off macOS and Linux, so search can't find its rows there
and the test failed on Windows since zeronsh#1018.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: zeronsh[bot] <346184242+zeronsh[bot]@users.noreply.github.com>
zeronsh Bot added a commit that referenced this pull request Oct 27, 2026
…ting (#1005)

* Smooth scrolling: mouse-wheel notches glide like Chrome's, with a setting

A mouse-wheel notch moved content in one jump: GPUI hands non-precise
wheels to containers as `ScrollDelta::Lines`, applied at once. The window
root now takes each notch at the end of the capture phase and replays it
over the following frames as fractional `Lines` slices, on Chrome's wheel
curve (`cc::ScrollOffsetAnimationCurve` for `kMouseWheel`): ease-in-out,
cubic-bezier(0.42, 0, 0.58, 1), over 200ms, shortening to 100ms for long
moves. A notch in flight retargets at the current speed, so a spin is one
continuous glide. Slices stay in lines, so every container keeps its own
line height and a notch travels exactly as far as before.

Precise input, notches with Ctrl, Alt, Cmd or Fn held, and content that
eases notches itself (WebView2) stay raw; a press ends a glide.

The in-app browser on macOS glides too. AppKit hands a page its wheel
directly and WKWebView applies a tick at once, so a local event monitor
holds the page's ticks and replays the same glide as precise pixel deltas,
which WebKit routes like a trackpad's: to the scroller under the pointer,
clamped at its edges.

Settings → Appearance → Motion → Smooth scrolling, on by default. Reduced
motion turns it off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Transcript: upward input breaks the bottom pin as it arrives

The pin broke only when one wheel event moved the view more than 1px from
the bottom, decided in a deferred check. A glided notch starts and ends
with sub-pixel slices, and its slices arrive on frames, where the spring's
step runs before that check: it pulled the view back and recorded the
distance the check compared against. A notch up from the bottom of a chat
drifted back down. Upward input over a scrollable transcript now breaks
the pin on the spot, as use-stick-to-bottom's wheel handler does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: smooth scrolling media

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Transcript: only a wheel the list took breaks the bottom pin

`on_scroll_wheel` broke the pin for any upward wheel that bubbled to the
transcript root, including one an overlay above the list let through
(an image viewer at its pan limit, say) while the list never moved. The
list's scroll handler now marks the event it took, and only that event
can escape the pin.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: zeronsh[bot] <346184242+zeronsh[bot]@users.noreply.github.com>

* Smooth scrolling: the AppKit glide flag is macOS-only

Only `browser::macos` reads it; elsewhere `gliding` was dead code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: zeronsh[bot] <346184242+zeronsh[bot]@users.noreply.github.com>

* Smooth scrolling: leave touchpads alone on X11 and Windows

X11 reports touchpads (and high-resolution wheels) as fractional
`ScrollDelta::Lines`, so every touchpad event was held back and eased
over 200ms. Outside macOS, where trackpads are flagged precise, only a
whole-line delta is a wheel notch; fractional lines now pass through.

The transcript's arrival-time pin escape is for wheel notches only:
precise input keeps the distance test it had before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: zeronsh[bot] <346184242+zeronsh[bot]@users.noreply.github.com>

* Smooth scrolling: drop the browser's unused wheel fixture hook

No fixture calls fixture_wheel; it served a throwaway capture that was never
committed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: zeronsh[bot] <346184242+zeronsh[bot]@users.noreply.github.com>

* Smooth scrolling: findable in settings search

The Motion row joins the settings index under Appearance → Motion, with the
words people reach for: mouse, wheel, glide, ease.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: zeronsh[bot] <346184242+zeronsh[bot]@users.noreply.github.com>

* Settings search: the Appshots pick test runs where Appshots shows

Appshots is hidden off macOS and Linux, so search can't find its rows there
and the test failed on Windows since #1018.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: zeronsh[bot] <346184242+zeronsh[bot]@users.noreply.github.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Wing <44917547+wingleeio@users.noreply.github.com>
Co-authored-by: zeronsh[bot] <346184242+zeronsh[bot]@users.noreply.github.com>
zeronsh Bot added a commit that referenced this pull request Oct 27, 2026
a_pick_keeps_the_keyboard_in_the_field searched for "destination" and
expected Appshots' Destination row. Appshots has no page off macOS and
Linux, so the search (rightly) finds none of it on Windows and the test
failed there since #1018. #1005 gated the whole test to macOS and Linux;
this runs the focus check on Windows again.

- a_pick_keeps_the_keyboard_in_the_field drops that cfg gate and picks
  Files' Autosave, a row every platform shows, by Enter and by a click.
- appshots_leaves_a_pick_the_keyboard keeps the Appshots case, the page
  that takes the keyboard as it opens, where Appshots exists; on Windows
  it holds that "appshot", "destination" and "capture" find no Appshots
  hit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: zeronsh[bot] <346184242+zeronsh[bot]@users.noreply.github.com>
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.

[Feature]: Search Settings: find any setting without knowing its page

2 participants