mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-19 13:21:46 +00:00
fix: offline banner no longer covers the top of the app (#813)
OfflineBanner was fixed at top:0 but the rest of the page had no idea it was visible, so on mobile (and the desktop nav on wider screens) the banner sat on top of the header content. When the banner is visible it now sets --offline-banner-h on <html>; body reserves that space via padding-top, and the desktop fixed Navbar shifts its top by the same amount. When back online the var is removed and everything snaps back.
This commit is contained in:
@@ -89,6 +89,7 @@ export default function Navbar({ tripTitle, tripId, onBack, showBack, onShare }:
|
||||
touchAction: 'manipulation',
|
||||
paddingTop: 'env(safe-area-inset-top, 0px)',
|
||||
height: 'var(--nav-h)',
|
||||
top: 'var(--offline-banner-h, 0px)',
|
||||
transition: 'background 240ms cubic-bezier(0.23,1,0.32,1), backdrop-filter 240ms cubic-bezier(0.23,1,0.32,1), box-shadow 240ms cubic-bezier(0.23,1,0.32,1)',
|
||||
}} className="hidden md:flex items-center px-4 gap-4 fixed top-0 left-0 right-0 z-[200]">
|
||||
{/* Left side */}
|
||||
|
||||
@@ -40,6 +40,22 @@ export default function OfflineBanner(): React.ReactElement | null {
|
||||
}, [])
|
||||
|
||||
const hidden = isOnline && pendingCount === 0
|
||||
|
||||
// When the banner is visible, reserve space at the top of the page so it
|
||||
// doesn't cover the nav/header. Uses a CSS var on <html> so we can offset
|
||||
// via a global `body` rule instead of rewiring every layout.
|
||||
useEffect(() => {
|
||||
const root = document.documentElement
|
||||
if (hidden) {
|
||||
root.style.removeProperty('--offline-banner-h')
|
||||
} else {
|
||||
// 32px for icon+text row + the top safe-area inset that the banner adds
|
||||
// in its own padding. Kept in one place so it's easy to tweak.
|
||||
root.style.setProperty('--offline-banner-h', 'calc(env(safe-area-inset-top, 0px) + 32px)')
|
||||
}
|
||||
return () => { root.style.removeProperty('--offline-banner-h') }
|
||||
}, [hidden])
|
||||
|
||||
if (hidden) return null
|
||||
|
||||
const offline = !isOnline
|
||||
|
||||
@@ -431,6 +431,8 @@ input[type="number"], input[type="time"], input[type="date"], input[type="dateti
|
||||
--safe-top: env(safe-area-inset-top, 0px);
|
||||
--nav-h: 0px;
|
||||
--bottom-nav-h: 0px;
|
||||
/* Set by OfflineBanner when it's visible so body can reserve space. */
|
||||
--offline-banner-h: 0px;
|
||||
--font-system: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', system-ui, sans-serif;
|
||||
--sp-1: 4px;
|
||||
--sp-2: 8px;
|
||||
@@ -536,7 +538,9 @@ body {
|
||||
font-family: var(--font-system);
|
||||
background-color: var(--bg-primary);
|
||||
color: var(--text-primary);
|
||||
transition: background-color 0.2s, color 0.2s;
|
||||
transition: background-color 0.2s, color 0.2s, padding-top 0.15s ease;
|
||||
/* Reserve space when OfflineBanner is visible; 0 when online. */
|
||||
padding-top: var(--offline-banner-h, 0px);
|
||||
}
|
||||
|
||||
/* ── Marker cluster custom styling ────────────── */
|
||||
|
||||
Reference in New Issue
Block a user