Skip to content

Commit 0643b7f

Browse files
Improve ask/search Enter key press UX (#2624)
Co-authored-by: Zeno Kapitein <[email protected]>
1 parent 5b3b4e0 commit 0643b7f

File tree

14 files changed

+142
-43
lines changed

14 files changed

+142
-43
lines changed

packages/gitbook/src/components/Search/HighlightQuery.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ export function HighlightQuery(props: {
2525
'py-0.5',
2626
'rounded',
2727
'straight-corners:rounded-sm',
28+
'group-[.is-active]:bg-primary-200',
29+
'group-[.is-active]:text-contrast-primary-200',
30+
'dark:group-[.is-active]:bg-primary-700',
31+
'dark:group-[.is-active]:text-contrast-primary-700',
2832
],
2933
} = props;
3034
const matches = matchString(text, query);

packages/gitbook/src/components/Search/SearchPageResultItem.tsx

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,26 +23,38 @@ export const SearchPageResultItem = React.forwardRef(function SearchPageResultIt
2323
href={item.href}
2424
className={tcls(
2525
'flex',
26+
'gap-4',
2627
'flex-row',
2728
'items-center',
28-
'px-4',
29-
'sm:px-12',
30-
'py-4',
31-
'sm:py-6',
29+
'p-4',
3230
'border-t',
33-
'first:border-t-0',
3431
'border-dark/2',
35-
'dark:border-light/2',
36-
'hover:bg-dark-4/2',
32+
'dark:border-light/1',
33+
'first:border-none',
3734
'text-base',
38-
'text-dark',
3935
'font-medium',
40-
'first:mt-0',
41-
'dark:text-light',
42-
'dark:hover:bg-light-4/2',
43-
active ? ['bg-dark/1', 'dark:bg-light/1'] : null,
36+
'hover:bg-dark/1',
37+
'dark:hover:bg-light/1',
38+
'group',
39+
active
40+
? [
41+
'is-active',
42+
'bg-primary-50',
43+
'text-contrast-primary-50',
44+
'dark:bg-primary-800',
45+
'dark:text-contrast-primary-800',
46+
'hover:bg-primary-100/8',
47+
'dark:hover:bg-primary-700/7',
48+
]
49+
: null,
4450
)}
4551
>
52+
<div className="size-4">
53+
<Icon
54+
icon="file-lines"
55+
className={tcls('size-4', active ? 'text-primary' : 'opacity-5')}
56+
/>
57+
</div>
4658
<div className={tcls('flex', 'flex-col', 'w-full')}>
4759
{item.spaceTitle ? (
4860
<div
@@ -60,10 +72,19 @@ export const SearchPageResultItem = React.forwardRef(function SearchPageResultIt
6072
) : null}
6173
<HighlightQuery query={query} text={item.title} />
6274
</div>
63-
<Icon
64-
icon="chevron-right"
65-
className={tcls('size-4', 'text-dark', 'dark:text-light', 'opacity-6')}
66-
/>
75+
<div
76+
className={tcls(
77+
'p-2',
78+
'rounded',
79+
'straight-corners:rounded-none',
80+
active ? ['bg-primary', 'text-contrast-primary'] : ['opacity-6'],
81+
)}
82+
>
83+
<Icon
84+
icon={active ? 'arrow-turn-down-left' : 'chevron-right'}
85+
className={tcls('size-4')}
86+
/>
87+
</div>
6788
</Link>
6889
);
6990
});

packages/gitbook/src/components/Search/SearchQuestionResultItem.tsx

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,35 +26,63 @@ export const SearchQuestionResultItem = React.forwardRef(function SearchQuestion
2626
onClick={onClick}
2727
className={tcls(
2828
'flex',
29-
'flex-row',
3029
'px-4',
31-
'py-2',
32-
'hover:bg-dark-4/2',
33-
'text-dark/7',
30+
recommended ? ['py-2', 'text-dark/7', 'dark:text-light/8'] : 'py-4',
31+
'hover:bg-dark/1',
32+
'dark:hover:bg-light/1',
3433
'first:mt-0',
3534
'last:pb-3',
36-
'dark:text-light/8',
37-
'dark:hover:bg-light-4/2',
38-
active ? ['bg-dark/1', 'dark:bg-light/1'] : null,
35+
active && [
36+
'is-active',
37+
'bg-primary-50',
38+
'text-contrast-primary-50',
39+
'dark:bg-primary-800',
40+
'dark:text-contrast-primary-800',
41+
'hover:bg-primary-100/8',
42+
'dark:hover:bg-primary-700/7',
43+
],
3944
)}
4045
{...getLinkProp({
4146
ask: true,
4247
query: question,
4348
})}
4449
>
4550
<Icon
46-
icon="magnifying-glass"
51+
icon={recommended ? 'search' : 'sparkles'}
4752
className={tcls(
4853
'size-4',
4954
'shrink-0',
50-
'mt-0.5',
55+
'mt-1.5',
5156
'mr-4',
52-
'mt-1',
53-
'text-dark/5',
54-
'dark:text-light/5',
57+
active ? ['text-primary'] : ['text-dark/5', 'dark:text-light/5'],
5558
)}
5659
/>
57-
{recommended ? question : t(language, 'search_ask', [question])}
60+
<div className="w-full">
61+
{recommended ? (
62+
question
63+
) : (
64+
<>
65+
<div className="font-medium">{t(language, 'search_ask', [question])}</div>
66+
<div className={tcls('text-sm', 'text-dark/8', 'dark:text-light/8')}>
67+
{t(language, 'search_ask_description')}
68+
</div>
69+
</>
70+
)}
71+
</div>
72+
<div
73+
className={tcls(
74+
'p-2',
75+
'rounded',
76+
'self-center',
77+
'straight-corners:rounded-none',
78+
active ? ['bg-primary', 'text-contrast-primary'] : ['opacity-6'],
79+
)}
80+
>
81+
<Icon
82+
icon={active ? 'arrow-turn-down-left' : 'chevron-right'}
83+
className={tcls('size-4')}
84+
/>
85+
</div>
5886
</Link>
5987
);
6088
});

packages/gitbook/src/components/Search/SearchResults.tsx

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { t, useLanguage } from '@/intl/client';
55
import { SiteContentPointer } from '@/lib/api';
66
import { tcls } from '@/lib/tailwind';
77

8-
import { isQuestion } from './isQuestion';
98
import { SearchPageResultItem } from './SearchPageResultItem';
109
import { SearchQuestionResultItem } from './SearchQuestionResultItem';
1110
import { SearchSectionResultItem } from './SearchSectionResultItem';
@@ -92,8 +91,6 @@ export const SearchResults = React.forwardRef(function SearchResults(
9291
}
9392

9493
debounceTimeout.current = setTimeout(async () => {
95-
setCursor(null);
96-
9794
const fetchedResults = await (global
9895
? searchAllSiteContent(query, pointer)
9996
: searchSiteSpaceContent(query, pointer, revisionId));
@@ -110,6 +107,16 @@ export const SearchResults = React.forwardRef(function SearchResults(
110107
}
111108
}, [query, global, pointer, spaceId, revisionId, withAsk]);
112109

110+
React.useEffect(() => {
111+
if (!query) {
112+
// Reset the cursor when there's no query
113+
setCursor(null);
114+
} else if (results && results.length > 0) {
115+
// Auto-focus the first result
116+
setCursor(0);
117+
}
118+
}, [results, query]);
119+
113120
// Scroll to the active result.
114121
React.useEffect(() => {
115122
if (cursor === null || !refs.current[cursor]) {
@@ -256,10 +263,13 @@ export const SearchResults = React.forwardRef(function SearchResults(
256263
);
257264
});
258265

266+
/**
267+
* Add a "Ask <question>" item at the top of the results list.
268+
*/
259269
function withQuestionResult(results: null | ResultType[], query: string): null | ResultType[] {
260270
const without = results ? results.filter((result) => result.type !== 'question') : null;
261271

262-
if (!isQuestion(query)) {
272+
if (query.length === 0) {
263273
return without;
264274
}
265275

packages/gitbook/src/components/Search/SearchSectionResultItem.tsx

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Icon } from '@gitbook/icons';
12
import React from 'react';
23

34
import { tcls } from '@/lib/tailwind';
@@ -21,27 +22,39 @@ export const SearchSectionResultItem = React.forwardRef(function SearchSectionRe
2122
ref={ref}
2223
href={item.href}
2324
className={tcls(
24-
'search-section-result-item',
2525
'[&:has(+:not(&))]:mb-6',
2626
'flex',
27-
'flex-col',
28-
'mb-2',
29-
'px-4',
30-
'sm:px-12',
31-
'hover:bg-dark-4/2',
32-
'dark:hover:bg-light-4/2',
27+
'items-center',
28+
'pl-6',
29+
'sm:pl-12',
30+
'pr-4',
3331
'text-dark/8',
3432
'dark:text-light/8',
33+
'hover:bg-dark/1',
34+
'dark:hover:bg-light/1',
3535
'font-normal',
36-
'transition-colors',
37-
active ? ['bg-dark/1', 'dark:bg-light/1'] : null,
36+
'py-2',
37+
'group',
38+
active && [
39+
'is-active',
40+
'bg-primary-50',
41+
'text-contrast-primary-50',
42+
'dark:bg-primary-800',
43+
'dark:text-contrast-primary-800',
44+
'hover:bg-primary-100/8',
45+
'dark:hover:bg-primary-700/7',
46+
],
3847
)}
3948
>
4049
<div
4150
className={tcls(
4251
'border-l-2',
4352
'px-4',
44-
'py-2',
53+
'py-1',
54+
'flex',
55+
'flex-1',
56+
'overflow-hidden',
57+
'flex-col',
4558
'border-dark/2',
4659
'dark:border-light/2',
4760
)}
@@ -57,6 +70,20 @@ export const SearchSectionResultItem = React.forwardRef(function SearchSectionRe
5770
</p>
5871
) : null}
5972
</div>
73+
<div
74+
className={tcls(
75+
'p-2',
76+
'rounded',
77+
'straight-corners:rounded-none',
78+
'bg-primary',
79+
'text-contrast-primary',
80+
'hidden',
81+
'sm:block',
82+
active ? ['opacity-11', 'block'] : ['opacity-0'],
83+
)}
84+
>
85+
<Icon icon="arrow-turn-down-left" className={tcls('size-4')} />
86+
</div>
6087
</Link>
6188
);
6289
});

packages/gitbook/src/intl/translations/de.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export const de = {
1313
search_scope_space: '${1}',
1414
search_scope_all: 'Alle Inhalte',
1515
search_ask: 'Fragen "${1}"',
16+
search_ask_description: 'Finden Sie die Antwort mit AI',
1617
search_ask_sources: 'Quellen',
1718
search_ask_sources_no_answer: 'Verwandte Seiten',
1819
search_ask_no_answer:

packages/gitbook/src/intl/translations/en.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export const en = {
1313
search_scope_space: '${1}',
1414
search_scope_all: 'All content',
1515
search_ask: 'Ask "${1}"',
16+
search_ask_description: 'Find the answer with AI',
1617
search_ask_sources: 'Sources',
1718
search_ask_sources_no_answer: 'Related pages',
1819
search_ask_no_answer:

packages/gitbook/src/intl/translations/es.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export const es: TranslationLanguage = {
1515
search_scope_space: '${1}',
1616
search_scope_all: 'Todo el contenido',
1717
search_ask: 'Preguntar "${1}"',
18+
search_ask_description: 'Encuentra la respuesta con IA',
1819
search_ask_sources: 'Fuentes',
1920
search_ask_sources_no_answer: 'Páginas relacionadas',
2021
search_ask_no_answer:

packages/gitbook/src/intl/translations/fr.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export const fr: TranslationLanguage = {
1515
search_scope_space: '${1}',
1616
search_scope_all: 'Tout le contenu',
1717
search_ask: 'Demander "${1}"',
18+
search_ask_description: "Trouvez la réponse avec l'IA",
1819
search_ask_sources: 'Sources',
1920
search_ask_sources_no_answer: 'Pages connexes',
2021
search_ask_no_answer:

packages/gitbook/src/intl/translations/ja.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export const ja: TranslationLanguage = {
1515
search_scope_space: '${1}',
1616
search_scope_all: '全てのコンテンツ',
1717
search_ask: '"${1}" を質問する',
18+
search_ask_description: 'AIで答えを見つける',
1819
search_ask_sources: '情報源',
1920
search_ask_sources_no_answer: '関連ページ',
2021
search_ask_no_answer:

0 commit comments

Comments
 (0)