# 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.
- React: `import { GeoTraceroute } from "@/components/lumesec/geo-traceroute"`
- Collection: Location (https://elements.lumesec.ai/components/location)
- Data: takes your data (`data`); shows demo data until you pass it
- Registry item: https://elements.lumesec.ai/r/geo-traceroute.json
- Page: https://elements.lumesec.ai/components/location/traceroute



Live preview: https://elements.lumesec.ai/view/geo-traceroute

Demo source:

```tsx
import { GeoTraceroute } from "@/components/lumesec/geo-traceroute";

export default function GeoTracerouteDemo() {
  return <GeoTraceroute className="w-full max-w-[660px]" />;
}
```

> **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](/docs/data).

## Playground

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

## Installation

```bash
npx shadcn@latest add @lumesec/geo-traceroute
```

First time with the @lumesec registry? Register it once, or install by URL:

```bash
npx shadcn@latest registry add @lumesec=https://elements.lumesec.ai/r/{name}.json
npx shadcn@latest add https://elements.lumesec.ai/r/geo-traceroute.json
```

## Usage

React:

```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.

| Prop              | Type                              | Default                      | Description                                                                                                                                                                                                                                                                                                                                              |
| ----------------- | --------------------------------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `hops`            | `readonly TraceHop[]`             | `11 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. |
| `target`          | `string`                          | `last hop's name or address` | The destination shown in the header. The demo shows `app.example.com`.                                                                                                                                                                                                                                                                                   |
| `value`           | `number \| null`                  | —                            | Index of the selected hop in `hops` (controlled), or null for none. Use with `onValueChange`.                                                                                                                                                                                                                                                            |
| `defaultValue`    | `number \| null`                  | `null`                       | Selected hop when uncontrolled.                                                                                                                                                                                                                                                                                                                          |
| `onValueChange`   | `(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.                                                                                                                                                                                                                                           |
| `playing`         | `boolean`                         | —                            | Whether the playback runs (controlled). Use with `onPlayingChange`. Setting it to true after the end starts over from hop 1.                                                                                                                                                                                                                             |
| `defaultPlaying`  | `boolean`                         | `true`                       | Whether the playback starts by itself when uncontrolled. It begins once the map is first on screen. With false the path is drawn complete.                                                                                                                                                                                                               |
| `onPlayingChange` | `(playing: boolean) => void`      | —                            | Called by Pause, Play and Replay, with false when the playback reaches the end, and with false when `hops` changes.                                                                                                                                                                                                                                      |
| `speed`           | `number`                          | `1`                          | Playback speed. At 1, each millisecond of round-trip time a hop adds is 10 ms of waiting at that hop.                                                                                                                                                                                                                                                    |
| `jumpMs`          | `number`                          | `40`                         | 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.                                                                                                                                                                                                                                |
| `probes`          | `number`                          | `3`                          | 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.                                                                                                                                                                                                                                    |
| `onComplete`      | `() => void`                      | —                            | Called when the playback reaches the end of the trace.                                                                                                                                                                                                                                                                                                   |

### Ref

`ref` points at the root `HTMLDivElement`.

## Keyboard

| Keys                | Action                                                                             |
| ------------------- | ---------------------------------------------------------------------------------- |
| Tab                 | Moves to Replay, to Pause or Play, then to the hop rows, which share one tab stop. |
| ArrowUp / ArrowDown | Moves focus to the previous or next hop.                                           |
| Home / End          | Moves focus to the first or last hop.                                              |
| Enter / Space       | Selects the focused hop, or clears the selection when it is already selected.      |
| Escape              | Clears 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](/docs/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.


