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

Map styles

A map style is the document the map loads, with its sources and layers. This guide covers which of TomTom's built-in styles loads, its optional traffic and terrain parts, its label language, and switching styles at runtime. To adjust the loaded style, such as its label sizes, road widths, colours or 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', // 'streetLight' when left out
});
Style ID Look
streetLight (default), streetDark Full-detail map, light or dark
streetLightDriving, streetDarkDriving Tuned for in-car navigation
monoLight, monoDark Minimal monochrome
streetSatellite Satellite imagery, with the vector roads and labels drawn over it

Each ID is the camelCase name of the TomTom Orbis style it loads. For example, streetLightDriving loads basic_street-light-driving. standardStyleIDs lists them all, typed StandardStyleID. Use it to fill a style picker.

The map loads only these styles. To give one your brand's look, restyle it at runtime with the Styling Foundations module and map colours. The changes survive style switches.

Dynamic style switching

await map.setStyle('streetDark');
// 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. For the resolved MapLibre style with the knobs applied, use exportStyle.

Keeping or dropping state

By default, a style switch carries everything over. That means module data and configuration (routes, places, POI filters, traffic visibility…) and the previous style's parts (traffic, terrain). For a clean switch, pass resetState: true:

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

// 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('streetDark', { 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. Use it to preserve custom layers, sync UI state or re-create 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, such as 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.

A style change removes the sources and layers you add through map.mapLibreMap. 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 whether the style is light or dark:

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 SDK hands the new style to MapLibre, and the setStyle promise 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

To pick them, use include. Leave it out to load all of them, or pass [] to load none:

const map = new TomTomMap({
    mapLibre: { container: 'map' },
    style: { type: 'standard', id: 'streetLight', 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. The traffic incident descriptions follow it too.

Related guides and examples

Core map setup

Practical examples