World map
block / marketing
A flat dotted world map whose highlighted cities are dots of the field itself, snapped onto the lattice and lit inside two rings — with beams travelling the routes between them.
- type
- block
- files
- 2
- registry deps
- skeleton, @automindz/world-dots
- npm deps
- none
installs
- components/automindz/world-map.tsx
- styles/automindz-worldmap.css
- One path for five thousand dots — a run per row, stamped by a zero-length dash pattern
- A marker is one of those dots, snapped onto the lattice; the land dot under it goes
- Two flat rings at 2.25 and 3.25 land-dot radii mark it, not its size
- Markers draw from --automindz-worldmap-marker, defaulting to your own --primary
- Labels are opt-in — the marker list underneath is the content either way
Edit lib/automindz/world-dots.ts, not the component, and pass it — config has no default here (<WorldMap config={WORLD_MARKERS} />). Markers are { lat, lng, label?, size?, id? }; arcs address a marker by its id, or by its index if it has none. The stylesheet is not optional: add import "@/styles/automindz-worldmap.css" to your root layout once, or nothing moves. Skipping it is safe, never blank — the dots are a stroke-dasharray presentation attribute on the component's own path, so the land, the markers with their rings and every route are still drawn end to end; that is also the prefers-reduced-motion path. **A marker is one of the map's own dots, lit — never a pin dropped on top of them.** Its latitude and longitude are snapped to the nearest lattice position by snapToLattice, preferring one that already has a land dot so a coastal city does not round into open water, and that dot is punched out of the land path — so the pitch of the field runs unbroken through the marker instead of an extra dot appearing in the gap between four others. The disc is 1.1 land-dot radii and what marks the place is its colour and two flat concentric rings at 2.25 and 3.25 radii, not its size. All grid units, so the ratios hold at every step instead of being fixed radii that only look right at one spacing. The snap never moves a marker more than one cell, so a point with no land dot near it — an island smaller than step, a marker in mid-ocean, one outside the drawn latitude band — lights its own containing cell rather than being dragged to a coast; and two markers that fall in the same cell take neighbouring dots, in declaration order. **The markers are the one thing here that takes your brand colour.** They draw from --automindz-worldmap-marker, which falls back to your own --primary and then to currentColor — so a client whose brand is orange gets orange markers with no code change, and one line moves them anywhere else: className="[--automindz-worldmap-marker:var(--color-emerald-500)]". The land and the routes stay currentColor, so text-primary retints the drawing. Nothing inside the component names a colour. **Labels are off by default** — pass labels to paint the pills. They are decorative: every marker's name is a real list item underneath either way, and that list plus the route list are the accessible content of the item, so pass label to name them (the drawing itself is aria-hidden). Turn labels on and both survival rules come with it: every pill drops to sr-only below 34rem of container width — a literal in the component, not a dial, because a container query condition cannot read a custom property — and two markers closer than a pill's width lose the second pill, in declaration order, so move a marker up the list to win its label. **The box is always a 2:1 equirectangular frame of the whole planet**, whatever south/north you draw dots between, so lat, lng → x, y is two divisions and the empty space above and below the dots is real latitude rather than padding — the default band drops Antarctica. **No route crosses the ±180 seam**: Tokyo to Los Angeles is drawn the long way, because a split arc is two subpaths and a dash pattern restarts at every subpath, so the beam would appear on both halves at once. Routes that cannot be drawn land in resolveWorldMap's skipped array with a reason (unknown-marker, self, duplicate). **The traffic cadence is capped, not documented**: worldCycle() stretches the cycle until every route is crossed at 1.5Hz or slower, so set it with the cycle prop and never by overriding --automindz-worldmap-cycle, which the component writes and the per-route phases are already measured against. Dials: --automindz-worldmap-marker, --automindz-worldmap-glow (the ink in a marker's inner ring; the outer one is a fraction of it), --automindz-worldmap-dot, --automindz-worldmap-land, --automindz-worldmap-rail, --automindz-worldmap-beam.
Variations
one state per section
- 01Eight cities, six routes
- 02Markers on a brand colour
- 03Coarser land, tinted
- 04Three cities on top of each other
- 05Narrow: pills drop, markers stay
- 06A config with three mistakes in it
- 07Nothing pinned
- 08Loading
Eight cities, six routes
The land is one <path> of five thousand dots — a run of dots per row, stamped by a zero-length dash pattern — and the beams travel the routes on one shared clock, each on its own phase. A marker is one of those dots, lit: its latitude and longitude are snapped to the nearest lattice position and the land dot there is taken out of the path, so zoom in and the pitch runs unbroken through it. Two flat rings mark it, not its size. No pills: labels is off by default.
- San Francisco
- New York
- São Paulo
- London
- Cape Town
- Mumbai
- Singapore
- Sydney
- San Francisco to New York
- London to New York
- New York to São Paulo
- São Paulo to Cape Town
- London to Cape Town
- London to Mumbai
- Mumbai to Singapore
Markers on a brand colour
The markers draw from --automindz-worldmap-marker, which falls back to the consumer's own --primary — so a client whose brand is orange gets this with no code change. Here the docs site points it at a colour from the outside; nothing inside the component names one. labels on as well.
- San Francisco
- New York
- São Paulo
- London
- Cape Town
- Mumbai
- Singapore
- Sydney
- San Francisco to New York
- London to New York
- New York to São Paulo
- São Paulo to Cape Town
- London to Cape Town
- London to Mumbai
- Mumbai to Singapore
Coarser land, tinted
step={3} thins the field to a stipple that still reads as continents, and text-primary retints the land and the routes — the markers keep their own ink. The marker and both its rings are ratios of a land dot, not fixed radii, so the whole mark thins with the field and stays on the coarser lattice.
- San Francisco
- New York
- São Paulo
- London
- Cape Town
- Mumbai
- Singapore
- Sydney
- San Francisco to New York
- London to New York
- New York to São Paulo
- São Paulo to Cape Town
- London to Cape Town
- London to Mumbai
- Mumbai to Singapore
Three cities on top of each other
With labels on: London, Paris and Amsterdam are closer together than one line of text, so only the first of them keeps a painted pill — the other two are still list items, still read out, still found by a page search. Singapore carries size: 1.6, and its rings scale with it. Two cities that snap to the same lattice cell take neighbouring dots instead of one being drawn twice.
- London
- Paris
- Amsterdam
- Singapore
- London to Singapore
Narrow: pills drop, markers stay
Below 34rem of the map's own width every pill drops to sr-only at once, because eight of them are comfortable at 900px and a pile at 400. The dots never collide — their spacing, their size and the markers' are all grid units, so they scale together.
- San Francisco
- New York
- São Paulo
- London
- Cape Town
- Mumbai
- Singapore
- Sydney
- San Francisco to New York
- London to New York
- New York to São Paulo
- São Paulo to Cape Town
- London to Cape Town
- London to Mumbai
- Mumbai to Singapore
A config with three mistakes in it
A route declared twice, a route from a place to itself, and a route to an id that does not exist. One arc survives; the rest land in resolveWorldMap's skipped array with a reason instead of being drawn wrong. Tokyo has no id, so its index addresses it.
- New York
- São Paulo
- Tokyo
- Tokyo to New York
Nothing pinned
An empty config still renders the map, because a map with nothing on it is still a map. No marker list and no route list are emitted at all rather than two empty ones.
Loading
The skeleton is the same 2:1 box the map fills, so nothing moves when the data lands. The frame is aria-busy and holds its height.
