🐛 Highlight first search result in font picker and fix Enter confirm (#10450)

When the user types a search term that filters out the currently-active
font, the picker showed no selection at all and Enter would close without
applying any font. Fix:

- Compute effective-selected (render-only, no state mutation) as the
  first filtered font when the current font is absent from the results.
  The row renderer and recent-fonts list use this for the tick mark, so
  the top match is visually pre-selected while the user types.
- Enter key applies first-result (via on-select then on-close) when the
  current selection is not in the filtered list; otherwise closes as
  before. No font is live-applied on every keystroke.
- on-key-down deps extended to on-select/on-close; effect deps include
  on-key-down so the global listener is always current.

Avoids the live-apply side-effect that caused the revert of #9512.
Fixes #3204.

Signed-off-by: Filip Sajdak <filip.sajdak@siili.com>
Co-authored-by: Andrey Antukh <niwi@niwi.nz>
This commit is contained in:
Filip Sajdak 2026-07-31 10:46:53 +02:00 committed by GitHub
parent 7fa6631005
commit 0b5db57def
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -197,6 +197,13 @@
(filter #(contains? installed-ids (:id %)))
(filter-fonts state)))
;; When the active font is not in the filtered results, pre-select
;; the first match visually so the user can confirm it with Enter —
;; without live-applying it on every keystroke.
effective-selected
(if (and (seq fonts) (not (d/seek #(= (:id %) (:id @selected)) fonts)))
(first fonts)
@selected)
full-size? (boolean (and full-size show-recent))
@ -218,13 +225,18 @@
on-key-down
(mf/use-fn
(mf/deps fonts)
(mf/deps fonts on-select on-close)
(fn [event]
(cond
(kbd/up-arrow? event) (select-prev event)
(kbd/down-arrow? event) (select-next event)
(kbd/esc? event) (on-close)
(kbd/enter? event) (on-close)
(kbd/enter? event)
(let [first-result (when-not (d/seek #(= (:id %) (:id @selected)) fonts)
(first fonts))]
(if first-result
(do (on-select first-result) (on-close))
(on-close)))
:else (dom/focus! (mf/ref-val input)))))
on-filter-change
@ -239,7 +251,7 @@
(on-select font)
(on-close)))]
(mf/with-effect [fonts]
(mf/with-effect [fonts on-key-down]
(let [key (events/listen js/document "keydown" on-key-down)]
#(events/unlistenByKey key)))
@ -290,7 +302,7 @@
:font font
:style {}
:on-click on-select-and-close
:is-current (= (:id font) (:id @selected))}])])]
:is-current (= (:id font) (:id effective-selected))}])])]
[:div {:class (stl/css-case :fonts-list true
:fonts-list-full-size full-size?)}
@ -298,7 +310,7 @@
(fn [props]
(let [width (unchecked-get props "width")
height (unchecked-get props "height")
render #(row-renderer fonts @selected on-select-and-close %)]
render #(row-renderer fonts effective-selected on-select-and-close %)]
(mf/html
[:> rvt/List #js {:height height
:ref flist