Skip to Content
ExamplesAdd map controller with controls

Maps UI SDK - Add a map controller with controls

This example demonstrates how to set up a basic map with controls UI controls using the MapsGL Map Controller Provider.

Key Features

  • Basic map initialization with Mapbox GL
  • MapsGL controller integration
  • Zoom in/out controls
  • Data inspector
  • Geolocation support

Implementation

The map controller uses several components working together. Here’s how to implement it:

  1. First, create the basic map component with Mapbox initialization:
import { useState, useRef } from 'react'; export const App = () => { const [map, setMap] = useState<mapboxgl.Map | null>(null); const containerRef = useRef<HTMLDivElement>(null); // Initialize map useEffect(() => { mapboxgl.accessToken = 'YOUR_MAPBOX_KEY'; const mapEl = new mapboxgl.Map({ container: containerRef.current || '', style: 'mapbox://styles/mapbox//streets-v10', center: [-74.5, 40], zoom: 3 }); setMap(mapEl); }, []); return ( <div ref={containerRef} className="w-full h-full" /> ); }
  1. Add the MapsGLMapControllerProvider to enable map interactions. Optionally, wrap your application in the Anchor.Position component for global positioning styles:
import { MapsGLMapControllerProvider, Anchor } from '@xweather/maps-ui-sdk'; export const App = () => { const [map, setMap] = useState<mapboxgl.Map | null>(null); const containerRef = useRef<HTMLDivElement>(null); // ... map initialization ... return ( <Anchor.Position offset={12}> <MapsGLMapControllerProvider accessKeys={accessKeys} strategy="mapbox" map={map} > {/* Control panel will go here */} </MapsGLMapControllerProvider> <div ref={containerRef} className="w-full h-full" /> </Anchor.Position> ); }
  1. Create a button component for the controls with the IconButton component:
import { IconButton, IconProps } from '@xweather/maps-ui-sdk'; interface MapControlButtonProps { icon: ComponentType<IconProps>; isActive?: boolean; onClick: () => void; } const MapControlButton = ({ icon, onClick, isActive }: MapControlButtonProps) => { const classNameBase = 'rounded-md hover:text-white text-2xl text-[#C1C7CD] size-7'; const activeClass = isActive ? 'border-2 border-[#4ED9C2]' : ''; return ( <IconButton className={`${classNameBase} ${activeClass}`} icon={icon} onClick={onClick} /> ); };
  1. Create a specialized GeoLocate button with loading state.

The GeoLocate button is a special case that requires handling an asynchronous operation. We’ll add a LoadingSpinner to provide visual feedback while waiting for the browser’s Geolocation API :

import { useState } from 'react'; import { HStack, LoadingSpinner, getCurrentLocation, GeoLocateIcon } from '@xweather/maps-ui-sdk'; const GeoLocateButton = ({ map }) => { // Track loading state for geolocation request const [isLoading, setIsLoading] = useState(false); const handleGeoLocate = async () => { try { setIsLoading(true); // Use the utility function to access browser geolocation const { lat, lon } = await getCurrentLocation(); // Animate the map to the user's location map?.flyTo({ center: [lon, lat], essential: true, zoom: 7 }); } catch (error) { console.error('Error getting location:', error); } finally { setIsLoading(false); } }; return ( <HStack className="relative items-center justify-center"> {isLoading && <LoadingSpinner className="absolute" size={34} />} <MapControlButton icon={GeoLocateIcon} onClick={handleGeoLocate} /> </HStack> ); };

This component:

  • Uses React’s useState to track the geolocation loading state
  • Shows a loading spinner while waiting for the geolocation request
  • Uses the getCurrentLocation utility which handles the geolocation request and browser permissions, returning the user’s current location if successful
  • Animates the map to the user’s location when coordinates are received
  • Handles errors gracefully and ensures the loading spinner is always removed when the operation completes
  1. Finally, implement the control panel component by combining the MapControlButton and GeoLocateButton with the useMapsGLMapControllerContext hook.
import { useMapsGLMapControllerContext } from '@xweather/maps-ui-sdk'; const MapControlPanel = () => { const { map, toggleDataInspector, isDataInspectorVisible } = useMapsGLMapControllerContext(); return ( <Anchor.BottomLeft offsetY={40} className="z-10"> <VStack className="bg-black rounded-xl p-2 gap-1.5"> <MapControlButton icon={AddIcon} onClick={() => map?.zoomIn()} /> <MapControlButton icon={SubtractIcon} onClick={() => map?.zoomOut()} /> <MapControlButton icon={TargetIcon} onClick={() => toggleDataInspector('move', true)} isActive={isDataInspectorVisible} /> <GeoLocateButton map={map} /> </VStack> </Anchor.BottomLeft> ); };

This component:

  • Provides zoom controls for adjusting the map view
  • Includes a data inspector toggle that can be activated on click or mouse move
  • Uses the isDataInspectorVisible state to style the inspector button when active
  • Integrates the GeoLocate button we created in the previous step
  • Positions all controls consistently in an accessible location on the map
© 2026 Xweather (opens in a new tab)Terms of Service (opens in a new tab)Privacy Policy (opens in a new tab)