fix: FAB buttons above nav + Sasquatch no auto-trigger on map

- FABs (add spot/shop): switch from fixed bottom-[88px] to
  calc(3.5rem + env(safe-area-inset-bottom, 0px) + 0.75rem) so they
  respect device safe-area and always clear the bottom nav on all
  Android/iOS Capacitor builds
- Right-side filter pills: same fix, switched from absolute to fixed
  with the same safe-area-aware bottom value
- useSasquatchGuide: /map page now returns undefined message, meaning
  Sasquatch never auto-opens when navigating to Shops & Spots — user
  must tap the floating bubble to open it manually

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
This commit is contained in:
shakespeare.diy 2026-07-24 00:12:53 +07:00
parent c48efdf525
commit eba7542097
2 changed files with 22 additions and 44 deletions

View file

@ -147,38 +147,10 @@ export function useSasquatchGuide() {
};
}
// Show on Shops & Spots map page with random jokes
// /map: never auto-show — user opens Sasquatch by tapping the floating bubble
// The map guide context + jokes are still available in the generic fallback inside SasquatchGuide
else if (location.pathname === '/map') {
const joke = getRandomJoke(MAP_JOKES);
message = {
id: 'map-guide',
title: 'Shops & Spots Explorer! 🗺️',
message: `Welcome to the global skate database! Use the map to discover spots and shops worldwide, or switch to list view to filter by type. Toggle between Spots (🛹), Shops (🏪), and Gear (🛒) using the buttons. Pro tip: Click anywhere on the map when logged in to add a new spot!\n\n${joke}`,
context: 'map',
suggestedQuestions: [
'Find beginner spots',
'Find spots in Bangkok',
'Find skate parks',
'Any street spots?',
'Gear for sale?',
'How to add spot?',
'What are spots?',
'Weather on map?',
],
action: user ? {
label: 'Add Your First Spot',
onClick: () => {
// This will just scroll to show them they can click the map
window.scrollTo({ top: 0, behavior: 'smooth' });
},
} : {
label: 'Login to Add Spots',
onClick: () => {
window.location.href = '/onboarding';
},
},
enableChat: true,
};
message = undefined;
}
setCurrentMessage(message);

View file

@ -1421,16 +1421,19 @@ export default function MapPage() {
</div>
)}
{/* Add Spot + Add Shop FABs — bottom-left, 16px from bottom of map container
The map container already excludes the bottom nav height, so bottom-4 is correct.
Hidden when overlays open. */}
{/* Add Spot + Add Shop FABs — fixed to screen, above bottom nav.
Uses fixed positioning so CSS variable issues on Capacitor don't affect placement.
calc(4rem + env(safe-area-inset-bottom, 0px)) + 44px gap = clears nav on all devices. */}
{user && (
<div className={cn(
"absolute bottom-4 left-3 z-[1001] md:hidden flex flex-col items-start gap-2.5 transition-all duration-200",
mobileFiltersOpen || selectedSpot || sasquatchPanelOpen
? "opacity-0 pointer-events-none scale-90"
: "opacity-100 scale-100"
)}>
<div
className={cn(
"fixed left-3 z-[1001] md:hidden flex flex-col items-start gap-2.5 transition-all duration-200",
mobileFiltersOpen || selectedSpot || sasquatchPanelOpen
? "opacity-0 pointer-events-none scale-90"
: "opacity-100 scale-100"
)}
style={{ bottom: 'calc(3.5rem + env(safe-area-inset-bottom, 0px) + 0.75rem)' }}
>
{/* Add Shop — green circle */}
<Link to="/create-shop" aria-label="Add a skate shop">
<button
@ -1536,10 +1539,13 @@ export default function MapPage() {
)}
{/* Right-side control column — filter pills + Quick Snap (mobile only, hidden when overlays open) */}
<div className={cn(
"absolute bottom-4 right-3 z-[1000] md:hidden flex flex-col items-center gap-2 transition-opacity duration-150",
mobileFiltersOpen || selectedSpot ? "opacity-0 pointer-events-none" : "opacity-100"
)}>
<div
className={cn(
"fixed right-3 z-[1000] md:hidden flex flex-col items-center gap-2 transition-opacity duration-150",
mobileFiltersOpen || selectedSpot ? "opacity-0 pointer-events-none" : "opacity-100"
)}
style={{ bottom: 'calc(3.5rem + env(safe-area-inset-bottom, 0px) + 0.75rem)' }}
>
{/* Layer filter pills — compact icon-only */}
{[
{ key: 'spots', label: '🛹', active: showSpots, toggle: () => setShowSpots(v => !v), activeColor: 'bg-red-500/90' },