Skip to content
NewYour data: charts, lists and meters that take your records
<GeoTraceroute />ReactNetwork & latencyFree

Traceroute

A traceroute as a hop table and a dotted map; the packet waits at each hop for its share of the round-trip time, so slow hops are slow to watch.

View as Markdown
<GeoTraceroute />

Trypress Replay, then move through the table with the arrow keys.

Your data

Pass your trace as hops. Without it the component shows an invented 11-hop demo trace from a home router through Frankfurt, Marseille and Mumbai to Singapore, with documentation-range addresses. 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 <GeoTraceroute />
Props
defaultPlayingremounts
speedlive
jumpMslive
probeslive
targetlive
React
<GeoTraceroute
  defaultPlaying
  speed={1}
  jumpMs={40}
  probes={3}
  target="app.example.com"
/>

Installation

pnpm dlx shadcn@latest add @lumesec/geo-traceroute
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-traceroute.json

Usage

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

import * as React from "react";

import { GeoTraceroute, type TraceHop } from "@/components/lumesec/geo-traceroute";

const hops: TraceHop[] = [
  { address: "192.168.1.1", name: "router.home.arpa", rtt: [0.6, 0.5, 0.7] },
  { address: "203.0.113.14", location: "Frankfurt", lat: 50.11, lon: 8.68, rtt: [8.4, 8.1, 9.0] },
  { address: "*", rtt: [] },
  { address: "192.0.2.33", location: "Mumbai", lat: 19.08, lon: 72.88, rtt: [110.4, 109.8, 111.2] },
  { address: "203.0.113.200", name: "app.example.com", location: "Singapore", lat: 1.35, lon: 103.82, rtt: [162.4, 161.9, 163.0] },
];

export function Example() {
  const [hop, setHop] = React.useState<number | null>(null);
  return <GeoTraceroute target="app.example.com" hops={hops} value={hop} onValueChange={setHop} />;
}

Behaviour

A traceroute as a hop table and a map. The path draws hop by hop, and the packet waits at each hop for its share of the round-trip time, so slow hops are slow to watch.

Jumps of more than 40 ms are drawn as dashed long-haul segments with the added time beside them. Hops without a location, or that did not answer, stay in the table only. Selecting a row highlights its segment.

API reference

Props

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

hopsTypereadonly TraceHop[]Default11 demo hops

The hops in order: { address, name?, location?, lat?, lon?, rtt }. rtt holds one round-trip time in ms per probe; a non-finite entry is a probe that timed out and an empty array a hop that did not answer. Hops with lat and lon are drawn on the map; location is the place name in the table. An empty array shows an empty table and map.

targetTypestringDefaultlast hop's name or address

The destination shown in the header. The demo shows app.example.com.

valueTypenumber | null

Index of the selected hop in hops (controlled), or null for none. Use with onValueChange.

defaultValueTypenumber | nullDefaultnull

Selected hop when uncontrolled.

onValueChangeType(value: number | null) => void

Called with the hop index when a row or a map marker is selected, and with null when the selection is cleared.

playingTypeboolean

Whether the playback runs (controlled). Use with onPlayingChange. Setting it to true after the end starts over from hop 1.

defaultPlayingTypebooleanDefaulttrue

Whether the playback starts by itself when uncontrolled. It begins once the map is first on screen. With false the path is drawn complete.

onPlayingChangeType(playing: boolean) => void

Called by Pause, Play and Replay, with false when the playback reaches the end, and with false when hops changes.

speedTypenumberDefault1

Playback speed. At 1, each millisecond of round-trip time a hop adds is 10 ms of waiting at that hop.

jumpMsTypenumberDefault40

Added round-trip time in ms above which a segment is drawn as a dashed long-haul jump with a chip such as +42 ms on it.

probesTypenumberDefault3

Probes sent per hop: the number of marks in each row, 1 to 8. A row with more rtt entries shows one mark per entry.

onCompleteType() => void

Called when the playback reaches the end of the trace.

Ref

ref points at the root HTMLDivElement.

Keyboard

KeysAction
TabMoves to Replay, to Pause or Play, then to the hop rows, which share one tab stop.
ArrowUp / ArrowDownMoves focus to the previous or next hop.
Home / EndMoves focus to the first or last hop.
Enter / SpaceSelects the focused hop, or clears the selection when it is already selected.
EscapeClears the selection.

Accessibility

  • The hops are a native table with a caption (Hops to plus the target) and column headers.
  • The first cell of each row holds a button with aria-pressed, named by the hop number, its name or address, where it is and its median round-trip time. The buttons form one roving tab stop.
  • The probe marks of each row are one image named, for example, 2 of 3 probes answered.
  • The map has role="img" and an aria-label such as 7 located hops from Frankfurt to Singapore, 162 ms. 2 long-haul jumps. Its markers, labels and chips are hidden from assistive technology; the table carries the same data.
  • Replay and Pause or Play are native buttons named by their label, which stays in the accessible name when the narrow layout shows only the icon.
  • A polite live region announces the end of the playback with the number of hops and the total round-trip time.
  • The canvases are aria-hidden.
  • Reduced motion: the whole path is drawn at once: there is no packet, dwell ring, ping or spark, the round-trip times show directly, the total and the Pause label swap without rolling, and selection changes apply at once.

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-glint, --foreground, --muted-foreground, --muted, --card and --border.

Notes

  • The playback walks the table row by row. Rows before the first located hop take a short turn each. The packet then appears at the first located hop and, for each segment, travels the curve in 0.35 s plus 0.25 s per 10,000 km, then waits at the next hop for the time that hop adds: its median minus the median of the located hop before it, 10 ms of animation per ms at speed 1, at least 0.18 s. Rows between two located hops take their turns while the packet travels.
  • While the packet waits it circles the hop once, and the lattice dots around the hop fill clockwise from the direction it arrived in, like a progress ring. The row is highlighted with an accent bar, its probe marks fill in turn and its round-trip time counts up from the hop above. Rows the playback has not reached show a dash.
  • At the end two rings of land dots run out from the destination, sparks fly past the map's edge, the header total rolls in and onComplete fires.
  • Medians use the answered probes only. A segment's added time never goes below 0, so a hop that answers faster than the hop before it waits the minimum.
  • Addresses in private, shared (carrier-grade NAT), loopback or link-local ranges get a Private tag and never reach the map, even with coordinates. Hops without coordinates and hops that did not answer stay in the table only; selecting one dims the map and shows No location.
  • Selecting a located hop redraws its incoming segment at full strength and 1.5 times the dot size, dims the other segments to a quarter, and lights the ring of dots around the hop.
  • Pause holds the clock, so the packet and the ring stop where they are. Play resumes; Play after the end and Replay start over from hop 1. Changing hops stops the playback and shows the new path complete.
  • The map frames the located hops with a 25 % margin and at least 60° on each axis, on a zoomed Equal Earth projection that fills the box, so it has no curved edges. Segments that cross the 180th meridian continue from the other edge.
  • Clicking a hop marker on the map selects that hop, like its row.
  • The map's height follows its width. Below 480 px the Name column hides, the RTT unit moves into the column header and the header buttons show only their icons.
  • 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?