mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-19 13:21:46 +00:00
drop hero / inline tab-bar on mobile journey + gallery, eager map tiles
- mobile: journey and gallery views both run as chromeless overlays now. The hero card, backlink, stats row and inline tab-bar are hidden; the floating top bar (back, Journey/Gallery toggle, settings) handles branding for both views, and the gallery content gets a top padding that matches the bar so nothing is occluded. - the journey-title pill below the tab-toggle is removed — the toggle itself is enough; the pill just duplicated information. - JourneyMap tile layer: set updateWhenIdle:false and keepBuffer:4. Leaflet defaults to "wait for pan to settle before loading tiles" on mobile, which showed as a visible tile-lag when switching timeline cards (flyTo moves the map). Eager updates plus a wider off-screen ring keep the neighbouring tiles hot.
This commit is contained in:
@@ -183,6 +183,12 @@ const JourneyMap = forwardRef<JourneyMapHandle, Props>(function JourneyMap(
|
|||||||
maxZoom: 18,
|
maxZoom: 18,
|
||||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
|
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
|
||||||
referrerPolicy: 'strict-origin-when-cross-origin',
|
referrerPolicy: 'strict-origin-when-cross-origin',
|
||||||
|
// Leaflet defaults updateWhenIdle:true on mobile (waits for pan to settle
|
||||||
|
// before loading tiles). On the journey mobile combined view we flyTo
|
||||||
|
// constantly when switching cards, so tiles lag visibly — force eager
|
||||||
|
// updates and keep a larger ring of off-screen tiles ready.
|
||||||
|
updateWhenIdle: false,
|
||||||
|
keepBuffer: 4,
|
||||||
} as any).addTo(map)
|
} as any).addTo(map)
|
||||||
|
|
||||||
const items = buildMarkerItems(entries)
|
const items = buildMarkerItems(entries)
|
||||||
|
|||||||
@@ -230,6 +230,8 @@ export default function JourneyDetailPage() {
|
|||||||
const lifecycle = computeJourneyLifecycle(current.status, tripDateMin || null, tripDateMax || null)
|
const lifecycle = computeJourneyLifecycle(current.status, tripDateMin || null, tripDateMax || null)
|
||||||
|
|
||||||
const showMobileCombined = isMobile && view === 'timeline'
|
const showMobileCombined = isMobile && view === 'timeline'
|
||||||
|
const showMobileGallery = isMobile && view === 'gallery'
|
||||||
|
const isMobileChromeless = showMobileCombined || showMobileGallery
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-zinc-50 dark:bg-zinc-950">
|
<div className="min-h-screen bg-zinc-50 dark:bg-zinc-950">
|
||||||
@@ -262,8 +264,8 @@ export default function JourneyDetailPage() {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Floating top bar on mobile combined view: back | tabs+title | settings */}
|
{/* Floating top bar on mobile Journey + Gallery views: back | tabs+title | settings */}
|
||||||
{showMobileCombined && (
|
{isMobileChromeless && (
|
||||||
<div
|
<div
|
||||||
className="fixed left-0 right-0 z-30 flex items-start justify-between gap-2 px-4"
|
className="fixed left-0 right-0 z-30 flex items-start justify-between gap-2 px-4"
|
||||||
style={{ top: 'calc(var(--nav-h, 56px) + 12px)' }}
|
style={{ top: 'calc(var(--nav-h, 56px) + 12px)' }}
|
||||||
@@ -276,28 +278,31 @@ export default function JourneyDetailPage() {
|
|||||||
<ArrowLeft size={16} />
|
<ArrowLeft size={16} />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div className="flex-1 min-w-0 flex flex-col items-center gap-1">
|
<div className="flex-1 min-w-0 flex justify-center">
|
||||||
<div className="flex bg-white/90 dark:bg-zinc-800/90 backdrop-blur-lg border border-zinc-200 dark:border-zinc-700 rounded-lg overflow-hidden shadow-lg">
|
<div className="flex bg-white/90 dark:bg-zinc-800/90 backdrop-blur-lg border border-zinc-200 dark:border-zinc-700 rounded-lg overflow-hidden shadow-lg">
|
||||||
<button
|
<button
|
||||||
onClick={() => setView('timeline')}
|
onClick={() => setView('timeline')}
|
||||||
className="flex items-center gap-1.5 px-3 py-[7px] text-[12px] font-medium bg-zinc-900 dark:bg-white text-white dark:text-zinc-900"
|
className={`flex items-center gap-1.5 px-3 py-[7px] text-[12px] font-medium ${
|
||||||
|
view === 'timeline'
|
||||||
|
? 'bg-zinc-900 dark:bg-white text-white dark:text-zinc-900'
|
||||||
|
: 'text-zinc-500 hover:text-zinc-700 dark:hover:text-zinc-300'
|
||||||
|
}`}
|
||||||
>
|
>
|
||||||
<MapPin size={13} />
|
<MapPin size={13} />
|
||||||
{t('journey.detail.journeyTab') || 'Journey'}
|
{t('journey.detail.journeyTab') || 'Journey'}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => setView('gallery')}
|
onClick={() => setView('gallery')}
|
||||||
className="flex items-center gap-1.5 px-3 py-[7px] text-[12px] font-medium text-zinc-500 hover:text-zinc-700 dark:hover:text-zinc-300"
|
className={`flex items-center gap-1.5 px-3 py-[7px] text-[12px] font-medium ${
|
||||||
|
view === 'gallery'
|
||||||
|
? 'bg-zinc-900 dark:bg-white text-white dark:text-zinc-900'
|
||||||
|
: 'text-zinc-500 hover:text-zinc-700 dark:hover:text-zinc-300'
|
||||||
|
}`}
|
||||||
>
|
>
|
||||||
<Grid size={13} />
|
<Grid size={13} />
|
||||||
{t('journey.share.gallery')}
|
{t('journey.share.gallery')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{current?.title && (
|
|
||||||
<div className="max-w-full truncate text-center text-[11px] font-medium text-zinc-700 dark:text-zinc-200 px-2.5 py-0.5 rounded-full bg-white/80 dark:bg-zinc-800/80 backdrop-blur-md border border-zinc-200/60 dark:border-zinc-700/60 shadow-sm">
|
|
||||||
{current.title}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{canEditJourney ? (
|
{canEditJourney ? (
|
||||||
@@ -323,8 +328,8 @@ export default function JourneyDetailPage() {
|
|||||||
{t('journey.detail.backToJourney')}
|
{t('journey.detail.backToJourney')}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{/* Hero card — full width */}
|
{/* Hero card — hidden on mobile gallery/journey views (floating top bar handles branding there) */}
|
||||||
<div className="px-4 md:px-0 mb-6">
|
<div className={`px-4 md:px-0 mb-6 ${isMobileChromeless ? 'hidden' : ''}`}>
|
||||||
<div className="rounded-none md:rounded-2xl -mx-4 md:mx-0 overflow-hidden relative p-5 md:p-7" style={{ background: pickGradient(current.id), color: 'white' }}>
|
<div className="rounded-none md:rounded-2xl -mx-4 md:mx-0 overflow-hidden relative p-5 md:p-7" style={{ background: pickGradient(current.id), color: 'white' }}>
|
||||||
{current.cover_image && (
|
{current.cover_image && (
|
||||||
<div className="absolute inset-0 z-[1]">
|
<div className="absolute inset-0 z-[1]">
|
||||||
@@ -418,8 +423,8 @@ export default function JourneyDetailPage() {
|
|||||||
|
|
||||||
{/* Left column */}
|
{/* Left column */}
|
||||||
<div>
|
<div>
|
||||||
{/* View Controls */}
|
{/* View Controls — hidden on mobile (floating top bar has them) */}
|
||||||
<div className="flex items-center justify-between mt-5 mb-5">
|
<div className={`flex items-center justify-between mt-5 mb-5 ${isMobileChromeless ? 'hidden' : ''}`}>
|
||||||
<div className="flex bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-lg overflow-hidden">
|
<div className="flex bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700 rounded-lg overflow-hidden">
|
||||||
{(isMobile
|
{(isMobile
|
||||||
? [
|
? [
|
||||||
@@ -516,8 +521,11 @@ export default function JourneyDetailPage() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Gallery View */}
|
{/* Gallery View — mobile gets extra top padding so the floating top bar doesn't overlap */}
|
||||||
<div className={view === 'gallery' ? '' : 'hidden'}>
|
<div
|
||||||
|
className={view === 'gallery' ? '' : 'hidden'}
|
||||||
|
style={showMobileGallery ? { paddingTop: 'calc(var(--nav-h, 56px) + 64px)' } : undefined}
|
||||||
|
>
|
||||||
<GalleryView
|
<GalleryView
|
||||||
entries={current.entries}
|
entries={current.entries}
|
||||||
journeyId={current.id}
|
journeyId={current.id}
|
||||||
|
|||||||
Reference in New Issue
Block a user