@@ -11,8 +11,8 @@ import LanguageSelector from "@apps/pyconkr-2026/components/layout/LanguageSelec
1111import { UserMenuButton } from "@apps/pyconkr-2026/components/layout/UserMenuButton" ;
1212import { useAppContext } from "@apps/pyconkr-2026/contexts/app_context" ;
1313
14- import { MobileHeader } from "./Mobile/MobileHeader" ;
1514import { PyConLogo } from "../../pycon_logo" ;
15+ import { MobileHeader } from "./Mobile/MobileHeader" ;
1616
1717type MenuType = NestedSiteMapSchema ;
1818type MenuOrUndefinedType = MenuType | undefined ;
@@ -43,7 +43,9 @@ export default function Header() {
4343
4444 useEffect ( resetDepths , [ language ] ) ;
4545
46- if ( isMobile ) return < MobileHeader /> ;
46+ if ( isMobile ) {
47+ return < MobileHeader /> ;
48+ }
4749
4850 let breadCrumbRoute = "" ;
4951 let breadCrumbArray = currentSiteMapDepth . slice ( 1 , - 1 ) ;
@@ -52,13 +54,7 @@ export default function Header() {
5254 const headerStyle : SxProps < Theme > = shouldShowTitleBanner ? { } : { backgroundColor : "transparent" } ;
5355
5456 return (
55- < Box
56- sx = { {
57- position : "relative" ,
58- "&:has(.nav-dropdown:hover) .header-title-text" : { opacity : 1 } ,
59- } }
60- onMouseLeave = { resetDepths }
61- >
57+ < Box sx = { { position : "relative" } } onMouseLeave = { resetDepths } >
6258 < HeaderContainer sx = { headerStyle } >
6359 < HeaderInner >
6460 < NavSideElementContainer >
@@ -71,7 +67,6 @@ export default function Header() {
7167 </ Stack >
7268 </ Link >
7369 </ NavSideElementContainer >
74-
7570 { siteMapNode ? (
7671 < Stack direction = "row" alignItems = "center" justifyContent = "center" spacing = { 0.5 } >
7772 { Object . values ( siteMapNode . children )
@@ -107,20 +102,20 @@ export default function Header() {
107102 </ HeaderContainer >
108103
109104 { navState . depth1 && (
110- < NavDropdownOuter className = "nav-dropdown" >
111- < NavDropdownInner >
112- < Typography variant = "h2" sx = { { fontSize : "1.5rem" , fontWeight : 700 , color : "#ededde" } } >
105+ < NavOuterContainer >
106+ < NavInnerContainer >
107+ < Typography variant = "h2" sx = { { fontSize : "1.5rem" , fontWeight : 700 } } >
113108 { navState . depth1 . name }
114109 </ Typography >
115- < HighlightDivider flexItem />
110+ < Depth1to2Divider flexItem />
116111 < Stack direction = "row" spacing = { 4 } >
117112 < Stack spacing = { 1.25 } >
118113 { Object . values ( navState . depth1 . children )
119114 . filter ( ( s ) => ! s . hide )
120115 . map ( ( r ) => (
121116 < Depth2Item
122- key = { r . id }
123117 className = { r . id === navState . depth2 ?. id ? "active" : "" }
118+ key = { r . id }
124119 onClick = { resetDepths }
125120 onMouseEnter = { ( ) => setDepth2 ( r ) }
126121 onMouseLeave = { ( ) => isEmpty ( navState . depth2 ?. children ?? { } ) && setDepth2 ( undefined ) }
@@ -136,14 +131,15 @@ export default function Header() {
136131
137132 { navState . depth2 && ! isEmpty ( navState . depth2 . children ) && (
138133 < >
139- < Depth2to3Divider orientation = "vertical" flexItem />
134+ { ! isEmpty ( navState . depth2 . children ) && < Depth2to3Divider orientation = "vertical" flexItem /> }
135+
140136 < Stack spacing = { 1.5 } >
141137 { Object . values ( navState . depth2 . children )
142138 . filter ( ( s ) => ! s . hide )
143139 . map ( ( r ) => (
144140 < Depth3Item
145- key = { r . id }
146141 className = { r . id === navState . depth3 ?. id ? "active" : "" }
142+ key = { r . id }
147143 onClick = { resetDepths }
148144 onMouseEnter = { ( ) => setDepth3 ( r ) }
149145 onMouseLeave = { ( ) => setDepth3 ( undefined ) }
@@ -159,11 +155,10 @@ export default function Header() {
159155 </ >
160156 ) }
161157 </ Stack >
162- </ NavDropdownInner >
163- </ NavDropdownOuter >
158+ </ NavInnerContainer >
159+ </ NavOuterContainer >
164160 ) }
165-
166- { shouldShowTitleBanner && (
161+ { shouldShowTitleBanner ? (
167162 < >
168163 < BreadCrumbContainer >
169164 < BreadCrumbInner >
@@ -185,18 +180,28 @@ export default function Header() {
185180 </ Typography >
186181 </ BreadCrumbInner >
187182 </ BreadCrumbContainer >
183+ { /* Spacer for fixed header */ }
188184 < Box sx = { { height : `calc(${ HeaderHeight } + ${ BreadCrumbHeight } )` } } />
189185 </ >
186+ ) : (
187+ < Box sx = { { height : HeaderHeight } } />
190188 ) }
191189 </ Box >
192190 ) ;
193191}
194192
195- const ResponsivePadding = ( { theme } : MUIStyledCommonProps ) => ( {
193+ const ResponsivePaddingDefinition = ( { theme } : MUIStyledCommonProps ) => ( {
196194 paddingRight : theme ! . spacing ( 16 ) ,
197195 paddingLeft : theme ! . spacing ( 16 ) ,
198- [ theme ! . breakpoints . down ( "lg" ) ] : { paddingRight : theme ! . spacing ( 4 ) , paddingLeft : theme ! . spacing ( 4 ) } ,
199- [ theme ! . breakpoints . down ( "sm" ) ] : { paddingRight : theme ! . spacing ( 2 ) , paddingLeft : theme ! . spacing ( 2 ) } ,
196+
197+ [ theme ! . breakpoints . down ( "lg" ) ] : {
198+ paddingRight : theme ! . spacing ( 4 ) ,
199+ paddingLeft : theme ! . spacing ( 4 ) ,
200+ } ,
201+ [ theme ! . breakpoints . down ( "sm" ) ] : {
202+ paddingRight : theme ! . spacing ( 2 ) ,
203+ paddingLeft : theme ! . spacing ( 2 ) ,
204+ } ,
200205} ) ;
201206
202207const HeaderContainer = styled ( "header" ) ( ( { theme } ) => ( {
@@ -207,12 +212,13 @@ const HeaderContainer = styled("header")(({ theme }) => ({
207212 backdropFilter : "blur(12px)" ,
208213 WebkitBackdropFilter : "blur(12px)" ,
209214 borderBottom : "1px solid rgba(237, 94, 189, 0.2)" ,
210- color : "#ededde" ,
215+ color : theme . palette . text . primary ,
216+
211217 fontWeight : 500 ,
218+
212219 zIndex : theme . zIndex . appBar ,
213220 transition : "background-color 0.3s ease-in-out" ,
214221 "& .header-title-text" : {
215- // TODO: FIXME: HeaderInner의 좌측 정렬 모드를 중앙 정렬("1fr auto 1fr")로 되돌릴 때 opacity를 다시 0으로 변경할 것 (hover 시에만 노출되는 원래 동작 복귀)
216222 opacity : 1 ,
217223 transition : "opacity 0.2s ease" ,
218224 } ,
@@ -223,84 +229,90 @@ const HeaderContainer = styled("header")(({ theme }) => ({
223229
224230const HeaderInner = styled ( "div" ) ( ( { theme } ) => ( {
225231 display : "grid" ,
226- // TODO: FIXME: sitemap 항목이 충분히 등록되면 gridTemplateColumns를 "1fr auto 1fr"로 되돌려 중앙 정렬로 복귀하고, columnGap도 제거할 것
227- gridTemplateColumns : "auto auto 1fr" ,
228- columnGap : theme . spacing ( 2 ) ,
232+ gridTemplateColumns : "1fr auto 1fr" ,
229233 alignItems : "center" ,
230234 width : "100%" ,
231235 height : "100%" ,
232236 maxWidth : MaxContentWidth ,
233237 marginInline : "auto" ,
234- ...ResponsivePadding ( { theme } ) ,
238+ ...ResponsivePaddingDefinition ( { theme } ) ,
235239} ) ) ;
236240
237- const NavButton = styled ( Button ) < { isActive ?: boolean } > ( ( { isActive } ) => ( {
238- color : isActive ? "#ed5ebd" : "#ededde" ,
241+ const NavButton = styled ( Button ) < { isActive ?: boolean } > ( ( { theme , isActive } ) => ( {
242+ color : isActive ? theme . palette . primary . main : theme . palette . text . primary ,
239243 minWidth : 0 ,
240244 textTransform : "none" ,
241245 fontSize : "0.9rem" ,
242246 fontWeight : isActive ? 700 : 400 ,
243247 transition : "color 0.2s ease" ,
244- "&:hover" : { color : "#ed5ebd" , backgroundColor : "transparent" } ,
248+ "&:hover" : { color : theme . palette . primary . main , backgroundColor : "transparent" } ,
245249} ) ) ;
246250
247251const NavSideElementContainer = styled ( Stack ) ( {
248252 flexDirection : "row" ,
249253 alignItems : "center" ,
250254} ) ;
251255
252- const NavDropdownOuter = styled ( Stack ) ( ( { theme } ) => ( {
256+ const NavOuterContainer = styled ( Stack ) ( ( { theme } ) => ( {
253257 width : "100vw" ,
258+
254259 position : "fixed" ,
255260 left : 0 ,
256261 top : HeaderHeight ,
262+
257263 zIndex : theme . zIndex . appBar + 1 ,
264+
258265 backgroundColor : "rgba(18, 9, 30, 0.95)" ,
259266 boxShadow : "0 5px 20px rgba(0, 0, 0, 0.4)" ,
260267 backdropFilter : "blur(12px)" ,
268+
261269 WebkitBackdropFilter : "blur(12px)" ,
262270 borderBottom : "1px solid rgba(237, 94, 189, 0.2)" ,
263271} ) ) ;
264272
265- const NavDropdownInner = styled ( Stack ) ( ( { theme } ) => ( {
273+ const NavInnerContainer = styled ( Stack ) ( ( { theme } ) => ( {
266274 width : "100%" ,
267275 maxWidth : MaxContentWidth ,
268276 marginInline : "auto" ,
269277 minHeight : "10rem" ,
270278 overflowY : "auto" ,
271279 gap : "1rem" ,
280+
272281 paddingTop : "1.5rem" ,
273282 paddingBottom : "2rem" ,
274- color : "#ededde" ,
275- ...ResponsivePadding ( { theme } ) ,
283+
284+ ...ResponsivePaddingDefinition ( { theme } ) ,
276285} ) ) ;
277286
278- const HighlightDivider = styled ( Divider ) ( {
287+ const Depth1to2Divider = styled ( Divider ) ( ( { theme } ) => ( {
279288 width : "3rem" ,
280- borderBottom : "4px solid #f5c73d" ,
281- borderColor : "#f5c73d" ,
282- } ) ;
289+ borderBottom : `4px solid ${ theme . palette . highlight . main } ` ,
290+ } ) ) ;
283291
284- const Depth2Item = styled ( Link ) ( {
285- display : "inline-flex" ,
286- alignItems : "center" ,
287- gap : "0.25rem" ,
288- color : "#ededde" ,
292+ const Depth2Item = styled ( Link ) ( ( { theme } ) => ( {
293+ color : theme . palette . text . primary ,
289294 fontWeight : 300 ,
290295 textDecoration : "none" ,
291296 width : "fit-content" ,
292297 borderBottom : "2px solid transparent" ,
293- transition : "color 0.15s ease" ,
294- "&.active" : { fontWeight : 700 , borderBottom : "2px solid #ed5ebd" , color : "#ed5ebd" } ,
295- "&:hover" : { color : "#ed5ebd" } ,
296- } ) ;
298+
299+ "&.active" : {
300+ fontWeight : 700 ,
301+ borderBottom : `2px solid ${ theme . palette . primary . main } ` ,
302+ color : theme . palette . primary . main ,
303+ } ,
304+ "&:hover" : {
305+ color : theme . palette . primary . main ,
306+ } ,
307+ } ) ) ;
297308
298309const Depth2to3Divider = styled ( Divider ) ( { borderColor : "rgba(237, 94, 189, 0.3)" } ) ;
299310
300311const Depth3Item = styled ( Depth2Item ) ( { fontSize : "0.75rem" } ) ;
301312
302- const BreadCrumbContainer = styled ( "div" ) ( ( { theme } ) => ( {
313+ const BreadCrumbContainer = styled ( Stack ) ( ( { theme } ) => ( {
303314 position : "fixed" ,
315+
304316 top : HeaderHeight ,
305317 width : "100%" ,
306318 height : BreadCrumbHeight ,
@@ -320,12 +332,17 @@ const BreadCrumbInner = styled(Stack)(({ theme }) => ({
320332 gap : "0.25rem" ,
321333 justifyContent : "center" ,
322334 alignItems : "flex-start" ,
323- ...ResponsivePadding ( { theme } ) ,
335+
336+ ...ResponsivePaddingDefinition ( { theme } ) ,
337+
324338 "& a" : {
325- color : "#f5c73d" ,
339+ color : theme . palette . highlight . main ,
326340 fontWeight : 300 ,
327341 fontSize : "0.75rem" ,
328342 textDecoration : "none" ,
329- "&:hover" : { textDecoration : "underline" } ,
343+
344+ "&:hover" : {
345+ textDecoration : "underline" ,
346+ } ,
330347 } ,
331348} ) ) ;
0 commit comments