Skip to content
NewYour data: charts, lists and meters that take your records
<GeoFlows />ReactMaps & trafficFree

Region traffic

Traffic between regions as dotted curves whose rows and particle rate follow throughput; selecting a region isolates its flows and rolls its totals.

View as Markdown
<GeoFlows />

Tryselect a region, then press Escape to see every flow again.

Your data

Pass your regions as regions and your traffic as flows. Without either the component shows 12 demo cloud regions and 14 demo flows with invented throughput that drifts every 3 s; regions alone shows an empty map. See Your data.

Playground

Change a prop and the component re-renders. Props marked remounts set an initial value, so the component starts over.

Loading <GeoFlows />
Props
projectionlive
livelive
maxParticleslive
unitlive
React
<GeoFlows projection="equalEarth" live maxParticles={400} unit="Gbps" />

Installation

pnpm dlx shadcn@latest add @lumesec/geo-flows
First timeRegister the @lumesec registry once, or install by URL+

Adds @lumesec to your components.json:

pnpm dlx shadcn@latest registry add @lumesec=https://elements.lumesec.ai/r/{name}.json

Or skip the setup and install by URL:

npx shadcn@latest add https://elements.lumesec.ai/r/geo-flows.json

Usage

geo-flows-example.tsx
"use client";

import * as React from "react";

import { GeoFlows, type FlowRegion, type RegionFlow } from "@/components/lumesec/geo-flows";

const regions: FlowRegion[] = [
  { id: "fra", label: "Frankfurt", lat: 50.11, lon: 8.68 },
  { id: "iad", label: "Ashburn", lat: 39.04, lon: -77.49 },
  { id: "sin", label: "Singapore", lat: 1.35, lon: 103.82 },
];

export function Example({ flows }: { flows: RegionFlow[] }) {
  const [region, setRegion] = React.useState<string | null>(null);
  return <GeoFlows regions={regions} flows={flows} value={region} onValueChange={setRegion} unit="Gbps" />;
}

Behaviour

Traffic between regions as dotted curves whose width and particle rate follow throughput. Downstream runs in the accent colour and upstream in the info colour, each bending to its own side of the line.

Select a region and its flows stay lit while all others collapse to hairlines and drain; the inbound and outbound totals roll to that region's numbers.

API reference

Props

Also accepts every prop of <div> (React.ComponentProps<"div">), spread onto the root element.

regionsTypereadonly FlowRegion[]Default12 demo regions

The regions on the map: { id, label, lat, lon }. Regions with a repeated id or a non-finite coordinate are skipped.

flowsTypereadonly RegionFlow[]Default14 demo flows

Traffic between regions: { from, to, down, up } with region ids and throughput in unit. down runs from from to to, up the other way. Flows that name an unknown region or carry no traffic are skipped; an empty array shows an empty map.

valueTypestring | null

Selected region id (controlled), or null for none. Use with onValueChange.

defaultValueTypestring | nullDefaultnull

Selected region when uncontrolled.

onValueChangeType(value: string | null) => void

Called with the region id when a region is selected, and with null when the selection is cleared.

unitTypestringDefault"Gbps"

Unit of down and up, shown after the totals and used in the accessible names.

formatType(value: number) => stringDefaultone decimal

Formats the totals and the throughput in the map's accessible name. The default gives one decimal with grouping, for example 1,204.5.

maxParticlesTypenumberDefault400

Most particles in flight at once. When the cap is reached the oldest particle is dropped. 0 turns particles off.

projectionType"equalEarth" | "equirectangular"Default"equalEarth"

Map projection. The map is cropped to 50° S to 72° N with its central meridian at 10° E.

liveTypebooleanDefaulttrue

Lets the demo flows drift by up to 12 % every 3 s while the map is on screen. Has no effect when flows or regions is given.

Ref

ref points at the root HTMLDivElement.

Keyboard

KeysAction
TabMoves to the region markers, which share one tab stop, then to the clear button of the selection chip.
ArrowLeft / ArrowRight / ArrowUp / ArrowDownMoves focus to the nearest marker in that direction on the map.
Enter / SpaceSelects the focused region, or clears the selection when it is already selected.
EscapeClears the selection.

Accessibility

  • Each region marker is a button with aria-pressed, named by the region's label. The markers form one roving tab stop.
  • The map has role="img" and an aria-label that gives the number of regions and the three largest flows with their downstream and upstream throughput.
  • The totals are DOM text. A polite live region announces the selected region's inbound and outbound totals when the selection changes, not when the data changes.
  • The chip's clear button is named "Clear selection: " plus the label. After clearing, focus moves to that region's marker.
  • Where markers overlap on small maps, a tap on a dot goes to the marker whose centre is nearest; a tap on a label goes to its own region.
  • The canvases are aria-hidden.
  • Reduced motion: there are no particles, ping or halo: the number of dot rows carries the throughput, selection and data changes apply at once, and the totals swap without rolling.

Theming

Styled with Tailwind classes on your shadcn theme tokens, so light and dark follow your theme. The accent comes from --lumesec. See Theming.

This component reads --lumesec, --lumesec-shine, --lumesec-info, --foreground, --muted-foreground, --card and --border.

Notes

  • Downstream curves use --lumesec and bend to the left of their direction of travel; upstream curves use --lumesec-info and bend to the other side, so the two directions of a flow separate.
  • A curve has 1 + round(2 × √(throughput / largest throughput)) rows of dots, so 1 to 3. Particles start at random along a Poisson process of 1.2 + 10 × throughput / largest particles per second and travel at constant speed.
  • With nothing selected, In is the sum of every down and Out the sum of every up. With a region selected, In is the traffic arriving there (down of flows to it plus up of flows from it) and Out the traffic leaving it.
  • Selecting a region lights its flows from the region outward behind an uneven front, collapses every other flow to a hairline and stops its particles, pings the land around the region and lights the land under it as its traffic arrives.
  • When flows changes, rows and particle rates spring to the new values; added flows grow out of their origin and removed ones retract into it.
  • Flows that cross the map's edge at 170° W continue from the other edge.
  • The map's height follows from its width, so set only the width. Below 480 px only the selected region's label shows and the selection chip moves to its own row. Labels that do not fit are hidden; the markers keep their names.
  • The animation runs only while the map is on screen. Colours follow the theme and are re-read when it changes.

Was this page helpful?