@@ -12,7 +12,7 @@ import { IconMenu2, IconX } from "@tabler/icons-react"
1212import { AnimatePresence , m as motion } from "motion/react"
1313import Image from "next/image"
1414import Link from "next/link"
15- import React , { useEffect , useRef , useState } from "react"
15+ import React , { useEffect , useLayoutEffect , useRef , useState } from "react"
1616import { useWebHaptics } from "web-haptics/react"
1717import { NavigationLink } from "./NavigationLink"
1818import { NavigationMobileItem } from "./NavigationMobileItem"
@@ -26,10 +26,12 @@ type NavigationMobileProps = {
2626const NavigationMobile : React . FC < NavigationMobileProps > = ( { locale, items, buttons } ) => {
2727 const { trigger } = useWebHaptics ( )
2828 const menuRef = useOutsideClick < HTMLElement > ( ( ) => setIsOpen ( false ) )
29+ const rootRef = useRef < HTMLDivElement > ( null )
2930 const wasOpenRef = useRef ( false )
3031 const [ isOpen , setIsOpen ] = useState ( false )
3132 const [ mobileOpenKey , setMobileOpenKey ] = useState < string | null > ( null )
3233 const [ isMenuClosing , setIsMenuClosing ] = useState ( false )
34+ const [ shellInsetWidth , setShellInsetWidth ] = useState ( 0 )
3335 const { homeHref, navbarItems, navbarButtons } = useNavigationViewModel ( locale , items , buttons )
3436 const menuTransition = {
3537 duration : 0.34 ,
@@ -43,6 +45,18 @@ const NavigationMobile: React.FC<NavigationMobileProps> = ({ locale, items, butt
4345 const isScrolled = useNavigationScrollState ( {
4446 onScroll : ( ) => setIsOpen ( ( prevIsOpen ) => ( prevIsOpen ? false : prevIsOpen ) ) ,
4547 } )
48+ const expandedHeaderPadding = 8
49+ const shellInset = isScrolled && ! isShellExpanded ? shellInsetWidth : 0
50+ const headerInlinePadding = isShellExpanded
51+ ? expandedHeaderPadding
52+ : isScrolled
53+ ? shellInsetWidth
54+ : 0
55+ const headerRightPadding = isShellExpanded
56+ ? expandedHeaderPadding
57+ : isScrolled
58+ ? shellInsetWidth + expandedHeaderPadding
59+ : 0
4660
4761 useEffect ( ( ) => {
4862 let timeoutId : ReturnType < typeof setTimeout > | undefined
@@ -63,6 +77,26 @@ const NavigationMobile: React.FC<NavigationMobileProps> = ({ locale, items, butt
6377 }
6478 } , [ isOpen ] )
6579
80+ useLayoutEffect ( ( ) => {
81+ const element = rootRef . current
82+
83+ if ( ! element ) {
84+ setShellInsetWidth ( 0 )
85+ return
86+ }
87+
88+ const measure = ( ) => {
89+ setShellInsetWidth ( element . clientWidth * 0.1 )
90+ }
91+
92+ measure ( )
93+
94+ const resizeObserver = new ResizeObserver ( measure )
95+ resizeObserver . observe ( element )
96+
97+ return ( ) => resizeObserver . disconnect ( )
98+ } , [ ] )
99+
66100 const closeMenu = ( ) => {
67101 trigger ( "medium" )
68102 setIsOpen ( false )
@@ -75,26 +109,25 @@ const NavigationMobile: React.FC<NavigationMobileProps> = ({ locale, items, butt
75109 ref = { menuRef }
76110 >
77111 < Container >
78- < div className = "relative my-6" >
112+ < div ref = { rootRef } className = "relative my-6" >
79113 < motion . div
80114 className = { cn (
81115 "pointer-events-none absolute inset-0 rounded-2xl shadow-sm" ,
82116 ( isScrolled || isShellExpanded ) ? "bg-primary/50 backdrop-blur-lg" : "bg-transparent shadow-none" ,
83117 ) }
84118 initial = { false }
85119 animate = { {
86- clipPath : isScrolled && ! isShellExpanded
87- ? "inset(0% 10% 0% 10% round 1rem)"
88- : "inset(0% 0% 0% 0% round 1rem)" ,
120+ left : shellInset ,
121+ right : shellInset ,
89122 } }
90123 transition = { shellTransition }
91124 />
92125 < motion . div
93126 className = "pointer-events-none absolute inset-0 z-10 rounded-2xl border border-white/5"
94127 initial = { false }
95128 animate = { {
96- left : isScrolled && ! isShellExpanded ? "10%" : "0%" ,
97- right : isScrolled && ! isShellExpanded ? "10%" : "0%" ,
129+ left : shellInset ,
130+ right : shellInset ,
98131 opacity : isScrolled || isShellExpanded ? 1 : 0 ,
99132 } }
100133 transition = { shellTransition }
@@ -107,8 +140,8 @@ const NavigationMobile: React.FC<NavigationMobileProps> = ({ locale, items, butt
107140 className = { "w-full flex items-center justify-between gap-2" }
108141 initial = { false }
109142 animate = { {
110- paddingLeft : isScrolled ? "calc(10% + 0rem)" : "calc(0% + 0rem)" ,
111- paddingRight : isScrolled ? "calc(10% + 0.5rem)" : "calc(0% + 0rem)" ,
143+ paddingLeft : headerInlinePadding ,
144+ paddingRight : headerRightPadding ,
112145 } }
113146 transition = { shellTransition }
114147 >
@@ -146,10 +179,7 @@ const NavigationMobile: React.FC<NavigationMobileProps> = ({ locale, items, butt
146179 initial = { { opacity : 0 , y : - 4 , height : 0 } }
147180 animate = { { opacity : 1 , y : 0 , height : "auto" } }
148181 exit = { { opacity : 0 , y : - 4 , height : 0 } }
149- transition = { {
150- ...menuTransition ,
151- delay : isScrolled ? 0.08 : 0 ,
152- } }
182+ transition = { menuTransition }
153183 style = { { overflow : "hidden" } }
154184 className = "flex flex-col gap-2 px-2"
155185 >
0 commit comments