Theming

Every piece of chrome ApexMaps draws itself, the legend, tooltip, breadcrumb and attribution, reads its colors from CSS custom properties on the map's container. A host dashboard restyles the map by setting those properties, with no options tree involved at all.

#dashboard-map {
  --apexmaps-surface: #1e1b4b;
  --apexmaps-focus: #f472b6;
}

Dark mode

theme.mode is 'light', 'dark', or 'auto':

theme: { mode: 'dark' }

Dark mode is applied as a class (apexmaps--dark) on the container rather than only through a prefers-color-scheme media query, so a dashboard can force it independently of the operating system. 'auto' follows the OS setting via prefers-color-scheme. What changes between light and dark is the chrome, the no-data color and the text; the data palette itself (scale.palette) is unchanged, since a blues choropleth should read as the same blues choropleth in either mode.

theme.palette sets a default PaletteName for series that don't name their own, useful for keeping every series on a map consistent without repeating scale: { palette: 'x' } on each one.

The --apexmaps-* custom property surface

These are the variables the library itself reads. Override any of them on the map's container, or globally on :root, and every component that uses that variable follows.

VariableUsed forLight defaultDark default
--apexmaps-fgPrimary text (legend, breadcrumb, tooltip title)#1f2933#e5e7eb
--apexmaps-fg-mutedSecondary text (tooltip labels, breadcrumb items)#6b7280#9ca3af
--apexmaps-bgContainer backgroundtransparenttransparent
--apexmaps-surfaceTooltip and card backgrounds#ffffff#1f2937
--apexmaps-borderBorders, legend item hover, swatch outlinesrgba(0,0,0,0.12)rgba(255,255,255,0.16)
--apexmaps-shadowTooltip drop shadow0 4px 16px rgba(15,23,42,0.14)0 4px 16px rgba(0,0,0,0.5)
--apexmaps-focusFocus ring, selection box outline, active legend accents#2563eb#60a5fa
--apexmaps-radiusTooltip and legend swatch corner radius6px6px
--apexmaps-font-sizeBase font size for legend, tooltip, breadcrumb12px12px

--apexmaps-focus doubles as the selection box color (.apexmaps-select-box strokes and fills with it), so a rebrand that changes the accent color updates the box-selection rectangle for free.

#branded {
  --apexmaps-fg: #f8fafc;
  --apexmaps-fg-muted: #cbd5f5;
  --apexmaps-surface: #1e1b4b;
  --apexmaps-border: rgba(255, 255, 255, 0.24);
  --apexmaps-focus: #f472b6;
  --apexmaps-radius: 2px;
  --apexmaps-font-size: 13px;
}
// No theme option set at all: the container's CSS alone drives the legend,
// tooltip and attribution.
new ApexMaps(document.getElementById('branded'), {
  chart: { height: 320, background: 'transparent' },
  geo: { map: 'eu/nuts0@20m' },
  series: [{ name: 'Adoption', joinBy: ['nuts_id', 'key'], data, scale: { palette: 'magma' } }],
})

Two variables outside this table are written by the engine rather than meant for you to set directly: --apexmaps-anim and --apexmaps-anim-geom pace the fill and geometry transitions from chart.animations.speed, and zero out automatically under prefers-reduced-motion.

Responsive rules

responsive swaps in a different slice of options once the map's measured container width crosses a breakpoint, the same shape as ApexCharts' own responsive array:

responsive: [
  { breakpoint: 560, options: { legend: { position: 'bottom' }, dataLabels: { enabled: false } } },
  { breakpoint: 900, options: { legend: { position: 'right' } } },
]

Rules match against measured width rather than viewport width, and the narrowest matching breakpoint wins, so they can be declared in any order. This is what a map should do at that width, not a media query in disguise: a map that is half of a two-column dashboard row is "narrow" long before the browser viewport is, and responsive reacts to the box the map is actually in.

map.on('resized', () => {
  console.log(map.viewport.width, map.config.legend.position)
})

An explicit width on the container (chart.width: '100%' on a sized parent, not an unconstrained flex or grid item) matters here: a resizable box that reports its intrinsic max-content width will size the map to that instead of to the page, and no breakpoint will ever fire.

See also