fix(portal): mobile toolbar as fixed viewport element + layout fixes

Selection toolbar:
- Moved OUTSIDE map container div to a fixed viewport position
  (bottom-4, z-[110]). iOS Safari clips absolute elements inside
  calc(100vh) containers — fixed positioning solves this.
- Only shown when UAT selected and has data.

Mobile top layout:
- UAT card takes full width (right-2 not right-[140px])
- Basemap switcher at top-[52px] left-2 on mobile (below UAT card)
- Desktop: unchanged (top-right offset from zoom controls)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
AI Assistant
2026-03-25 11:06:48 +02:00
parent 12ff629fbf
commit d82b873552
+19 -17
View File
@@ -1528,7 +1528,7 @@ function HartaContent() {
/> />
{/* Top-left: UAT info + change button (responsive) */} {/* Top-left: UAT info + change button (responsive) */}
<div className="absolute top-2 left-2 right-[140px] sm:right-auto z-10 flex flex-col gap-2"> <div className="absolute top-2 left-2 right-2 sm:right-auto z-10 flex flex-col gap-2">
<div className="bg-background/95 backdrop-blur-sm border rounded-lg shadow-lg px-2 sm:px-3 py-1.5 sm:py-2 flex items-center gap-2"> <div className="bg-background/95 backdrop-blur-sm border rounded-lg shadow-lg px-2 sm:px-3 py-1.5 sm:py-2 flex items-center gap-2">
<div className="min-w-0"> <div className="min-w-0">
<p className="text-xs sm:text-sm font-semibold truncate">{selectedUat?.name}</p> <p className="text-xs sm:text-sm font-semibold truncate">{selectedUat?.name}</p>
@@ -1556,9 +1556,9 @@ function HartaContent() {
</div> </div>
</div> </div>
{/* Top-right: basemap switcher + simple feature info (offset to avoid zoom controls) */} {/* Basemap switcher + feature info */}
{/* On mobile (< sm), drops below the UAT card via top-14 */} {/* Mobile: below UAT card. Desktop: top-right offset from zoom controls */}
<div className="absolute top-14 sm:top-2 right-2 sm:right-12 z-10 flex flex-col items-end gap-2"> <div className="absolute top-[52px] left-2 sm:top-2 sm:left-auto sm:right-12 z-10 flex flex-col items-start sm:items-end gap-2">
<PortalBasemapSwitcher value={basemap} onChange={setBasemap} /> <PortalBasemapSwitcher value={basemap} onChange={setBasemap} />
{clickedFeature && selectionMode === "off" && ( {clickedFeature && selectionMode === "off" && (
<div className="bg-background/95 backdrop-blur-sm border rounded-lg shadow-lg w-56 sm:w-64 overflow-hidden"> <div className="bg-background/95 backdrop-blur-sm border rounded-lg shadow-lg w-56 sm:w-64 overflow-hidden">
@@ -1616,19 +1616,21 @@ function HartaContent() {
)} )}
</div> </div>
{/* Bottom: selection toolbar — centered, above attribution */} </div>
<div className="absolute bottom-3 sm:bottom-8 left-1/2 -translate-x-1/2 sm:left-3 sm:translate-x-0 z-30"> )}
<SelectionToolbar {/* Selection toolbar — FIXED at bottom of viewport (always visible when map shown) */}
selectedFeatures={selectedFeatures} {selectedSiruta && !hasNoData && (
selectionMode={selectionMode} <div className="fixed bottom-4 left-1/2 -translate-x-1/2 z-[110]">
onSelectionModeChange={handleSelectionModeChange} <SelectionToolbar
hideEnrichment selectedFeatures={selectedFeatures}
onClearSelection={() => { selectionMode={selectionMode}
mapHandleRef.current?.clearSelection(); onSelectionModeChange={handleSelectionModeChange}
setSelectedFeatures([]); hideEnrichment
}} onClearSelection={() => {
/> mapHandleRef.current?.clearSelection();
</div> setSelectedFeatures([]);
}}
/>
</div> </div>
)} )}
</> </>