diff --git a/src/__tests__/skills-index.test.tsx b/src/__tests__/skills-index.test.tsx
index 2c9202286..260b3bcb4 100644
--- a/src/__tests__/skills-index.test.tsx
+++ b/src/__tests__/skills-index.test.tsx
@@ -178,6 +178,56 @@ describe('SkillsIndex', () => {
})
})
+ it('switches browse default sorting back to relevance when entering search', async () => {
+ searchMock = { sort: 'downloads' }
+ vi.useFakeTimers()
+
+ render()
+
+ const input = screen.getByPlaceholderText('Filter by name, slug, or summary…')
+ await act(async () => {
+ fireEvent.change(input, { target: { value: 'cli-design-framework' } })
+ await vi.runAllTimersAsync()
+ })
+
+ expect(navigateMock).toHaveBeenCalled()
+ const lastCall = navigateMock.mock.calls.at(-1)?.[0] as {
+ replace?: boolean
+ search: (prev: Record) => Record
+ }
+ expect(lastCall.replace).toBe(true)
+ expect(lastCall.search({ sort: 'downloads' })).toEqual({
+ q: 'cli-design-framework',
+ sort: undefined,
+ dir: undefined,
+ })
+ })
+
+ it('preserves explicitly user-set downloads sort when entering search', async () => {
+ searchMock = { sort: 'downloads', dir: 'desc' }
+ vi.useFakeTimers()
+
+ render()
+
+ const input = screen.getByPlaceholderText('Filter by name, slug, or summary…')
+ await act(async () => {
+ fireEvent.change(input, { target: { value: 'cli-design-framework' } })
+ await vi.runAllTimersAsync()
+ })
+
+ expect(navigateMock).toHaveBeenCalled()
+ const lastCall = navigateMock.mock.calls.at(-1)?.[0] as {
+ replace?: boolean
+ search: (prev: Record) => Record
+ }
+ expect(lastCall.replace).toBe(true)
+ expect(lastCall.search({ sort: 'downloads', dir: 'desc' })).toEqual({
+ q: 'cli-design-framework',
+ sort: 'downloads',
+ dir: 'desc',
+ })
+ })
+
it('loads more results when search pagination is requested', async () => {
searchMock = { q: 'remind' }
vi.stubGlobal('IntersectionObserver', undefined)
diff --git a/src/routes/skills/-useSkillsBrowseModel.ts b/src/routes/skills/-useSkillsBrowseModel.ts
index 25a26de02..93c24c1e5 100644
--- a/src/routes/skills/-useSkillsBrowseModel.ts
+++ b/src/routes/skills/-useSkillsBrowseModel.ts
@@ -229,7 +229,22 @@ export function useSkillsBrowseModel({
const trimmed = next.trim()
navigateTimer.current = window.setTimeout(() => {
void navigate({
- search: (prev) => ({ ...prev, q: trimmed ? next : undefined }),
+ search: (prev) => {
+ const hadQuery = typeof prev.q === 'string' && prev.q.trim().length > 0
+ const enteringSearch = Boolean(trimmed) && !hadQuery
+ const usesImplicitBrowseDefault = prev.sort === 'downloads' && prev.dir === undefined
+
+ return {
+ ...prev,
+ q: trimmed ? next : undefined,
+ ...(enteringSearch && usesImplicitBrowseDefault
+ ? {
+ sort: undefined,
+ dir: undefined,
+ }
+ : null),
+ }
+ },
replace: true,
})
}, 220)