AdminKitDocs
Plugins

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:

src/components/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:

src/app/(dashboard)/maps-vector/page.tsx
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

PropTypeDefaultDescription
map"world" | "us_aea_en"The map; "us_aea_en" is PRO only
options(theme: Theme) => VectorMapOptionsjsVectorMap'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

Pro

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: false keeps the page scrolling when the pointer is over the map.
  • The skeleton is aria-hidden="true".

Last updated on

On this page