Skip to content

Commit ceb32b1

Browse files
Redo search scopes (#3688)
Co-authored-by: Claire Chabas <[email protected]>
1 parent f8c54b4 commit ceb32b1

File tree

15 files changed

+118
-86
lines changed

15 files changed

+118
-86
lines changed

.changeset/curly-fishes-accept.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"gitbook": patch
3+
---
4+
5+
Redo search scope UI

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ export function SearchContainer(props: SearchContainerProps) {
240240
}
241241
rootProps={{
242242
open: Boolean(visible && (state?.open ?? false)),
243-
modal: isMobile,
243+
modal: false,
244244
}}
245245
contentProps={{
246246
onOpenAutoFocus: (event) => event.preventDefault(),

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

Lines changed: 79 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import { tString, useLanguage } from '@/intl/client';
44
import type { SiteSection } from '@gitbook/api';
5+
import { Button, Checkbox, DropdownMenu, DropdownMenuItem } from '../primitives';
56
import { SegmentedControl, SegmentedControlItem } from '../primitives/SegmentedControl';
67
import { useSearch } from './useSearch';
78

@@ -24,80 +25,106 @@ export function SearchScopeToggle(props: {
2425
return null;
2526
}
2627

28+
// Whether to include all variants in the search
29+
const scopeIsExtended = ['extended', 'all'].includes(state.scope);
30+
2731
return (
2832
<>
2933
{withSections ? (
30-
<SegmentedControl className="animate-scale-in">
31-
{/* `Default` scope = current section's current variant + best match in other sections */}
32-
<SegmentedControlItem
33-
active={
34-
withSiteVariants
35-
? state.scope === 'default'
36-
: ['default', 'all'].includes(state.scope)
37-
}
38-
label={
39-
withSiteVariants
40-
? tString(language, 'search_scope_default')
41-
: tString(language, 'search_scope_all')
42-
}
43-
className={withSiteVariants ? '@max-md:basis-full' : ''}
44-
icon={withSiteVariants ? 'bullseye-arrow' : 'infinity'}
45-
onClick={() => setSearchState({ ...state, scope: 'default' })}
46-
/>
47-
48-
{/* `Current` scope = current section's current variant (with further variant scope selection if necessary) */}
49-
<SegmentedControlItem
50-
active={state.scope === 'current' || state.scope === 'extended'}
51-
icon={section?.icon ?? 'crosshairs'}
52-
label={tString(language, 'search_scope_current', section?.title)}
53-
onClick={() => setSearchState({ ...state, scope: 'current' })}
54-
/>
55-
56-
{/* `All` scope = all content on the site. Only visible if site has variants, otherwise it's the same as default */}
57-
{withSiteVariants ? (
34+
<div className="mb-2 flex items-center gap-2">
35+
<SegmentedControl className="grow animate-scale-in">
5836
<SegmentedControlItem
59-
active={state.scope === 'all'}
37+
active={['default', 'all'].includes(state.scope)}
6038
label={tString(language, 'search_scope_all')}
6139
icon="infinity"
62-
onClick={() => setSearchState({ ...state, scope: 'all' })}
40+
onClick={() =>
41+
setSearchState({
42+
...state,
43+
scope: scopeIsExtended ? 'all' : 'default',
44+
})
45+
}
6346
/>
47+
<SegmentedControlItem
48+
active={['current', 'extended'].includes(state.scope)}
49+
icon={section?.icon}
50+
label={tString(language, 'search_scope_current', section?.title)}
51+
onClick={() =>
52+
setSearchState({
53+
...state,
54+
scope: scopeIsExtended ? 'extended' : 'current',
55+
})
56+
}
57+
/>
58+
</SegmentedControl>
59+
{withSiteVariants ? (
60+
<DropdownMenu
61+
button={
62+
<Button
63+
icon="ellipsis"
64+
iconOnly
65+
size="default"
66+
variant="blank"
67+
label={tString(language, 'more')}
68+
className="shrink-0"
69+
active={scopeIsExtended}
70+
/>
71+
}
72+
>
73+
<DropdownMenuItem
74+
onClick={() =>
75+
setSearchState({
76+
...state,
77+
scope: (() => {
78+
switch (state.scope) {
79+
case 'extended':
80+
return 'current';
81+
case 'current':
82+
return 'extended';
83+
case 'all':
84+
return 'default';
85+
default:
86+
return 'all';
87+
}
88+
})(),
89+
})
90+
}
91+
active={scopeIsExtended}
92+
>
93+
<div className="flex items-center gap-3">
94+
<Checkbox checked={scopeIsExtended} />
95+
<div className="flex flex-col items-start">
96+
Include all variants
97+
<div className="text-tint-subtle text-xs">
98+
Search content in every language/version
99+
</div>
100+
</div>
101+
</div>
102+
</DropdownMenuItem>
103+
</DropdownMenu>
64104
) : null}
65-
</SegmentedControl>
66-
) : null}
67-
{withVariants &&
68-
(!withSections || state.scope === 'current' || state.scope === 'extended') ? (
69-
<SegmentedControl className="animate-scale-in">
70-
{/* `Current` scope = current section's current variant. `Default` on sites without sections. */}
105+
</div>
106+
) : withVariants ? (
107+
<SegmentedControl className="mb-2 animate-scale-in">
71108
<SegmentedControlItem
72109
size={withSections ? 'small' : 'medium'}
73-
active={
74-
withSections
75-
? state.scope === 'current'
76-
: ['default', 'current'].includes(state.scope)
77-
}
110+
active={!scopeIsExtended}
78111
className="py-1"
79112
label={tString(language, 'search_scope_current', spaceTitle)}
80113
onClick={() =>
81114
setSearchState({
82115
...state,
83-
scope: withSections ? 'current' : 'default',
116+
scope: 'default',
84117
})
85118
}
86119
/>
87120

88-
{/* `Extended` scope = all variants of the current section. `All` on sites without sections. */}
89121
<SegmentedControlItem
90122
size={withSections ? 'small' : 'medium'}
91-
active={
92-
withSections
93-
? state.scope === 'extended'
94-
: ['extended', 'all'].includes(state.scope)
95-
}
123+
active={scopeIsExtended}
96124
className="py-1"
97-
label={tString(language, 'search_scope_extended')}
98-
onClick={() =>
99-
setSearchState({ ...state, scope: withSections ? 'extended' : 'all' })
100-
}
125+
icon="infinity"
126+
label={tString(language, 'search_scope_all')}
127+
onClick={() => setSearchState({ ...state, scope: 'all' })}
101128
/>
102129
</SegmentedControl>
103130
) : null}

packages/gitbook/src/components/primitives/DropdownMenu.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ export function DropdownMenu(props: {
8282
onMouseLeave={() => setHovered(false)}
8383
align={align}
8484
side={side}
85-
className="z-40 animate-scale-in border-tint pt-2"
85+
className="z-50 animate-scale-in border-tint pt-2"
8686
>
8787
<div
8888
className={tcls(
@@ -214,7 +214,7 @@ export function DropdownSubMenu(props: { children: React.ReactNode; label: React
214214
<RadixDropdownMenu.SubContent
215215
hideWhenDetached
216216
collisionPadding={8}
217-
className="z-40 animate-present"
217+
className="z-50 animate-present"
218218
>
219219
<div className="flex max-h-96 min-w-40 max-w-[40vw] flex-col gap-1 overflow-auto rounded-lg straight-corners:rounded-sm bg-tint-base p-2 shadow-lg ring-1 ring-tint-subtle sm:min-w-52 sm:max-w-80">
220220
{children}

packages/gitbook/src/components/primitives/SegmentedControl.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export function SegmentedControl(props: { children: React.ReactNode; className?:
99
role="toolbar"
1010
aria-orientation="horizontal"
1111
className={tcls(
12-
'mb-2 flex flex-wrap gap-1 circular-corners:rounded-3xl rounded-corners:rounded-lg bg-tint p-1',
12+
'flex flex-wrap gap-1 circular-corners:rounded-3xl rounded-corners:rounded-lg bg-tint p-1',
1313
className
1414
)}
1515
>

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ export const de = {
1717
search_section_result_content: 'Abschnitt mit Inhalt ${1}',
1818
search_section_result_default: 'Abschnitt',
1919
search_scope_current: '${1}',
20-
search_scope_extended: 'Alle Inhalte',
21-
search_scope_default: 'Beste Match',
22-
search_scope_all: 'Alles',
20+
search_scope_all: 'Überall',
21+
search_scope_include_all_title: 'Alle Varianten einschließen',
22+
search_scope_include_all_description: 'Inhalt in jeder Sprache/Version durchsuchen',
2323
ask: 'Fragen',
2424
search_ask: 'Fragen "${1}"',
2525
search_ask_description: 'Finden Sie die Antwort mit ${1}',

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ export const en = {
1717
search_section_result_content: 'Section with content ${1}',
1818
search_section_result_default: 'Section',
1919
search_scope_current: '${1}',
20-
search_scope_extended: 'All content',
21-
search_scope_default: 'Best match',
22-
search_scope_all: 'Everything',
20+
search_scope_all: 'Everywhere',
21+
search_scope_include_all_title: 'Include all variants',
22+
search_scope_include_all_description: 'Search content in every language/version',
2323
ask: 'Ask',
2424
search_ask: 'Ask "${1}"',
2525
search_ask_description: 'Find the answer with ${1}',

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ export const es: TranslationLanguage = {
1919
search_section_result_content: 'Sección con contenido ${1}',
2020
search_section_result_default: 'Sección',
2121
search_scope_current: '${1}',
22-
search_scope_extended: 'Todo el contenido',
23-
search_scope_default: 'Mejor match',
24-
search_scope_all: 'Todo',
22+
search_scope_all: 'En todas partes',
23+
search_scope_include_all_title: 'Incluir todas las variantes',
24+
search_scope_include_all_description: 'Buscar contenido en todos los idiomas/versiones',
2525
ask: 'Preguntar',
2626
search_ask: 'Preguntar "${1}"',
2727
search_ask_description: 'Encuentra la respuesta con ${1}',

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ export const fr = {
1717
search_section_result_content: 'Section avec contenu ${1}',
1818
search_section_result_default: 'Section',
1919
search_scope_current: '${1}',
20-
search_scope_extended: 'Tous les contenus',
21-
search_scope_default: 'Meilleur match',
22-
search_scope_all: 'Tout',
20+
search_scope_all: 'Partout',
21+
search_scope_include_all_title: 'Inclure toutes les variantes',
22+
search_scope_include_all_description: 'Rechercher le contenu dans toutes les langues/versions',
2323
ask: 'Poser une question',
2424
search_ask: 'Demander « ${1} »',
2525
search_ask_description: 'Trouvez la réponse avec ${1}',

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ export const ja: TranslationLanguage = {
1919
search_section_result_content: 'コンテンツ「${1}」のセクション',
2020
search_section_result_default: 'セクション',
2121
search_scope_current: '${1}',
22-
search_scope_extended: '全てのコンテンツ',
23-
search_scope_default: '最適なマッチ',
24-
search_scope_all: 'すべて',
22+
search_scope_all: 'どこでも',
23+
search_scope_include_all_title: 'すべてのバリエーションを含める',
24+
search_scope_include_all_description: 'すべての言語/バージョンでコンテンツを検索',
2525
ask: '質問する',
2626
search_ask: '"${1}" を質問する',
2727
search_ask_description: '${1}で答えを見つける',

0 commit comments

Comments
 (0)