1
1
// Import External Dependencies
2
2
import { useEffect , useState } from 'react' ;
3
- import Banner from 'react-banner' ;
4
3
import PropTypes from 'prop-types' ;
4
+ import { DocSearch } from '@docsearch/react' ;
5
+ import { Link as ReactDOMLink } from 'react-router-dom' ;
5
6
6
7
// Import Components
7
8
import Link from '../Link/Link' ;
8
9
import Logo from '../Logo/Logo' ;
9
10
import Dropdown from '../Dropdown/Dropdown' ;
10
11
11
- // Import helpers
12
- import isClient from '../../utilities/is-client' ;
13
-
14
- // Import constants
15
- import { THEME } from '../../constants/theme' ;
16
-
17
12
// Load Styling
18
- import 'docsearch.js/dist/cdn/docsearch.css' ;
19
- import './Navigation.scss' ;
20
- import './Search.scss' ;
13
+ import '@docsearch/css' ;
21
14
22
15
import GithubIcon from '../../styles/icons/github.svg' ;
23
16
import TwitterIcon from '../../styles/icons/twitter.svg' ;
24
17
import StackOverflowIcon from '../../styles/icons/stack-overflow.svg' ;
18
+ import Hamburger from '../../styles/icons/hamburger.svg' ;
19
+ import { NavLink , useLocation } from 'react-router-dom' ;
20
+ import HelloDarkness from '../HelloDarkness' ;
25
21
26
- const onSearch = ( ) => { } ;
27
- const { DARK , LIGHT } = THEME ;
22
+ NavigationItem . propTypes = {
23
+ children : PropTypes . node . isRequired ,
24
+ url : PropTypes . string . isRequired ,
25
+ isActive : PropTypes . func ,
26
+ } ;
27
+
28
+ function NavigationItem ( { children, url, isActive } ) {
29
+ let obj = { } ;
30
+ // decide if the link is active or not by providing a function
31
+ // otherwise we'll let react-dom makes the decision for us
32
+ if ( isActive ) {
33
+ obj = {
34
+ isActive,
35
+ } ;
36
+ }
37
+ return (
38
+ < NavLink
39
+ { ...obj }
40
+ activeClassName = "active-menu"
41
+ to = { url }
42
+ className = "text-gray-100 dark:text-gray-100 text-sm font-light uppercase hover:text-blue-200"
43
+ >
44
+ { children }
45
+ </ NavLink >
46
+ ) ;
47
+ }
48
+
49
+ NavigationIcon . propTypes = {
50
+ children : PropTypes . node . isRequired ,
51
+ to : PropTypes . string . isRequired ,
52
+ title : PropTypes . string . isRequired ,
53
+ } ;
54
+ function NavigationIcon ( { children, to, title } ) {
55
+ return (
56
+ < Link
57
+ to = { to }
58
+ className = "inline-flex items-center"
59
+ title = { `webpack on ${ title } ` }
60
+ >
61
+ { children }
62
+ </ Link >
63
+ ) ;
64
+ }
65
+ const navigationIconProps = {
66
+ 'aria-hidden' : true ,
67
+ fill : '#fff' ,
68
+ width : 16 ,
69
+ } ;
28
70
29
71
Navigation . propTypes = {
30
72
pathname : PropTypes . string ,
@@ -35,66 +77,62 @@ Navigation.propTypes = {
35
77
switchTheme : PropTypes . func ,
36
78
} ;
37
79
38
- function Navigation ( {
39
- pathname,
40
- hash = '' ,
41
- links,
42
- toggleSidebar,
43
- theme,
44
- switchTheme,
45
- } ) {
46
- const themeSwitcher = ( ) => switchTheme ( theme === DARK ? LIGHT : DARK ) ;
80
+ function Navigation ( { links, pathname, hash = '' , toggleSidebar } ) {
47
81
const [ locationHash , setLocationHash ] = useState ( hash ) ;
48
82
49
- useEffect ( ( ) => {
50
- if ( isClient ) {
51
- const DocSearch = require ( 'docsearch.js' ) ;
52
-
53
- DocSearch ( {
54
- apiKey : 'fac401d1a5f68bc41f01fb6261661490' ,
55
- indexName : 'webpack-js-org' ,
56
- inputSelector : '.navigation-search__input' ,
57
- } ) ;
58
- }
59
- } , [ ] ) ;
83
+ const location = useLocation ( ) ;
60
84
61
85
useEffect ( ( ) => {
62
86
setLocationHash ( hash ) ;
63
87
} , [ hash ] ) ;
64
88
65
89
return (
66
- < Banner
67
- onSearch = { onSearch }
68
- blockName = "navigation"
69
- logo = { < Logo light = { true } /> }
70
- url = { pathname }
71
- items = { [
72
- ...links ,
73
- {
74
- title : 'GitHub Repository' ,
75
- url : 'https://github.com/webpack/webpack' ,
76
- className : 'navigation__item--icon' ,
77
- content : < GithubIcon aria-hidden = "true" fill = "#fff" width = { 16 } /> ,
78
- } ,
79
- {
80
- title : 'webpack on Twitter' ,
81
- url : 'https://twitter.com/webpack' ,
82
- className : 'navigation__item--icon' ,
83
- content : < TwitterIcon aria-hidden = "true" fill = "#fff" width = { 16 } /> ,
84
- } ,
85
- {
86
- title : 'webpack on Stack Overflow' ,
87
- url : 'https://stackoverflow.com/questions/tagged/webpack' ,
88
- className : 'navigation__item--icon' ,
89
- content : (
90
- < StackOverflowIcon aria-hidden = "true" fill = "#fff" width = { 16 } />
91
- ) ,
92
- } ,
93
- {
94
- className : 'navigation__item--icon' ,
95
- content : (
90
+ < >
91
+ < header className = "bg-blue-800 dark:bg-gray-900" >
92
+ < div className = "flex items-center py-10 px-[16px] justify-between md:px-[24px] md:max-w-[1024px] md:mx-auto md:justify-start" >
93
+ < button
94
+ className = "bg-transparent border-none md:hidden"
95
+ onClick = { toggleSidebar }
96
+ >
97
+ < Hamburger
98
+ width = { 20 }
99
+ height = { 20 }
100
+ className = "fill-current text-white"
101
+ />
102
+ </ button >
103
+ < Link to = "/" className = "md:mr-auto" >
104
+ < Logo />
105
+ </ Link >
106
+ < nav className = "hidden md:inline-grid md:grid-flow-col md:gap-x-[18px]" >
107
+ { links . map ( ( { content, url, isActive } ) => (
108
+ < NavigationItem key = { url } url = { url } isActive = { isActive } >
109
+ { content }
110
+ </ NavigationItem >
111
+ ) ) }
112
+ { [
113
+ {
114
+ to : 'https://github.com/webpack/webpack' ,
115
+ title : 'GitHub' ,
116
+ children : < GithubIcon { ...navigationIconProps } /> ,
117
+ } ,
118
+ {
119
+ to : 'https://twitter.com/webpack' ,
120
+ title : 'Twitter' ,
121
+ children : < TwitterIcon { ...navigationIconProps } /> ,
122
+ } ,
123
+ {
124
+ to : 'https://stackoverflow.com/questions/tagged/webpack' ,
125
+ title : 'StackOverflow' ,
126
+ children : < StackOverflowIcon { ...navigationIconProps } /> ,
127
+ } ,
128
+ ] . map ( ( { to, title, children } ) => (
129
+ < NavigationIcon key = { to } to = { to } title = { title } >
130
+ { children }
131
+ </ NavigationIcon >
132
+ ) ) }
133
+
96
134
< Dropdown
97
- className = "navigation__languages "
135
+ className = ""
98
136
items = { [
99
137
{
100
138
title : 'English' ,
@@ -112,28 +150,68 @@ function Navigation({
112
150
} ,
113
151
] }
114
152
/>
115
- ) ,
116
- } ,
117
- {
118
- className : 'navigation__item--icon' ,
119
- content : (
120
- < button
121
- style = { {
122
- background : 'transparent' ,
123
- border : 'none' ,
124
- cursor : 'pointer' ,
153
+ </ nav >
154
+ < div className = "inline-flex items-center ml-[18px]" >
155
+ < HelloDarkness />
156
+ < DocSearch
157
+ apiKey = { 'fac401d1a5f68bc41f01fb6261661490' }
158
+ indexName = "webpack-js-org"
159
+ disableUserPersonalization = { true }
160
+ placeholder = "Search webpack documentation"
161
+ transformItems = { ( items ) =>
162
+ items . map ( ( { url, ...others } ) => {
163
+ const { origin } = new URL ( url ) ;
164
+ return {
165
+ ...others ,
166
+ url : url . replace ( new RegExp ( `^${ origin } ` ) , '' ) ,
167
+ } ;
168
+ } )
169
+ }
170
+ hitComponent = { ( { hit, children } ) => {
171
+ return < ReactDOMLink to = { hit . url } > { children } </ ReactDOMLink > ;
125
172
} }
126
- onClick = { themeSwitcher }
127
- data-testid = "hello-darkness"
128
- >
129
- { theme === DARK ? '🌙' : '☀️' }
130
- </ button >
131
- ) ,
132
- } ,
133
- ] }
134
- link = { Link }
135
- onMenuClick = { toggleSidebar }
136
- />
173
+ />
174
+ </ div >
175
+ </ div >
176
+ { /* sub navigation */ }
177
+ { links
178
+ . filter ( ( link ) => {
179
+ // only those with children are displayed
180
+ return link . children ;
181
+ } )
182
+ . map ( ( link ) => {
183
+ if ( link . isActive ) {
184
+ // hide the children if the link is not active
185
+ if ( ! link . isActive ( { } , location ) ) {
186
+ return null ;
187
+ }
188
+ }
189
+ return (
190
+ < div
191
+ key = { link . url }
192
+ className = "bg-gray-100 dark:bg-gray-800 hidden md:block"
193
+ >
194
+ < div
195
+ className = "md:max-w-[1024px] md:mx-auto md:grid md:grid-flow-col md:justify-end md:gap-x-[20px] md:px-[24px]"
196
+ data-testid = "sub-navigation"
197
+ >
198
+ { link . children . map ( ( child ) => (
199
+ < NavLink
200
+ key = { child . url }
201
+ to = { child . url }
202
+ title = { child . title }
203
+ className = "text-blue-400 py-5 text-sm capitalize"
204
+ activeClassName = "active-submenu"
205
+ >
206
+ { child . content }
207
+ </ NavLink >
208
+ ) ) }
209
+ </ div >
210
+ </ div >
211
+ ) ;
212
+ } ) }
213
+ </ header >
214
+ </ >
137
215
) ;
138
216
}
139
217
0 commit comments