fix(ui): unblock the zoom control, tidy Go Pro, and make the route map bigger
Three phone issues from a screenshot review: - Map: the floating toolbar sat on top of Leaflet's top-left zoom control. index.css now offsets .leaflet-top.leaflet-left by 4.25rem under max-width 767px, scoped to the map page via a new class (desktop toolbar is in flow, so no offset). Verified at 390x844. - Sasquatch: the cramped red 8px 'Go Pro' chip is now a proper lime pill with the bolt, matching the panel. - Directions: the map was 38vh and buried under the mode row. It's now 50vh (440px on larger screens; 60vh/62vh while following) and sits directly under the header, with the mode/vehicle row and 'From' row moved BELOW it. Done with flex order-* utilities rather than moving JSX; Start bar stays pinned.
This commit is contained in:
parent
1c7bd2aa6e
commit
1e0902f6b9
5 changed files with 39 additions and 19 deletions
22
AGENTS.md
22
AGENTS.md
|
|
@ -295,13 +295,16 @@ session with **no other memory of this project**. So:
|
|||
**Still deliberately absent: auto-reroute if you leave the route.** True
|
||||
screen-off/background navigation needs a native foreground service — the app
|
||||
must stay foregrounded to guide.
|
||||
- **Dialog layout (2026-09-27):** app-like flex column —
|
||||
`flex max-h-[calc(100dvh-2rem)] flex-col overflow-hidden`: header, mode row,
|
||||
"From" row and the **map** are `shrink-0` (map `h-[38vh] sm:h-[400px]`, or
|
||||
`h-[58vh]`/`sm:h-[60vh]` while following), the
|
||||
middle (stat tiles + steps) is the only scroll region (`min-h-0 flex-1
|
||||
overflow-y-auto`), and the **Start/Stop bar is pinned** at the bottom so it's
|
||||
always reachable. ⚠️ Don't go back to a single `overflow-hidden` content box:
|
||||
- **Dialog layout (2026-09-29):** app-like flex column —
|
||||
`flex max-h-[calc(100dvh-2rem)] flex-col overflow-hidden`. **Visual order is
|
||||
set with flex `order-*` utilities, not DOM order** (avoids moving JSX): the
|
||||
**map** is `order-2` (directly under the header — it's the point of the
|
||||
screen), the **mode/vehicle row** `order-3` and **"From" row** `order-4` sit
|
||||
*below* the map, the details are `order-5`, and the **Start/Stop bar** is
|
||||
`order-6`, pinned at the bottom so it's always reachable. The map is
|
||||
`shrink-0` at `h-[50vh] min-h-[300px] sm:h-[440px]` (was `38vh`), or
|
||||
`h-[60vh]`/`sm:h-[62vh]` while following. ⚠️ Don't go back to a single
|
||||
`overflow-hidden` content box:
|
||||
that made everything below the fold **unreachable** once the map grew. The
|
||||
summary is three `StatTile`s (distance / time / arrive) + a detail line
|
||||
(steps, driving-roads note, avg speed) and the map carries a metric
|
||||
|
|
@ -649,6 +652,11 @@ session with **no other memory of this project**. So:
|
|||
re-add a stacked toolbar or the footer subtraction. The "New here?" welcome
|
||||
banner (logged-out only) still occupies ~69px *in flow* on first visit — it's
|
||||
dismissible and the dismissal is persisted (`skatespots_welcome_dismissed`).
|
||||
⚠️ The floating toolbar sits over Leaflet's default **top-left zoom control**,
|
||||
so `MapPage` passes `className="h-full ss-map-floating-toolbar"` and
|
||||
`index.css` offsets `.leaflet-top.leaflet-left` by `4.25rem` **only under
|
||||
`max-width:767px`** (desktop toolbar is in flow, no offset). Verified at
|
||||
390×844: zoom top 135px vs search bottom 108px.
|
||||
- **Empty-map nudge (2026-09-28):** `MapPage` distinguishes the two empties — the
|
||||
existing "No spots match" card is for *filters* (`filteredSpots.length === 0 &&
|
||||
allLocations.length > 0`) and a new "No spots mapped yet — be the first" card
|
||||
|
|
|
|||
|
|
@ -668,10 +668,12 @@ export function RouteDialog({
|
|||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
{/* App-like shell: header + modes + map are pinned, the details in the
|
||||
middle scroll, and the Start/Stop bar stays reachable at the bottom. */}
|
||||
{/* App-like shell. VISUAL ORDER is set with flex `order` utilities, not DOM
|
||||
order: the map sits directly under the header (bigger — it's the point
|
||||
of the screen), the mode/vehicle row moves BELOW it, and the details
|
||||
scroll with the Start/Stop bar pinned at the bottom. */}
|
||||
<DialogContent className="flex max-h-[calc(100dvh-2rem)] w-[calc(100%-2rem)] max-w-lg flex-col gap-0 overflow-hidden p-0 sm:max-w-xl">
|
||||
<DialogHeader className="shrink-0 p-4 pb-3">
|
||||
<DialogHeader className="order-1 shrink-0 p-4 pb-3">
|
||||
<DialogTitle className="flex items-center gap-2 text-lg">
|
||||
<Navigation className="h-5 w-5 text-[#ccff00]" />
|
||||
Route to {destinationLabel}
|
||||
|
|
@ -683,8 +685,8 @@ export function RouteDialog({
|
|||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
{/* Mode toggle */}
|
||||
<div className="flex shrink-0 gap-1.5 px-4 pb-3">
|
||||
{/* Mode toggle (vehicles) — sits BELOW the map via order-3. */}
|
||||
<div className="order-3 flex shrink-0 gap-1.5 px-4 pb-3">
|
||||
{TRAVEL_MODES.map((m) => (
|
||||
<button
|
||||
key={m.mode}
|
||||
|
|
@ -705,7 +707,7 @@ export function RouteDialog({
|
|||
</div>
|
||||
|
||||
{/* Start point — default is where you are; you can pick another on the map */}
|
||||
<div className="flex shrink-0 flex-wrap items-center gap-1.5 px-4 pb-3">
|
||||
<div className="order-4 flex shrink-0 flex-wrap items-center gap-1.5 px-4 pb-3">
|
||||
<span className="text-[10px] font-black uppercase tracking-widest text-muted-foreground">
|
||||
From
|
||||
</span>
|
||||
|
|
@ -743,7 +745,7 @@ export function RouteDialog({
|
|||
`.leaflet-container { height: 100% }` override beats a `h-64` on the
|
||||
map element itself, and against a height-less parent that resolved to
|
||||
0 — a fully invisible map with no route line. */}
|
||||
<div className={cn('relative shrink-0', following ? 'h-[58vh] min-h-[340px] sm:h-[60vh]' : 'h-[38vh] min-h-[220px] sm:h-[400px]')}>
|
||||
<div className={cn('order-2 relative shrink-0', following ? 'h-[60vh] min-h-[360px] sm:h-[62vh]' : 'h-[50vh] min-h-[300px] sm:h-[440px]')}>
|
||||
<div
|
||||
ref={setMapDiv}
|
||||
className="h-full w-full bg-muted"
|
||||
|
|
@ -841,7 +843,7 @@ export function RouteDialog({
|
|||
</div>
|
||||
|
||||
{/* Scrollable details */}
|
||||
<div className="min-h-0 flex-1 overflow-y-auto">
|
||||
<div className="order-5 min-h-0 flex-1 overflow-y-auto">
|
||||
|
||||
{/* Summary bar */}
|
||||
<div className="p-4 border-t bg-muted/30 min-h-[64px] flex items-center">
|
||||
|
|
@ -978,7 +980,7 @@ export function RouteDialog({
|
|||
|
||||
{/* Follow mode: live turns + voice, with the screen kept awake. */}
|
||||
{route && !route.transit && (
|
||||
<div className="flex items-center gap-3 border-t bg-muted/30 px-4 py-3">
|
||||
<div className="order-6 flex items-center gap-3 border-t bg-muted/30 px-4 py-3">
|
||||
{arrived ? (
|
||||
<Button
|
||||
size="sm"
|
||||
|
|
|
|||
|
|
@ -1655,10 +1655,11 @@ Instructions:
|
|||
) : user ? (
|
||||
<button
|
||||
onClick={() => setProDialogOpen(true)}
|
||||
className="flex items-center gap-0.5 rounded bg-red-500/20 px-1 py-0.5 text-[8px] font-black uppercase tracking-wider text-red-400 hover:bg-red-500/30 transition-colors"
|
||||
className="ml-0.5 inline-flex items-center gap-1 rounded-full border border-[#ccff00]/40 bg-[#ccff00]/10 px-2 py-0.5 text-[9px] font-black uppercase tracking-wider text-[#ccff00] transition-colors hover:border-[#ccff00]/70 hover:bg-[#ccff00]/20"
|
||||
title="Upgrade to Sasquatch Pro"
|
||||
>
|
||||
⚡ Go Pro
|
||||
<span aria-hidden>⚡</span>
|
||||
Go Pro
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -122,6 +122,15 @@
|
|||
padding-bottom: 64px;
|
||||
}
|
||||
|
||||
/* The map page's toolbar floats over the top of the map on mobile, which would
|
||||
otherwise sit on top of Leaflet's default top-left zoom control. Push that
|
||||
control clear of it (desktop keeps the toolbar in flow, so no offset). */
|
||||
@media (max-width: 767px) {
|
||||
.ss-map-floating-toolbar .leaflet-top.leaflet-left {
|
||||
margin-top: 4.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.leaflet-popup-content-wrapper {
|
||||
border-radius: calc(var(--radius) - 4px);
|
||||
box-shadow: 0 10px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
|
||||
|
|
|
|||
|
|
@ -1633,7 +1633,7 @@ export default function MapPage() {
|
|||
onMapClick={handleMapClick}
|
||||
onMapMove={setMapCenter}
|
||||
enableClickToAdd={!!user}
|
||||
className="h-full"
|
||||
className="h-full ss-map-floating-toolbar"
|
||||
weatherEnabled={weatherEnabled}
|
||||
weatherData={weatherData}
|
||||
events={upcomingEvents || []}
|
||||
|
|
|
|||
Loading…
Reference in a new issue