1
1
import type { RoutePath } from '__generated__/routes.types' ;
2
2
import styled from '@emotion/styled' ;
3
+ import { motion } from 'framer-motion' ;
3
4
import { useBodyScrollLock } from 'hooks/useBodyScrollLock' ;
4
5
import useUserStore from 'hooks/useUserStore' ;
5
6
import { useState } from 'react' ;
@@ -38,7 +39,7 @@ const Nav = () => {
38
39
< source srcSet = "/images/logo.avif" type = "image/avif" />
39
40
< source srcSet = "/images/logo.webp" type = "image/webp" />
40
41
< source srcSet = "/images/logo.png" type = "image/png" />
41
- < NavLogo src = "/images/logo.png" alt = "수위키 로고" width = { 110 } height = { 30 } />
42
+ < NavLogo src = "/images/logo.png" alt = "수위키 로고" height = { 24 } />
42
43
</ picture >
43
44
</ LogoWrapper >
44
45
@@ -47,7 +48,34 @@ const Nav = () => {
47
48
aria-expanded = { isOpen }
48
49
aria-label = { isOpen ? '메뉴 닫기' : '메뉴 열기' }
49
50
>
50
- { isOpen ? < CloseIcon /> : < MenuIcon /> }
51
+ < MenuIconContainer >
52
+ < MenuLine
53
+ animate = { isOpen ? 'open' : 'closed' }
54
+ variants = { {
55
+ closed : { rotate : 0 , translateY : 0 } ,
56
+ open : { rotate : 45 , translateY : 7 } ,
57
+ } }
58
+ transition = { { duration : 0.3 } }
59
+ />
60
+
61
+ < MenuLine
62
+ animate = { isOpen ? 'open' : 'closed' }
63
+ variants = { {
64
+ closed : { opacity : 1 } ,
65
+ open : { opacity : 0 } ,
66
+ } }
67
+ transition = { { duration : 0.2 } }
68
+ />
69
+
70
+ < MenuLine
71
+ animate = { isOpen ? 'open' : 'closed' }
72
+ variants = { {
73
+ closed : { rotate : 0 , translateY : 0 } ,
74
+ open : { rotate : - 45 , translateY : - 7 } ,
75
+ } }
76
+ transition = { { duration : 0.3 } }
77
+ />
78
+ </ MenuIconContainer >
51
79
</ MenuButton >
52
80
53
81
< NavMenu isOpen = { isOpen } >
@@ -120,7 +148,6 @@ const NavMenu = styled.div<NavMenuProps>`
120
148
gap: 2rem;
121
149
122
150
@media screen and (max-width: 768px) {
123
- justify-content: center;
124
151
flex-direction: column;
125
152
width: 100%;
126
153
height: calc(100vh - 60px);
@@ -129,8 +156,9 @@ const NavMenu = styled.div<NavMenuProps>`
129
156
left: ${ ( { isOpen } ) => ( isOpen ? 0 : '-100%' ) } ;
130
157
transition: all 0.3s ease;
131
158
background: #ffffff;
132
- z-index: 999;
133
- padding: 2rem;
159
+ z-index: 10;
160
+ padding: 56px 8px;
161
+ gap: 16px;
134
162
}
135
163
` ;
136
164
@@ -150,39 +178,29 @@ const NavItem = styled.button<{ isHighlight?: boolean }>`
150
178
151
179
@media screen and (max-width: 768px) {
152
180
width: 100%;
153
- text-align: center ;
181
+ text-align: left ;
154
182
padding: 1rem;
183
+ font-size: 24px;
184
+ font-weight: 600;
155
185
}
156
186
` ;
157
187
158
- const CloseIcon = ( ) => (
159
- < svg
160
- stroke = "currentColor"
161
- fill = "currentColor"
162
- strokeWidth = "0"
163
- viewBox = "0 0 16 16"
164
- height = "1em"
165
- width = "1em"
166
- xmlns = "http://www.w3.org/2000/svg"
167
- >
168
- < path
169
- fillRule = "evenodd"
170
- clipRule = "evenodd"
171
- d = "M7.116 8l-4.558 4.558.884.884L8 8.884l4.558 4.558.884-.884L8.884 8l4.558-4.558-.884-.884L8 7.116 3.442 2.558l-.884.884L7.116 8z"
172
- />
173
- </ svg >
174
- ) ;
175
-
176
- const MenuIcon = ( ) => (
177
- < svg
178
- stroke = "currentColor"
179
- fill = "currentColor"
180
- strokeWidth = "0"
181
- viewBox = "0 0 512 512"
182
- height = "1em"
183
- width = "1em"
184
- xmlns = "http://www.w3.org/2000/svg"
185
- >
186
- < path d = "M32 96v64h448V96H32zm0 128v64h448v-64H32zm0 128v64h448v-64H32z" />
187
- </ svg >
188
- ) ;
188
+ const MenuIconContainer = styled . div `
189
+ width: 24px;
190
+ height: 24px;
191
+ display: flex;
192
+ flex-direction: column;
193
+ justify-content: space-between;
194
+ align-items: center;
195
+ position: relative;
196
+ padding: 4px 0;
197
+ ` ;
198
+
199
+ const MenuLine = styled ( motion . div ) `
200
+ width: 24px;
201
+ height: 2px;
202
+ background-color: black;
203
+ border-radius: 2px;
204
+ transform-origin: center;
205
+ position: relative;
206
+ ` ;
0 commit comments