@@ -4,7 +4,11 @@ import cn from 'classnames'
4
4
import ResizeDetector from 'react-resize-detector'
5
5
import ChosenArrow from '../ChosenArrow'
6
6
import IconArrowSmalldown from '../../assets/images/arrow-small-down.svg'
7
+ import MagnifyingGlass from '../../assets/images/magnifying_glass.svg'
7
8
import styles from './PrimaryNav.module.scss'
9
+ import { config } from 'topcoder-react-utils'
10
+
11
+ const BASE_URL = config . URL . BASE
8
12
9
13
const PrimaryNav = ( {
10
14
collapsed,
@@ -26,93 +30,146 @@ const PrimaryNav = ({
26
30
createHandleClickMoreItem,
27
31
createSetRef,
28
32
showChosenArrow,
29
- chosenArrowX
33
+ chosenArrowX,
34
+ searchOpened,
35
+ toggleSearchOpen
30
36
} ) => {
31
37
const filterNotInMore = menu => ! ( moreMenu || [ ] ) . find ( x => x . id === menu . id )
32
-
38
+ const activeTrigger = {
39
+ bottom : 50 // The main nav head bottom Y
40
+ }
33
41
return (
34
- < div className = { cn ( styles . primaryNavContainer , showLeftMenu && styles . primaryNavContainerOpen ) } >
35
- < div className = { styles . primaryNav } ref = { createSetRef ( 'primaryNav' ) } >
36
- < a
37
- className = { cn ( styles . tcLogo , collapsed && styles . tcLogoPush ) }
38
- onClick = { onClickLogo }
39
- href = '/'
40
- >
41
- { logo }
42
- </ a >
43
- { menu . map ( ( level1 , i ) => ( [
44
- < span className = { styles . primaryLevel1Separator } key = { `separator-${ i } ` } /> ,
45
- /* Level 1 menu item */
42
+ < div >
43
+ < div className = { cn ( styles . primaryNavContainer , showLeftMenu && styles . primaryNavContainerOpen ) } >
44
+ < div className = { styles . primaryNav } ref = { createSetRef ( 'primaryNav' ) } >
46
45
< a
47
- className = { cn ( styles . primaryLevel1 , ! activeLevel2Id && level1 . id === activeLevel1Id && styles . primaryLevel1Open , level1 . mobileOnly && styles . mobileOnly ) }
48
- href = { level1 . href }
49
- key = { `level1-${ i } ` }
50
- onClick = { createHandleClickLevel1 ( level1 . id , true ) }
51
- ref = { createSetRef ( level1 . id ) }
46
+ className = { cn ( styles . tcLogo , collapsed && styles . tcLogoPush ) }
47
+ onClick = { onClickLogo }
48
+ href = '/'
52
49
>
53
- { level1 . title }
54
- </ a > ,
55
- /* Level 2 menu */
56
- level1 . subMenu && (
57
- < div
58
- className = { cn ( styles . primaryLevel2Container , level1 . id === activeLevel1Id && styles . primaryLevel2ContainerOpen ) }
59
- key = { `level2-${ i } -container` }
60
- ref = { createSetRef ( `level2Container${ i } ` ) }
50
+ { logo }
51
+ </ a >
52
+ { menu . map ( ( level1 , i ) => ( [
53
+ < span className = { styles . primaryLevel1Separator } key = { `separator-${ i } ` } /> ,
54
+ /* Level 1 menu item */
55
+ < a
56
+ className = { cn ( styles . primaryLevel1 , ! activeLevel2Id && level1 . id === activeLevel1Id && styles . primaryLevel1Open , level1 . mobileOnly && styles . mobileOnly ) }
57
+ href = { level1 . href }
58
+ key = { `level1-${ i } ` }
59
+ onClick = { createHandleClickLevel1 ( level1 . id , true ) }
60
+ ref = { createSetRef ( level1 . id ) }
61
61
>
62
- { level1 . subMenu . filter ( filterNotInMore ) . map ( ( level2 , i ) => (
63
- < a
64
- className = { cn ( styles . primaryLevel2 , level2 . id === activeLevel2Id && styles . primaryLevel2Open ) }
65
- href = { level2 . href }
66
- key = { `level2-${ i } ` }
67
- onClick = { createHandleClickLevel2 ( level2 . id , true ) }
68
- ref = { createSetRef ( level2 . id ) }
69
- >
70
- { level2 . title }
71
- </ a >
72
- ) ) }
73
- { /* The More menu */ }
74
- { level1 . id === activeLevel1Id && moreMenu && moreMenu . length > 0 && (
75
- < div className = { cn ( styles . moreBtnContainer , openMore && styles . moreOpen ) } >
76
- < div className = { styles . backdrop } onClick = { onCloseMore } />
77
- < button
78
- className = { cn ( styles . primaryLevel2 , styles . moreBtn ) }
79
- onClick = { handleClickMore }
80
- ref = { createSetRef ( moreId ) }
62
+ { level1 . title }
63
+ </ a > ,
64
+ /* Level 2 menu */
65
+ level1 . subMenu && (
66
+ < div
67
+ className = { cn ( styles . primaryLevel2Container , level1 . id === activeLevel1Id && styles . primaryLevel2ContainerOpen ) }
68
+ key = { `level2-${ i } -container` }
69
+ ref = { createSetRef ( `level2Container${ i } ` ) }
70
+ >
71
+ { level1 . subMenu . filter ( filterNotInMore ) . map ( ( level2 , i ) => (
72
+ < a
73
+ className = { cn ( styles . primaryLevel2 , level2 . id === activeLevel2Id && styles . primaryLevel2Open ) }
74
+ href = { level2 . href }
75
+ key = { `level2-${ i } ` }
76
+ onClick = { createHandleClickLevel2 ( level2 . id , true ) }
77
+ ref = { createSetRef ( level2 . id ) }
81
78
>
82
- < div className = { styles . moreBtnMask } />
83
- < span > More</ span >
84
- < IconArrowSmalldown />
85
- </ button >
86
- < div className = { styles . moreContentContainer } >
87
- { moreMenu . map ( ( menu , i ) => (
88
- < a
89
- className = { cn ( styles . primaryLevel2 , menu . id === activeLevel2Id && styles . primaryLevel2Open ) }
90
- href = { menu . href }
91
- key = { `more-item-${ i } ` }
92
- onClick = { createHandleClickMoreItem ( menu . id ) }
93
- >
94
- { menu . title }
95
- </ a >
96
- ) ) }
79
+ { level2 . title }
80
+ </ a >
81
+ ) ) }
82
+ { /* The More menu */ }
83
+ { level1 . id === activeLevel1Id && moreMenu && moreMenu . length > 0 && (
84
+ < div className = { cn ( styles . moreBtnContainer , openMore && styles . moreOpen ) } >
85
+ < div className = { styles . backdrop } onClick = { onCloseMore } />
86
+ < button
87
+ className = { cn ( styles . primaryLevel2 , styles . moreBtn ) }
88
+ onClick = { handleClickMore }
89
+ ref = { createSetRef ( moreId ) }
90
+ >
91
+ < div className = { styles . moreBtnMask } />
92
+ < span > More</ span >
93
+ < IconArrowSmalldown />
94
+ </ button >
95
+ < div className = { styles . moreContentContainer } >
96
+ { moreMenu . map ( ( menu , i ) => (
97
+ < a
98
+ className = { cn ( styles . primaryLevel2 , menu . id === activeLevel2Id && styles . primaryLevel2Open ) }
99
+ href = { menu . href }
100
+ key = { `more-item-${ i } ` }
101
+ onClick = { createHandleClickMoreItem ( menu . id ) }
102
+ >
103
+ { menu . title }
104
+ </ a >
105
+ ) ) }
106
+ </ div >
97
107
</ div >
98
- </ div >
99
- ) }
108
+ ) }
109
+ </ div >
110
+ )
111
+ ] ) ) }
112
+ < ChosenArrow show = { showChosenArrow } x = { chosenArrowX } />
113
+ </ div >
114
+ < div className = { styles . primaryNavRight } >
115
+ < ResizeDetector
116
+ handleWidth
117
+ onResize = { onRightMenuResize }
118
+ />
119
+ { rightMenu && (
120
+ < div className = { styles . primaryLevel1 } >
121
+ { rightMenu }
100
122
</ div >
101
- )
102
- ] ) ) }
103
- < ChosenArrow show = { showChosenArrow } x = { chosenArrowX } />
123
+ ) }
124
+ < div
125
+ aria-label = 'Find members by username or skill'
126
+ role = 'button'
127
+ tabIndex = { 0 }
128
+ data-menu = 'search'
129
+ className = { cn ( styles . searchIcon , { opened : searchOpened } ) }
130
+ onFocus = { ( ) => toggleSearchOpen ( true ) }
131
+ onBlur = { ( event ) => {
132
+ if ( event . pageY < activeTrigger . bottom ) {
133
+ toggleSearchOpen ( false )
134
+ }
135
+ } }
136
+ onMouseEnter = { ( event ) => toggleSearchOpen ( true ) }
137
+ onMouseLeave = { ( event ) => {
138
+ console . log ( `${ event . clientX } - ${ event . clientY } ` )
139
+ if ( event . pageY < activeTrigger . bottom ) {
140
+ toggleSearchOpen ( false )
141
+ }
142
+ } }
143
+ onTouchStart = { ( event ) => {
144
+ if ( searchOpened ) {
145
+ toggleSearchOpen ( false )
146
+ } else {
147
+ toggleSearchOpen ( true )
148
+ }
149
+ } }
150
+ >
151
+ < MagnifyingGlass />
152
+ </ div >
153
+ </ div >
104
154
</ div >
105
-
106
- < div className = { styles . primaryNavRight } >
107
- < ResizeDetector
108
- handleWidth
109
- onResize = { onRightMenuResize }
155
+ < div
156
+ role = 'search'
157
+ className = { cn ( styles . searchField , { opened : searchOpened , closed : ! searchOpened } ) }
158
+ onMouseLeave = { ( event ) => { toggleSearchOpen ( false ) } }
159
+ >
160
+ < input
161
+ ref = { createSetRef ( 'searchInputBox' ) }
162
+ onKeyPress = { ( event ) => {
163
+ if ( event . key === 'Enter' ) {
164
+ window . location = `${ BASE_URL } /search/members?q=${
165
+ encodeURIComponent ( event . target . value )
166
+ } `
167
+ }
168
+ } }
169
+ onBlur = { ( ) => toggleSearchOpen ( false ) }
170
+ aria-label = 'Find members by username or skill'
171
+ placeholder = 'Find members by username or skill'
110
172
/>
111
- { rightMenu && (
112
- < div className = { styles . primaryLevel1 } >
113
- { rightMenu }
114
- </ div >
115
- ) }
116
173
</ div >
117
174
</ div >
118
175
)
@@ -138,7 +195,9 @@ PrimaryNav.propTypes = {
138
195
createHandleClickMoreItem : PropTypes . func ,
139
196
createSetRef : PropTypes . func ,
140
197
showChosenArrow : PropTypes . bool ,
141
- chosenArrowX : PropTypes . number
198
+ chosenArrowX : PropTypes . number ,
199
+ searchOpened : PropTypes . bool ,
200
+ toggleSearchOpen : PropTypes . func
142
201
}
143
202
144
203
export default PrimaryNav
0 commit comments