Fix Sasquatch / Add Spot FAB overlap on mobile map

- SasquatchGuide now dispatches 'sasquatch:panelchange' event when panel opens/closes
- MapPage listens to the event and hides the Add Spot FAB (with scale-down animation)
  whenever the Sasquatch panel is open — no more overlap
- FAB reappears with smooth opacity + scale transition when panel closes
- Added a visible close (X) button to the Sasquatch panel header alongside the existing
  minimize button — gives users a clear way to fully dismiss the panel
- Sasquatch panel bottom edge stays 10px above the nav bar on all screen sizes

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
This commit is contained in:
shakespeare.diy 2026-07-23 22:00:50 +07:00
parent a1cd936bc4
commit f48844b495
2 changed files with 34 additions and 5 deletions

View file

@ -582,6 +582,12 @@ Instructions:
// The full panel shows only when there's a message or when opened externally/by user tap. // The full panel shows only when there's a message or when opened externally/by user tap.
const shouldShowPanel = !!message || isVisible; const shouldShowPanel = !!message || isVisible;
// Notify the rest of the app (e.g. MapPage FAB) when the panel opens or closes
useEffect(() => {
const panelOpen = shouldShowPanel && !isMinimized;
window.dispatchEvent(new CustomEvent('sasquatch:panelchange', { detail: { open: panelOpen } }));
}, [shouldShowPanel, isMinimized]);
const inputDisabled = isThinking; const inputDisabled = isThinking;
// Build a fallback generic message for pages with no specific context // Build a fallback generic message for pages with no specific context
@ -688,15 +694,24 @@ Instructions:
</div> </div>
</div> </div>
<div className="flex gap-1 flex-shrink-0"> <div className="flex gap-1 flex-shrink-0">
{/* Minimize — keeps the bubble visible */} {/* Minimize — shrinks to draggable bubble */}
<button <button
onClick={() => setIsMinimized(true)} onClick={() => setIsMinimized(true)}
className="w-6 h-6 flex items-center justify-center rounded text-[#ccff00]/40 hover:text-[#ccff00] hover:bg-[#ccff00]/10 transition-colors" className="w-6 h-6 flex items-center justify-center rounded text-[#ccff00]/40 hover:text-[#ccff00] hover:bg-[#ccff00]/10 transition-colors"
aria-label="Minimize to bubble" aria-label="Minimize to bubble"
title="Minimize — bubble stays visible so you can reopen anytime" title="Minimize"
> >
<Minimize2 className="h-3 w-3" /> <Minimize2 className="h-3 w-3" />
</button> </button>
{/* Close — hides the panel entirely */}
<button
onClick={() => { setIsVisible(false); if (onDismiss) onDismiss(); }}
className="w-6 h-6 flex items-center justify-center rounded text-white/30 hover:text-white/80 hover:bg-white/10 transition-colors"
aria-label="Close panel"
title="Close"
>
<X className="h-3 w-3" />
</button>
</div> </div>
</div> </div>

View file

@ -572,6 +572,16 @@ export default function MapPage() {
// Welcome banner — show once to new/logged-out visitors, dismissible // Welcome banner — show once to new/logged-out visitors, dismissible
const [welcomeDismissed, setWelcomeDismissed] = useLocalStorage('skatespots_welcome_dismissed', false); const [welcomeDismissed, setWelcomeDismissed] = useLocalStorage('skatespots_welcome_dismissed', false);
const showWelcomeBanner = !user && !welcomeDismissed; const showWelcomeBanner = !user && !welcomeDismissed;
// Track Sasquatch panel open state so the Add Spot FAB can step aside
const [sasquatchPanelOpen, setSasquatchPanelOpen] = useState(false);
useEffect(() => {
const handler = (e: Event) => {
setSasquatchPanelOpen((e as CustomEvent<{ open: boolean }>).detail.open);
};
window.addEventListener('sasquatch:panelchange', handler);
return () => window.removeEventListener('sasquatch:panelchange', handler);
}, []);
// Quick camera capture // Quick camera capture
const [showQuickCamera, setShowQuickCamera] = useState(false); const [showQuickCamera, setShowQuickCamera] = useState(false);
@ -1410,10 +1420,14 @@ export default function MapPage() {
</div> </div>
)} )}
{/* Add Spot FAB — primary CTA, bottom-left, always visible on map */} {/* Add Spot FAB — primary CTA, bottom-left.
Hidden when Sasquatch panel is open (user is in chat mode).
Hidden when mobile filters or spot sheet is open. */}
<div className={cn( <div className={cn(
"absolute bottom-4 left-4 z-[1000] transition-opacity duration-150 md:hidden", "absolute bottom-4 left-4 z-[1000] transition-all duration-200 md:hidden",
mobileFiltersOpen || selectedSpot ? "opacity-0 pointer-events-none" : "opacity-100" mobileFiltersOpen || selectedSpot || sasquatchPanelOpen
? "opacity-0 pointer-events-none scale-90"
: "opacity-100 scale-100"
)}> )}>
{user ? ( {user ? (
<Link to="/create-spot"> <Link to="/create-spot">