Next.js Vector Map
A Next.js vector map for the App Router: jsVectorMap in a client component, fed marker data from a server component page, with colors that follow dark mode.
A map with markers tells people at a glance where your offices, sales or visitors are. VectorMap draws such a map as interactive SVG, with zoom buttons and markers in the colors of your theme. It is built on jsVectorMap 1.7.
The map ships with the free and PRO versions of AdminKit for Next.js. Both have the world map, and AdminKit PRO also has a map of the United States.
jsVectorMap needs the browser, so VectorMap is a client component, a file that starts with "use client". On the server and in the static export, it renders a skeleton and an empty <div>. After hydration, when the browser has taken over the HTML that Next.js built, an effect imports jsVectorMap and the map data and draws the map. You don't need next/dynamic. The component takes a function of the theme colors instead of fixed options, like the chart components.
Example
options is a function, and a server component cannot pass a function to a client component. So write a small client component that owns the options and takes the data as props. The demo's MarkerMap does this, in src/components/pages/maps/vector/marker-map.tsx:
"use client";
import { VectorMap } from "@/components/plugins/vector-map";
export function MarkerMap({
map,
markers,
}: {
map: "world" | "us_aea_en";
markers: { coords: [number, number]; name: string }[];
}) {
return (
<div className="position-relative" style={{ height: 350 }}>
<VectorMap
map={map}
className="h-100"
options={(theme) => ({
zoomButtons: true,
zoomOnScroll: false,
markers,
markerStyle: {
initial: { r: 9, stroke: theme.white, strokeWidth: 7, fill: theme.primary },
hover: { fill: theme.primary, stroke: theme.primary },
},
regionStyle: {
initial: { fill: theme["gray-200"] },
},
})}
/>
</div>
);
}The page passes plain data, so it stays a server component:
import { MarkerMap } from "@/components/marker-map";
import { pageMetadata } from "@/lib/site";
export const metadata = pageMetadata("/maps-vector");
const offices: { coords: [number, number]; name: string }[] = [
{ coords: [51.507351, -0.127758], name: "London" },
{ coords: [40.7127837, -74.0059413], name: "New York" },
{ coords: [35.689487, 139.691711], name: "Tokyo" },
{ coords: [6.524379, 3.379206], name: "Lagos" },
{ coords: [19.075983, 72.877655], name: "Mumbai" },
];
export default function Page() {
return (
<div className="card">
<div className="card-body">
<MarkerMap map="world" markers={offices} />
</div>
</div>
);
}The position-relative wrapper with a height sizes both the skeleton and the map. className="h-100" makes the map fill it.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
map | "world" | "us_aea_en" | The map; "us_aea_en" is PRO only | |
options | (theme: Theme) => VectorMapOptions | jsVectorMap's options, without selector and map |
id, className, aria-* and the other <div> props go to the map element. The component is in src/components/plugins/vector-map.tsx.
Colors and dark mode
The theme argument holds the colors of the current mode, such as theme.primary and theme["gray-200"]. Dark mode lists them. The theme is only known in the browser, which is one more reason the map draws after hydration. When the mode changes, the component calls options again and applies its regionStyle.initial and markerStyle.initial. The rest of the options, such as markers, are read once, when the map is created.
The component resizes the map with the window. It destroys the map when it leaves the page, for example when you navigate to another page.
United States map
This map is only available in AdminKit PRO. Learn more.
For data about the US, a map of the states says more than the world map. map="us_aea_en" draws them, as on the e-commerce dashboard and the vector maps demo:
<MarkerMap
map="us_aea_en"
markers={[
{ coords: [37.77, -122.41], name: "San Francisco: 375" },
{ coords: [40.71, -74.0], name: "New York: 350" },
{ coords: [32.77, -96.79], name: "Dallas: 225" },
]}
/>Other maps
You can add more maps from jsVectorMap's collection. Each map is a file in src/components/plugins/vector-maps/ that registers itself with jsVectorMap. To add one, copy its file there, with a .d.ts file like the others. Then add an entry to the maps object in vector-map.tsx. Its key is the name the file passes to jsVectorMap.addMap().
Accessibility
- The SVG map has no text alternative. Show the same data as text too, for example a list of the markers.
zoomOnScroll: falsekeeps the page scrolling when the pointer is over the map.- The skeleton is
aria-hidden="true".
Related
- React Vector Map: the same component in AdminKit for React (Vite)
- Bootstrap 5 vector map: the same plugin in the HTML version
- Bootstrap 5 dark mode:
adminkit.vectorMap()in the HTML version - Charts: the chart components that share the theme function
- Vector maps demo
Last updated on
Rich text editorPro
A Next.js Quill editor for the App Router and React 19: plain Quill 2 in a client component that server pages can render, with snow and bubble themes.
Drag and dropPro
Next.js drag and drop with dnd kit in a client component: the AdminKit PRO task board, hydration-safe ids and overlay, and mouse, touch and keyboard sorting.