Skip to content

Commit face5cd

Browse files
committed
Highlight first settings search result
1 parent 4b0b6ef commit face5cd

File tree

2 files changed

+42
-2
lines changed

2 files changed

+42
-2
lines changed

src/components/preferences/PreferencesDialog.test.tsx

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ describe('PreferencesDialog', () => {
102102

103103
const dialog = screen.getByRole('dialog')
104104
const desktopHeaderActions = dialog.querySelector<HTMLElement>(
105-
'div[class~=\"ml-auto\"][class~=\"md:flex\"]'
105+
'div[class~="ml-auto"][class~="md:flex"]'
106106
)
107107

108108
if (!desktopHeaderActions) {
@@ -133,7 +133,7 @@ describe('PreferencesDialog', () => {
133133
const dialog = screen.getByRole('dialog')
134134
const mobileSearchInput =
135135
dialog.querySelector<HTMLInputElement>(
136-
'div.md\\:hidden input[placeholder=\"Search settings...\"]'
136+
'div.md\\:hidden input[placeholder="Search settings..."]'
137137
)
138138

139139
if (!mobileSearchInput) {
@@ -152,4 +152,30 @@ describe('PreferencesDialog', () => {
152152
window.dispatchEvent(new Event('resize'))
153153
}
154154
})
155+
156+
it('highlights the first desktop search result after typing', async () => {
157+
const user = userEvent.setup()
158+
159+
render(<PreferencesDialog />)
160+
161+
const dialog = screen.getByRole('dialog')
162+
const desktopHeaderActions = dialog.querySelector<HTMLElement>(
163+
'div[class~="ml-auto"][class~="md:flex"]'
164+
)
165+
166+
if (!desktopHeaderActions) {
167+
throw new Error('Expected desktop header actions to be rendered')
168+
}
169+
170+
const desktopSearchInput =
171+
within(desktopHeaderActions).getByPlaceholderText('Search settings...')
172+
await user.type(desktopSearchInput, 'provider')
173+
174+
await waitFor(() => {
175+
const searchItems =
176+
desktopHeaderActions.querySelectorAll<HTMLElement>('[cmdk-item]')
177+
expect(searchItems.length).toBeGreaterThan(0)
178+
expect(searchItems[0]).toHaveAttribute('aria-selected', 'true')
179+
})
180+
})
155181
})

src/components/preferences/PreferencesDialog.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ export function PreferencesDialog() {
213213
const [activePane, setActivePane] = useState<PreferencePane>('general')
214214
const [searchValue, setSearchValue] = useState('')
215215
const [searchOpen, setSearchOpen] = useState(false)
216+
const [searchSelection, setSearchSelection] = useState('')
216217
const [pendingJump, setPendingJump] = useState<PreferenceSearchEntry | null>(
217218
null
218219
)
@@ -237,10 +238,19 @@ export function PreferencesDialog() {
237238
[searchResults]
238239
)
239240
const isSearching = searchValue.trim().length > 0
241+
const effectiveSearchSelection =
242+
searchOpen &&
243+
isSearching &&
244+
searchResults.some(result => result.id === searchSelection)
245+
? searchSelection
246+
: searchOpen && isSearching
247+
? (searchResults[0]?.id ?? '')
248+
: ''
240249

241250
const resetSearch = useCallback((options?: { blurActive?: boolean }) => {
242251
setSearchValue('')
243252
setSearchOpen(false)
253+
setSearchSelection('')
244254
if (options?.blurActive && document.activeElement instanceof HTMLElement) {
245255
document.activeElement.blur()
246256
}
@@ -473,6 +483,8 @@ export function PreferencesDialog() {
473483
className="relative shrink-0"
474484
>
475485
<Command
486+
value={effectiveSearchSelection}
487+
onValueChange={setSearchSelection}
476488
shouldFilter={false}
477489
className="bg-transparent overflow-visible h-auto w-auto"
478490
>
@@ -561,6 +573,8 @@ export function PreferencesDialog() {
561573
className="relative md:hidden"
562574
>
563575
<Command
576+
value={effectiveSearchSelection}
577+
onValueChange={setSearchSelection}
564578
shouldFilter={false}
565579
className="bg-transparent overflow-visible"
566580
>

0 commit comments

Comments
 (0)