1
- import { useState } from 'react' ;
1
+ import React , { useEffect , useState } from 'react' ;
2
2
import classNames from 'classnames' ;
3
3
import dynamic from 'next/dynamic' ;
4
- import { Noto_Sans_KR } from 'next/font/google' ;
5
4
import Link from 'next/link' ;
6
5
import { useRouter } from 'next/router' ;
7
6
import { FaGithub } from 'react-icons/fa' ;
8
7
import Icon from '../icons' ;
9
- import { Item } from './Item' ;
10
8
import styles from './NavigationBar.module.scss' ;
11
9
12
10
const ThemeToggleButton = dynamic ( ( ) => import ( './ThemeToggleButton' ) , {
13
11
ssr : false ,
14
12
} ) ;
15
13
16
- const notoSans = Noto_Sans_KR ( {
17
- weight : '500' ,
18
- style : [ 'normal' ] ,
19
- subsets : [ 'latin' ] ,
20
- } ) ;
21
-
22
14
// TODO - show floating menu button when display size is under sm
23
15
const NavigationBar = ( ) => {
24
16
const [ isOpen , setIsOpen ] = useState ( false ) ;
@@ -55,30 +47,10 @@ const NavigationBar = () => {
55
47
'mx-auto'
56
48
) }
57
49
>
58
- < div
59
- className = { classNames (
60
- 'left' ,
61
- 'flex' ,
62
- 'items-center' ,
63
- 'gap-2' ,
64
- 'sm:gap-0'
65
- ) }
66
- >
67
- < Link
68
- className = { classNames ( notoSans . className , styles . title ) }
69
- href = "/"
70
- >
71
- BenLog
72
- </ Link >
73
- </ div >
74
- < div className = { classNames ( 'hidden' , 'sm:flex' ) } >
75
- < ThemeToggleButton />
76
- < NavigationLinks />
77
- </ div >
78
- < div className = { classNames ( 'flex' , 'sm:hidden' ) } >
79
- < ThemeToggleButton />
80
- < Icon type = "hamburger" onClick = { toggleHamburgerIcon } />
81
- </ div >
50
+ < Left />
51
+ < Middle />
52
+ < Right />
53
+ < Hidden onClick = { toggleHamburgerIcon } />
82
54
</ div >
83
55
{ /** hidden part of NavigationBar */ }
84
56
{ isOpen ? (
@@ -92,32 +64,174 @@ const NavigationBar = () => {
92
64
93
65
export default NavigationBar ;
94
66
95
- const NavigationLinks = ( ) => {
67
+ const Left = ( ) => {
68
+ return (
69
+ < div
70
+ className = { classNames (
71
+ 'left' ,
72
+ 'flex' ,
73
+ 'items-center' ,
74
+ 'gap-2' ,
75
+ 'sm:gap-0'
76
+ ) }
77
+ >
78
+ < Logo />
79
+ </ div >
80
+ ) ;
81
+ } ;
82
+
83
+ const Logo = ( ) => {
84
+ return (
85
+ < Link
86
+ className = { classNames ( styles . title ) }
87
+ href = "/"
88
+ style = { { fontFamily : 'Noto Sans KR' } }
89
+ >
90
+ BenLog
91
+ </ Link >
92
+ ) ;
93
+ } ;
94
+
95
+ const Right = ( ) => {
96
+ return (
97
+ < div className = { classNames ( 'hidden' , 'sm:flex' ) } >
98
+ < ThemeToggleButton />
99
+ < NavigationLinks />
100
+ </ div >
101
+ ) ;
102
+ } ;
103
+
104
+ const Middle = ( ) => {
96
105
const router = useRouter ( ) ;
106
+ const [ isShowing , setIsShowing ] = useState ( false ) ;
107
+ const [ postTitle , setPostTitle ] = useState ( '' ) ;
108
+
109
+ useEffect ( ( ) => {
110
+ const isPostPath = getSubDomain ( router . pathname ) === 'posts' ;
111
+ setIsShowing ( isPostPath ) ;
112
+ } , [ router . pathname ] ) ;
113
+
114
+ useEffect ( ( ) => {
115
+ const handler = ( ) => {
116
+ const title = document . querySelector ( '.post-title' ) ;
117
+
118
+ if ( ! title ) return ;
119
+
120
+ setPostTitle ( title . textContent || '' ) ;
121
+ } ;
122
+
123
+ handler ( ) ;
124
+
125
+ router . events . on ( 'routeChangeComplete' , handler ) ;
126
+
127
+ return ( ) => {
128
+ router . events . off ( 'routeChangeComplete' , handler ) ;
129
+ } ;
130
+ } , [ router . events ] ) ;
131
+
97
132
return (
98
- < >
99
- < Link
100
- className = { classNames ( 'w-full' , 'text-center' , 'flex' , 'items-center' ) }
101
- href = "/posts"
102
- >
103
- < Item current = { getSubDomain ( router . pathname ) === 'posts' } > Posts</ Item >
104
- </ Link >
105
- < Link
106
- className = { classNames ( 'w-full' , 'text-center' , 'flex' , 'items-center' ) }
107
- href = "/about"
108
- >
109
- < Item current = { getSubDomain ( router . pathname ) === 'posts' } > About</ Item >
110
- </ Link >
133
+ < div
134
+ className = { classNames (
135
+ 'hidden' ,
136
+ 'md:flex' ,
137
+ 'flex-col' ,
138
+ 'justify-center' ,
139
+ 'items-center' ,
140
+ 'w-full' ,
141
+ 'text-center'
142
+ ) }
143
+ >
144
+ { postTitle }
145
+ </ div >
146
+ ) ;
147
+ } ;
148
+
149
+ interface HiddenComponentProps {
150
+ onClick ?: React . MouseEventHandler < HTMLDivElement > ;
151
+ }
152
+
153
+ const Hidden = ( { onClick } : HiddenComponentProps ) => {
154
+ return (
155
+ < div className = { classNames ( 'flex' , 'sm:hidden' ) } >
156
+ < ThemeToggleButton />
157
+ < Icon type = "hamburger" onClick = { onClick } />
158
+ </ div >
159
+ ) ;
160
+ } ;
161
+
162
+ interface NavigationLinkProps {
163
+ href : string ;
164
+ children ?: React . ReactNode ;
165
+ }
166
+
167
+ const getPathname = ( href : string ) => {
168
+ if ( href [ 0 ] !== '/' ) {
169
+ return href ;
170
+ }
171
+
172
+ return href . slice ( 1 ) ;
173
+ } ;
174
+
175
+ const NavigationLink = ( { href, children } : NavigationLinkProps ) => {
176
+ const router = useRouter ( ) ;
177
+ const pathname = getPathname ( href ) ;
178
+ const isExternalLink = href === pathname ;
179
+
180
+ return (
181
+ < li className = { classNames ( 'w-full' , 'text-center' , 'flex' , 'items-center' ) } >
111
182
< Link
112
- className = { classNames ( 'w-full' , 'text-center' , 'flex' , 'items-center' ) }
113
- href = "https://github.com/mrbartrns"
114
- rel = "noopener noreferrer"
115
- target = "_blank"
183
+ href = { href }
184
+ rel = { isExternalLink ? 'noopener noreferrer' : undefined }
185
+ target = { isExternalLink ? '_blank' : undefined }
186
+ title = { typeof children === 'string' ? children : pathname }
187
+ className = { classNames (
188
+ 'flex' ,
189
+ 'justify-center' ,
190
+ 'items-center' ,
191
+ 'w-full' ,
192
+ 'select-none' ,
193
+ 'transition-all' ,
194
+ 'py-1' ,
195
+ 'px-2' ,
196
+ 'font-medium' ,
197
+ 'text-zinc-600' ,
198
+ 'dark:text-zinc-300' ,
199
+ {
200
+ 'text-zinc-800' : getSubDomain ( router . pathname ) === pathname ,
201
+ 'dark:text-zinc-100' : getSubDomain ( router . pathname ) === pathname ,
202
+ } ,
203
+ 'hover:text-zinc-800' ,
204
+ 'dark:hover:text-zinc-100'
205
+ ) }
116
206
>
117
- < Item >
118
- < FaGithub className = { classNames ( 'text-xl' ) } />
119
- </ Item >
207
+ { children }
120
208
</ Link >
209
+ </ li >
210
+ ) ;
211
+ } ;
212
+
213
+ const NavigationLinks = ( ) => {
214
+ const links = [
215
+ {
216
+ href : '/posts' ,
217
+ children : 'Posts' ,
218
+ } ,
219
+ {
220
+ href : '/about' ,
221
+ children : 'About' ,
222
+ } ,
223
+ {
224
+ href : 'https://github.com/mrbartrns' ,
225
+ children : < FaGithub className = { classNames ( 'text-xl' ) } /> ,
226
+ } ,
227
+ ] ;
228
+ return (
229
+ < >
230
+ { links . map ( ( link ) => (
231
+ < NavigationLink key = { link . href } href = { link . href } >
232
+ { link . children }
233
+ </ NavigationLink >
234
+ ) ) }
121
235
</ >
122
236
) ;
123
237
} ;
0 commit comments