From 8cbca183a068d27fb320d81cca2e0a4ced831abc Mon Sep 17 00:00:00 2001
From: wangnov <1694546283@qq.com>
Date: Fri, 13 Mar 2026 12:06:00 +0800
Subject: [PATCH 1/2] fix: default skills search to relevance
---
src/__tests__/skills-index.test.tsx | 25 ++++++++++++++++++++++
src/routes/skills/-useSkillsBrowseModel.ts | 17 ++++++++++++++-
2 files changed, 41 insertions(+), 1 deletion(-)
diff --git a/src/__tests__/skills-index.test.tsx b/src/__tests__/skills-index.test.tsx
index 2c92022866..1bf296876a 100644
--- a/src/__tests__/skills-index.test.tsx
+++ b/src/__tests__/skills-index.test.tsx
@@ -178,6 +178,31 @@ 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('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 25a26de028..93c24c1e58 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)
From ab99d80a2a013356659d0aa4f060cfb49adc0547 Mon Sep 17 00:00:00 2001
From: wangnov <1694546283@qq.com>
Date: Fri, 13 Mar 2026 12:36:52 +0800
Subject: [PATCH 2/2] test: cover explicit search sort guard
---
src/__tests__/skills-index.test.tsx | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/src/__tests__/skills-index.test.tsx b/src/__tests__/skills-index.test.tsx
index 1bf296876a..260b3bcb4a 100644
--- a/src/__tests__/skills-index.test.tsx
+++ b/src/__tests__/skills-index.test.tsx
@@ -203,6 +203,31 @@ describe('SkillsIndex', () => {
})
})
+ 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)