This is the documentation of version 0.64.0. Go to the latest version, 1.0.0-rc.5.

Map styles

A map style is the document the map loads: its sources and layers. This guide covers which style loads — a built-in one or your own, its optional traffic and terrain parts, its label language — and switching it at runtime. To adjust the style that is loaded — label sizes, road widths, colours, a globe — see Map styling.

The demo below switches between the built-in styles:

Built-in styles

Basic styles

import { TomTomMap } from '@tomtom-org/maps-sdk/map';

const map = new TomTomMap({
    mapLibre: { container: 'map' },
    style: 'monoDark', // 'standardLight' when left out
});
Style ID Look
standardLight (default), standardDark Full-detail map, light or dark
drivingLight, drivingDark Tuned for in-car navigation
monoLight, monoDark Minimal monochrome
satellite Satellite imagery, with the vector roads and labels drawn over it

standardStyleIDs lists them all, typed StandardStyleID — use it to fill a style picker.

Custom styles

A custom style (style: { type: 'custom', url } or { type: 'custom', json }) loads as-is:

Styles from Map Maker

TomTom Map Maker is the tool to edit and host your own map styles:

const map = new TomTomMap({
    mapLibre: { container: 'map' },
    style: { type: 'custom', url: 'YOUR_MAP_MAKER_STYLE_URL' },
});

See Introduction to the map style for sources and layers, then Publish and share style and Using style in the application.

Dynamic style switching

await map.setStyle('standardDark');
// map.mapReady is true again; routes, places and traffic are back on the new style

setStyle returns a promise:

map.getStyleInput() returns the style id or object the map was last given — not the resolved MapLibre style, which exportStyle gives with the knobs applied.

Keeping or dropping state

By default a style switch carries everything over: module data and configuration (routes, places, POI filters, traffic visibility…) and the style parts of the previous style (traffic, terrain). Pass resetState: true for a clean switch instead:

// Carry everything over (default)
map.setStyle('standardDark');

// Clean switch: modules re-bind to the new style with default configuration and nothing shown,
// and only the style parts named in the new style are loaded
map.setStyle('standardDark', { resetState: true });

The demo below switches styles either way, over a map with places, a route and traffic on it:

Listening to style changes

addStyleChangeHandler reacts when a style switch triggered by map.setStyle() begins or completes: the hook for preserving custom layers, syncing UI state, or re-creating anything tied to the current style. It returns an unsubscribe function.

:::note This handler only fires for setStyle calls on TomTomMap, not on the initial style load. For lower-level hooks — the initial load, or any style-related MapLibre event — use map.mapLibreMap.on('styledata', ...) directly. :::

import { TomTomMap, type StyleChangeHandler } from '@tomtom-org/maps-sdk/map';

const map = new TomTomMap({ mapLibre: { container: 'map' } });

const handler: StyleChangeHandler = {
    onStyleAboutToChange: (context) => {
        // Before the switch — clean up anything tied to the current style
    },
    onStyleChanged: (context) => {
        // After the new style has loaded — restore state, re-add layers, update UI.
        // context.resetState tells you whether this is a clean switch.
    },
};
const unsubscribe = map.addStyleChangeHandler(handler);

// Later, when the handler's owner is torn down:
unsubscribe();

Preserving custom MapLibre layers

For your own GeoJSON data, prefer CustomGeoJSONModule: it restores its sources, layers and images after every style change, and gives them SDK events, with no handler to write.

Sources and layers added via map.mapLibreMap are removed when the style changes. Use onStyleAboutToChange to save their data and onStyleChanged to restore them:

import type { GeoJSONSource } from 'maplibre-gl';

let savedData: GeoJSON.FeatureCollection | null = null;

map.addStyleChangeHandler({
    onStyleAboutToChange: () => {
        const source = map.mapLibreMap.getSource('my-data') as GeoJSONSource | undefined;
        if (source) {
            savedData = source._data as GeoJSON.FeatureCollection;
        }
    },
    onStyleChanged: ({ resetState }) => {
        if (savedData && !resetState) {
            map.mapLibreMap.addSource('my-data', { type: 'geojson', data: savedData });
            map.mapLibreMap.addLayer({
                id: 'my-layer',
                type: 'circle',
                source: 'my-data',
                paint: { 'circle-radius': 6, 'circle-color': '#007cbf' },
            });
        }
    },
});

Updating UI based on the active style

map.styleLightDarkTheme reports the theme of the loaded style, custom ones included once loaded:

map.addStyleChangeHandler({
    onStyleChanged: () => {
        document.body.classList.toggle('dark-mode', map.styleLightDarkTheme === 'dark');
    },
});

Async handlers

Both callbacks can be async. The SDK awaits each one before continuing: onStyleAboutToChange handlers finish before the new style is handed to MapLibre, and the promise returned by setStyle resolves only after the last onStyleChanged handler has finished.

map.addStyleChangeHandler({
    onStyleAboutToChange: async () => {
        await persistStateToServer(map.getStyleInput());
    },
    onStyleChanged: async () => {
        await restoreStateFromServer();
    },
});

Available style parts

A standard style has optional parts, each from its own data source. The base map and POIs are always part of it, controlled by BaseMapModule and POIsModule; the others, listed in styleParts, are loaded but hidden until their module shows them:

Style part Data Shown by
trafficIncidents Real-time traffic incidents TrafficIncidentsModule
trafficFlow Real-time traffic flow TrafficFlowModule
terrain Elevation data, for hillshade and 3D terrain TerrainModule

include picks them; leave it out for all of them, pass [] for none:

const map = new TomTomMap({
    mapLibre: { container: 'map' },
    style: { type: 'standard', id: 'standardLight', include: ['trafficFlow', 'terrain'] },
});

Map language

const map = new TomTomMap({
    mapLibre: { container: 'map' },
    language: 'de-DE', // German labels
});

map.setLanguage('nl-NL'); // at runtime

Set it once — here, or in the global configuration — and it holds for the life of the map. Every style arrives with local-language labels, so the SDK re-applies the language after each style load, whether or not the switch carries state over; only setLanguage changes it.

Related guides and examples

Core map setup

Practical examples