Skip to content

Commit d9cf3ee

Browse files
updates
1 parent 07d4891 commit d9cf3ee

2 files changed

Lines changed: 51 additions & 2 deletions

File tree

components/Navbar.tsx

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client';
22

3-
import { useState, useEffect, type CSSProperties } from 'react';
3+
import { useState, useEffect, useLayoutEffect, useRef, type CSSProperties } from 'react';
44
import { createPortal } from 'react-dom';
55
import Image from 'next/image';
66
import Link from 'next/link';
@@ -38,8 +38,11 @@ type Props = {
3838
};
3939

4040
export default function Navbar({ variant = 'light' }: Props) {
41+
const navRef = useRef<HTMLElement>(null);
4142
const [scrolled, setScrolled] = useState(false);
4243
const [mobileOpen, setMobileOpen] = useState(false);
44+
/** Measured from TopBar + nav (px). Fixed 7rem was wrong when TopBar wraps → gap + short panel on iOS. */
45+
const [mobileMenuTopPx, setMobileMenuTopPx] = useState<number | null>(null);
4346
const [openDropdown, setOpenDropdown] = useState<'jobSupport' | 'locations' | null>(null);
4447
const [mobileJobOpen, setMobileJobOpen] = useState(false);
4548
const [mobileLocOpen, setMobileLocOpen] = useState(false);
@@ -61,6 +64,47 @@ export default function Navbar({ variant = 'light' }: Props) {
6164
};
6265
}, [mobileOpen]);
6366

67+
useLayoutEffect(() => {
68+
if (!mobileOpen || typeof document === 'undefined') {
69+
setMobileMenuTopPx(null);
70+
return;
71+
}
72+
const measure = () => {
73+
const nav = navRef.current;
74+
const topbar = document.querySelector('[data-pts-topbar]');
75+
let bottom = 0;
76+
if (topbar instanceof HTMLElement) {
77+
bottom = Math.max(bottom, topbar.getBoundingClientRect().bottom);
78+
}
79+
if (nav) {
80+
bottom = Math.max(bottom, nav.getBoundingClientRect().bottom);
81+
}
82+
setMobileMenuTopPx(Math.max(0, Math.ceil(bottom)));
83+
};
84+
measure();
85+
window.addEventListener('resize', measure);
86+
window.addEventListener('orientationchange', measure);
87+
const vv = window.visualViewport;
88+
vv?.addEventListener('resize', measure);
89+
vv?.addEventListener('scroll', measure);
90+
return () => {
91+
window.removeEventListener('resize', measure);
92+
window.removeEventListener('orientationchange', measure);
93+
vv?.removeEventListener('resize', measure);
94+
vv?.removeEventListener('scroll', measure);
95+
};
96+
}, [mobileOpen]);
97+
98+
const mobileOverlayPosition: CSSProperties | undefined =
99+
mobileMenuTopPx != null
100+
? {
101+
top: mobileMenuTopPx,
102+
height: `calc(100dvh - ${mobileMenuTopPx}px)`,
103+
maxHeight: `calc(100svh - ${mobileMenuTopPx}px)`,
104+
bottom: 'auto',
105+
}
106+
: undefined;
107+
64108
/** Above portal panel (2101) so the bar + ✕/☰ stay visible on legacy iOS when the sheet overlaps the row. */
65109
const navStackZ = mobileOpen ? 4000 : 1000;
66110

@@ -112,7 +156,7 @@ export default function Navbar({ variant = 'light' }: Props) {
112156
};
113157

114158
return (
115-
<nav style={navStyle}>
159+
<nav ref={navRef} style={navStyle}>
116160
<div
117161
style={{
118162
width: '100%',
@@ -377,10 +421,12 @@ export default function Navbar({ variant = 'light' }: Props) {
377421
className="pts-mobile-nav-backdrop"
378422
aria-label="Close menu"
379423
onClick={() => setMobileOpen(false)}
424+
style={mobileOverlayPosition}
380425
/>
381426
<div
382427
className="pts-mobile-nav-panel"
383428
style={{
429+
...mobileOverlayPosition,
384430
background: dark ? 'var(--pts-nav-bg)' : 'var(--pts-bg)',
385431
borderTop: dark ? '1px solid rgba(255,255,255,0.1)' : '1px solid var(--pts-border)',
386432
padding: '0.75rem 1rem 1.25rem',
@@ -661,6 +707,7 @@ export default function Navbar({ variant = 'light' }: Props) {
661707
bottom: 0;
662708
z-index: 2101;
663709
overflow-y: auto;
710+
overscroll-behavior: contain;
664711
-webkit-overflow-scrolling: touch;
665712
box-shadow: 0 -8px 32px rgba(0, 0, 0, 0.12);
666713
touch-action: manipulation;

components/TopBar.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export default function TopBar({ variant = 'legacyDark' }: Props) {
99
if (variant === 'legacyDark') {
1010
return (
1111
<div
12+
data-pts-topbar
1213
style={{
1314
background: 'var(--pts-topbar-bg)',
1415
borderBottom: '1px solid rgba(255, 255, 255, 0.08)',
@@ -42,6 +43,7 @@ export default function TopBar({ variant = 'legacyDark' }: Props) {
4243

4344
return (
4445
<div
46+
data-pts-topbar
4547
style={{
4648
background: 'var(--pts-forest)',
4749
borderBottom: '1px solid rgba(0, 0, 0, 0.08)',

0 commit comments

Comments
 (0)