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

Map theme plugin

The Map Theme plugin themes a TomTomMap from any source of a look, such as a brand's swatches, your page's CSS, a logo, a photo, a mood or an artist. It turns the source into the ten map colours for land, water, roads and labels, plus the accent that routes, geometries and pins take. setMapColors applies them to the whole map.

What it is for

Every source comes down to a handful of colours, and one call assigns them their roles:

The look comes from Call
A brand guide, a palette, colours a user picked deriveMapColors(colors)
Your own page's CSS deriveMapColors over its custom properties
A stylesheet: a website's, a design system's tokens deriveMapColorsFromCss(cssText)
A logo, a photo, a poster deriveMapColorsFromImage(image)
A mood, an artist a coding agent or the Agent Toolkit writes the colours, then deriveMapColors

Installation

npm install @tomtom-org/maps-sdk maplibre-gl culori @tomtom-org/maps-sdk-plugin-map-theme

@tomtom-org/maps-sdk and culori are peer dependencies. Every function is pure. Deriving needs no backend and no map.

From colours

import { StylingFoundationsModule } from '@tomtom-org/maps-sdk/map';
import { deriveMapColors } from '@tomtom-org/maps-sdk-plugin-map-theme';

const styling = await StylingFoundationsModule.get(map);
const colors = deriveMapColors(['#1d3f8a', '#e63312', '#f5d000', '#111111', '#f4f1ea']);
styling.setMapColors(colors);

How colours get their roles

The assignment is deterministic. Order doesn't matter, and near-duplicates count once.

Role Gets
land The lightest low-saturation colour (the darkest on a dark theme), toned down to a neutral
roadMajor The most colourful (highest OKLCH chroma) colour, preferring one that isn't blue or green
water, vegetation A blue or cyan, and a green
label The colour contrasting most with land, if it reaches 4.5:1
accent The most colourful colour left that reads 3:1 on land and sits 30° of hue or more from roadMajor. Otherwise, roadMajor's complement

Light and dark styles

setMapColors re-derives each style's own shades at that style's offsets, so a dark theme over streetLight pushes them to black. mapColorsLightDark(colors) tells a dark theme (labels lighter than land) from a light one, whether 'auto' or the source decided it. Use it to switch the map first:

import { mapColorsLightDark } from '@tomtom-org/maps-sdk-plugin-map-theme';

const lightDark = mapColorsLightDark(colors);
if (lightDark !== map.styleLightDarkTheme) {
    await map.setStyle(lightDark === 'dark' ? 'streetDark' : 'streetLight');
}
styling.setMapColors(colors);

From your page's CSS

To give a map your app's brand, read the page's custom properties and its theme-color, and theme from those.

const css = getComputedStyle(document.documentElement);
const brand = ['--color-primary', '--color-accent', '--color-surface', '--color-text']
    .map((name) => css.getPropertyValue(name).trim())
    .concat(document.querySelector('meta[name="theme-color"]')?.content ?? [])
    .filter(Boolean);

styling.setMapColors(deriveMapColors(brand));

Use your design system's own property names. The plugin reads colours in hex, rgb(), hsl() or a CSS name, and skips anything else.

From a stylesheet

A whole stylesheet works too, such as a website's CSS, a design system's tokens or a file a user uploads. deriveMapColorsFromCss(cssText, { mode, colorCount }) reads the colours it paints with and assigns them roles. It takes the CSS as text, so it needs no DOM.

import { deriveMapColorsFromCss } from '@tomtom-org/maps-sdk-plugin-map-theme';

// A File from an <input type="file" accept=".css">, or CSS a server fetched
styling.setMapColors(deriveMapColorsFromCss(await fileInput.files[0].text()));

cssColors(cssText) returns the colours, most used first, without assigning roles, so the user can edit them first.

From an image

import { deriveMapColorsFromImage } from '@tomtom-org/maps-sdk-plugin-map-theme';

// A File from an <input type="file">, a Blob, an <img>, an ImageBitmap or a CORS-readable URL
styling.setMapColors(await deriveMapColorsFromImage(fileInput.files[0], { mode: 'dark' }));

From a mood, an artist or a website you cannot read

A mood has no colours to read. A page can't fetch another origin's CSS either, though a server can fetch it and hand it to deriveMapColorsFromCss. So these start with a model, not a function:

Limits

API reference

deriveMapColors · mapColorsLightDark · deriveMapColorsFromCss · cssColors · deriveMapColorsFromImage · dominantColors · mapThemeModes

Related guides and examples