Dotted Map
A component with a svg dotted map.
import type { TCountryCode } from 'countries-list'import type { Marker } from '@/registry/magicui/dotted-map'import { DottedMap } from '@/registry/magicui/dotted-map'
type CountryCode = Lowercase<TCountryCode>
type MyMarker = Marker & { overlay: { countryCode: CountryCode label: string }}
const markers: MyMarker[] = [ { lat: 37.5665, lng: 126.978, size: 2.8, overlay: { countryCode: 'kr', label: 'Seoul' }, }, { lat: 40.7128, lng: -74.006, size: 2.8, overlay: { countryCode: 'us', label: 'NYC' }, },]
export function DottedMapDemo() { return ( <div class="relative h-125 w-full overflow-hidden rounded-lg border"> <div class=" absolute inset-0 bg-radial from-transparent to-background to-200% " /> <DottedMap<MyMarker> markers={markers} renderMarkerOverlay={({ marker, x, y, r }) => { const { countryCode, label } = marker.overlay const href = `https://flagcdn.com/w80/${countryCode}.webp`
const imgR = r * 0.75
const fontSize = r * 0.9 const pillH = r * 1.5 const pillW = label.length * (fontSize * 0.62) + r * 1.4 const pillX = x + r + r * 0.6 const pillY = y - pillH / 2
return ( <g style={{ 'pointer-events': 'none' }}> <image href={href} x={x - imgR} y={y - imgR} width={imgR * 2} height={imgR * 2} preserveAspectRatio="xMidYMid slice" style={{ 'clip-path': 'circle(50% at 50% 50%)' }} />
<rect x={pillX} y={pillY} width={pillW} height={pillH} rx={pillH / 2} fill="rgba(0,0,0,0.55)" /> <text x={pillX + r * 0.7} y={y + fontSize * 0.35} style={{ 'font-size': `${fontSize}px` }} fill="white" > {label} </text> </g> ) }} /> </div> )}Installation
Section titled “Installation”pnpm dlx shadcn@latest add @magicui-solid/dotted-mapbunx shadcn@latest add @magicui-solid/dotted-mapyarn dlx shadcn@latest add @magicui-solid/dotted-mapnpx shadcn@latest add @magicui-solid/dotted-mapExamples
Section titled “Examples”Smaller Dots
Section titled “Smaller Dots”import { DottedMap } from '@/registry/magicui/dotted-map'
export function DottedMapDemo2() { return ( <div class="relative h-125 w-full overflow-hidden rounded-lg border"> <DottedMap dotRadius={0.1} /> </div> )}Pulse Marker
Section titled “Pulse Marker”import type { Marker } from '@/registry/magicui/dotted-map'import { DottedMap } from '@/registry/magicui/dotted-map'
const markers: Marker[] = [ { lat: 37.5665, lng: 126.978, size: 0.3, }, { lat: 40.7128, lng: -74.006, size: 0.3, pulse: false, },]
export function DottedMapDemo3() { return ( <div class="relative h-125 w-full overflow-hidden rounded-lg border"> <div class=" absolute inset-0 bg-radial from-transparent to-background to-200% " /> <DottedMap markers={markers} pulse /> </div> )}Import
Section titled “Import”import { DottedMap } from '@/components/magicui/dotted-map'<div class="relative h-[400px] w-full overflow-hidden rounded-xl border"> <DottedMap /></div>With Custom Markers
Section titled “With Custom Markers”import { DottedMap, type Marker } from '@/components/magicui/dotted-map'import type { TCountryCode } from 'countries-list'
type CountryCode = Lowercase<TCountryCode>
type MyMarker = Marker & { overlay: { countryCode: CountryCode label: string }}
const markers: MyMarker[] = [ { lat: 37.5665, lng: 126.978, size: 2.8, overlay: { countryCode: 'kr', label: 'Seoul' }, },]
<DottedMap<MyMarker> markers={markers} renderMarkerOverlay={({ marker, x, y, r }) => { // Custom overlay rendering return <text x={x} y={y}>{marker.overlay.label}</text> }}/>| Prop | Type | Default | Description |
|---|---|---|---|
width |
number |
150 |
Width of the SVG map. |
height |
number |
75 |
Height of the SVG map. |
mapSamples |
number |
5000 |
Number of sample points for map generation. |
markers |
Marker[] |
[] |
Array of markers to display on the map. |
dotColor |
string |
currentColor |
Color of the map dots. |
markerColor |
string |
"#FF6900" |
Color of the markers. |
dotRadius |
number |
0.2 |
Radius of the map dots. |
stagger |
boolean |
true |
Whether to stagger dots in alternating rows for visual effect. |
pulse |
boolean |
false |
Enables built-in pulse animation for markers. |
renderMarkerOverlay |
(args) => JSX.Element |
undefined |
Custom render function for marker overlays. |
className |
string |
undefined |
Additional class names applied to the SVG. |
style |
CSSProperties |
undefined |
Inline styles merged into the SVG. |
Marker
Section titled “Marker”interface Marker { lat: number lng: number size?: number pulse?: boolean}Set pulse on DottedMap to animate all markers (and use marker.pulse = false to opt out per marker). Without the pulse prop, only markers with marker.pulse = true will pulse.
The DottedMap component supports generic types, allowing you to extend the Marker interface with custom properties:
import type { TCountryCode } from 'countries-list'
type CountryCode = Lowercase<TCountryCode>
type MyMarker = Marker & { overlay: { countryCode: CountryCode label: string }}
<DottedMap<MyMarker> markers={markers} />Original:
magicui.design/docs/components/dotted-map