# Service Map

> A root service and the services it sends traffic to, as cards joined by right-angle lines, each with a status badge, metric rows, and a beam of light running down every line.

Source: https://ui.cortexcn.dev/docs/cortex/service-map

## Installation

```bash
npx shadcn@latest add @cortexcn/service-map
```

## Usage

```tsx
import { ServiceMap } from "@/components/service-map";
```

```tsx
<ServiceMap
  caption="Last updated: 10:03 AM"
  nodes={[
    {
      id: "gateway",
      title: "API Gateway",
      metrics: [{ label: "/v1/orders", value: 48, unit: "k Reqs" }],
      x: 50,
      y: 20,
    },
    {
      id: "orders",
      parent: "gateway",
      title: "Orders",
      status: "healthy",
      metrics: [
        { label: "Traffic", value: 64, unit: "%" },
        { label: "Avg", value: 120, unit: "ms" },
      ],
      x: 30,
      y: 60,
    },
  ]}
/>
```

Each node is a card placed by its center, in percent of the map's width and height. A node with a `parent` is joined to it by a line, so one list describes the whole tree. Use it for endpoint traffic, payment rails, queues and their workers, or any system where one service hands work to others.

## Examples

### Static

With `animated={false}`, the lines are drawn without the moving beams.

## Behavior

- A child below its parent hangs off a horizontal line shared with its siblings, and a child straight below its parent gets a straight line. A child beside its parent is joined side to side.
- The lines are measured from the cards after the map renders, and redrawn when the map or any card changes size.
- Beams run from parent to child, one line after another, only while the map is on screen. With reduced motion enabled, the lines stay still.
- The map lays out at `minWidth` or wider (520px by default). In a narrower container it scrolls sideways, and takes keyboard focus so it can be scrolled from the keyboard.
- Badge text mixes the status color with the text color, so it stays readable in light and dark mode.
- Each child card tells screen readers which node sends it traffic. Icons are hidden from them.

## Props

### ServiceMap

| Prop        | Type               | Default         | Description                                         |
| ----------- | ------------------ | --------------- | --------------------------------------------------- |
| `nodes`     | `ServiceMapNode[]` | -               | The cards, and through `parent`, the lines          |
| `caption`   | `ReactNode`        | -               | A small label in the top-left corner                |
| `animated`  | `boolean`          | `true`          | Send beams down the lines while the map is on screen |
| `minWidth`  | `number`           | `520`           | Narrowest layout width in pixels; below it, scroll  |
| `ariaLabel` | `string`           | `"Service map"` | Names the map for screen readers                    |
| `className` | `string`           | -               | Extra classes; set the height here (default `h-80`) |

### ServiceMapNode

| Prop          | Type                                              | Default    | Description                                 |
| ------------- | ------------------------------------------------- | ---------- | ------------------------------------------- |
| `id`          | `string`                                          | -          | Unique id, used by children's `parent`      |
| `parent`      | `string`                                          | -          | The node that sends this one traffic        |
| `title`       | `string`                                          | -          | The card's name                             |
| `icon`        | `ReactNode`                                       | -          | Icon before the title, drawn at 14px        |
| `status`      | `"healthy" \| "warning" \| "critical" \| "idle"` | -          | Colors the status badge                     |
| `statusLabel` | `string`                                          | The status | Text in the badge                           |
| `metrics`     | `{ label: string; value: ReactNode; unit?: string }[]` | -     | Label and value rows under the title        |
| `x`           | `number`                                          | -          | The card's center, in percent of the width  |
| `y`           | `number`                                          | -          | The card's center, in percent of the height |