Components
Loading preview...
A MapLibre-powered map component with theme-aware basemaps, controlled viewport state, and custom style switching.
npx shadcn@latest add https://21st.dev/r/mapcn/mapcn-map"use client";
import { useEffect, useRef, useState } from "react";
import { Map, type MapRef } from "@/components/ui/mapcn-map";
const styles = {
default: undefined,
openstreetmap: "https://tiles.openfreemap.org/styles/bright",
openstreetmap3d: "https://tiles.openfreemap.org/styles/liberty",
};
type StyleKey = keyof typeof styles;
export default function CustomStylesMapDemo() {
const mapRef = useRef<MapRef>(null);
const [style, setStyle] = useState<StyleKey>("default");
const selectedStyle = styles[style];
const is3D = style === "openstreetmap3d";
useEffect(() => {
mapRef.current?.easeTo({ pitch: is3D ? 60 : 0, duration: 500 });
}, [is3D]);
return (
<div className="flex min-h-screen w-full items-center justify-center overflow-hidden bg-background p-8">
<div className="relative h-[420px] w-full max-w-4xl overflow-hidden rounded-lg border bg-background shadow-sm">
<Map
ref={mapRef}
center={[-0.1276, 51.5074]}
zoom={15}
styles={
selectedStyle
? { light: selectedStyle, dark: selectedStyle }
: undefined
}
/>
<div className="absolute top-2 right-2 z-10">
<select
value={style}
onChange={(e) => setStyle(e.target.value as StyleKey)}
className="rounded-md border bg-background px-2 py-1 text-sm text-foreground shadow"
>
<option value="default">Default (Carto)</option>
<option value="openstreetmap">OpenStreetMap</option>
<option value="openstreetmap3d">OpenStreetMap 3D</option>
</select>
</div>
</div>
</div>
);
}
export { CustomStylesMapDemo };