Map

The map container. Handles Mapbox GL setup, light/dark theming, Standard styles, and provides context for child components.

Basic Usage

Wrap your map in <Map>. It reads your token from NEXT_PUBLIC_MAPBOX_TOKEN and follows the document theme automatically.

import { Map } from "@/components/ui/map";

export function BasicMapExample() {
  return (
    <div className="h-[420px] w-full">
      <Map center={[-97.7431, 30.2672]} zoom={11} />
    </div>
  );
}

Theming

By default <Map> follows your site theme: it watches the light / dark class on <html> (the one next-themes toggles) and swaps the basemap live. No configuration needed.

To pin the basemap to a fixed theme and stop it reacting to site theme changes, pass theme:

<Map theme="dark" />

To change which Mapbox style each theme maps to, pass styles:

<Map
  styles={{
    light: "mapbox://styles/mapbox/streets-v12",
    dark: "mapbox://styles/mapbox/dark-v11",
  }}
/>
Heads up: a pinned theme is the off switch for automatic theme following - the map will ignore the document theme entirely until you remove it.

Styles & Modes

Theme switching is for light/dark basemaps. To pin a single fixed style regardless of theme - including the 3D Standard style - pass mapStyle. It takes precedence over theme / styles and turns off automatic swapping.

<Map mapStyle="mapbox://styles/mapbox/standard" />

The Standard style ships four light presets - day, dusk, dawn, night. Set one with lightPreset; it is re-applied across style swaps and ignored by classic styles that don't expose it.

Here it is live - the buttons swap lightPreset on the same map:

"use client";

import { useState } from "react";

import { Button } from "@/components/ui/button";
import { Map, type LightPreset } from "@/components/ui/map";

const presets: LightPreset[] = ["day", "dusk", "dawn", "night"];

export function MapModesExample() {
  const [preset, setPreset] = useState<LightPreset>("day");

  return (
    <div className="relative h-[420px] w-full">
      <Map
        mapStyle="mapbox://styles/mapbox/standard"
        lightPreset={preset}
        center={[-97.7426, 30.2668]}
        zoom={15.5}
        pitch={55}
        bearing={-20}
      />
      <div className="absolute top-3 left-3 z-10 flex gap-1 rounded-md border bg-background/80 p-1 backdrop-blur">
        {presets.map((value) => (
          <Button
            key={value}
            type="button"
            size="sm"
            variant={preset === value ? "default" : "ghost"}
            className="capitalize"
            onClick={() => setPreset(value)}
          >
            {value}
          </Button>
        ))}
      </div>
    </div>
  );
}
Token note: every style here works on the free Mapbox tier with a public token - no payment required. Switching styles or presets within a session does not cost extra map loads.

Props

Any other mapboxgl.MapOptions (such as center, zoom, pitch) are passed straight to the map.

PropTypeDefaultDescription
theme"light" | "dark"Basemap theme. Follows the document theme when omitted; set it to pin a theme and disable automatic switching.
styles{ light?: string; dark?: string }Override the default Mapbox styles per theme.
mapStylestringA single fixed style URL. Overrides theme/styles and disables automatic swapping.
lightPreset"day" | "dusk" | "dawn" | "night"Light preset for the Standard style. Ignored by styles without one.
accessTokenstringNEXT_PUBLIC_MAPBOX_TOKENMapbox access token.
classNamestringClasses for the map container.