Map Popup
terrae/popupFreeComponent
Info popups and tooltips for map locations.
Install it
npx shadcn@latest add https://www.terrae.dev/popup.jsonSource
1"use client"23import type mapboxgl from "mapbox-gl"4import type { PopupOptions } from "mapbox-gl"5import { mapgl } from "./map-library"6import { useEffect, useMemo, useRef, type ReactNode } from "react"7import { createPortal } from "react-dom"8import { X } from "lucide-react"9import { cn } from "@/lib/utils"10import { useMap } from "./hooks"11import type { MapCoordinates } from "./types"1213type MapPopupProps = {14 /** Coordinates [longitude, latitude] for popup position */15 coordinates: MapCoordinates16 /** Callback when popup is closed */17 onClose?: () => void18 /** Popup content */19 children: ReactNode20 /** Additional CSS classes for the popup container */21 className?: string22 /** Show a close button in the popup (default: false) */23 closeButton?: boolean24} & Omit<PopupOptions, "className" | "closeButton">2526export function MapPopup({27 coordinates,28 onClose,29 children,30 className,31 closeButton = false,32 ...popupOptions33}: MapPopupProps) {34 const { map } = useMap()35 const popupRef = useRef<mapboxgl.Popup | null>(null)3637 const container = useMemo(() => document.createElement("div"), [])3839 useEffect(() => {40 if (!map || !map.isStyleLoaded()) return4142 const popup = new mapgl.Popup({43 offset: 16,44 ...popupOptions,45 closeButton: false,46 className: "custom-map-popup",47 })48 .setMaxWidth("none")49 .setDOMContent(container)50 .setLngLat(coordinates)51 .addTo(map)5253 const onCloseProp = () => onClose?.()5455 popup.on("close", onCloseProp)5657 popupRef.current = popup5859 return () => {60 popup.off("close", onCloseProp)61 popup.remove()62 popupRef.current = null63 }64 }, [map, coordinates, popupOptions, onClose, container])6566 return createPortal(67 <div68 className={cn(69 "relative rounded-md border bg-popover p-3 text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95",70 className71 )}72 >73 {closeButton && (74 <button75 type="button"76 onClick={() => {77 popupRef.current?.remove()78 onClose?.()79 }}80 className="absolute top-1 right-1 z-10 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"81 aria-label="Close popup"82 >83 <X className="h-4 w-4" />84 <span className="sr-only">Close</span>85 </button>86 )}87 {children}88 </div>,89 container90 )91}
What it pulls in
npm packages
Other registry items
Files it writes
More from terrae
All 40 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Map Animated Circleanimated-circle | terrae | Components | Free | 1 dep | |
| Map Animated Footprintanimated-footprint | terrae | Components | Free | 2 deps | |
| Map Animated Polygonanimated-polygon | terrae | Components | Free | 1 dep | |
| Map Animated Pulseanimated-pulse | terrae | Components | Free | 1 dep | |
| Map Arc Animatedarc-animated | terrae | Components | Free | 1 dep | |
| Map Blur Areablur-area | terrae | Components | Free | 1 dep | |
| Map Camera Followcamera-follow | terrae | Components | Free | 1 dep | |
| Map Choroplethchoropleth | terrae | Components | Free | 1 dep |
