22
33import { tString , useLanguage } from '@/intl/client' ;
44import type { SiteSection } from '@gitbook/api' ;
5+ import { Button , Checkbox , DropdownMenu , DropdownMenuItem } from '../primitives' ;
56import { SegmentedControl , SegmentedControlItem } from '../primitives/SegmentedControl' ;
67import { 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 }
0 commit comments