# Routes
> Reverse-proxy routes in priority order, reordered by drag or Alt and arrow keys. A route that a broader one above always catches is shadowed.
- Element: `<sv-routes>`
- React: `import { SvRoutes } from "@/components/lumesec/sv-routes"`
- Collection: Service Map (https://elements.lumesec.ai/components/service-map)
- Registry item: https://elements.lumesec.ai/r/sv-routes.json
- Page: https://elements.lumesec.ai/components/service-map/routes



Live preview: https://elements.lumesec.ai/view/sv-routes

```html
<sv-routes></sv-routes>
```

## Installation

```bash
npx shadcn@latest add @lumesec/sv-routes
```

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/sv-routes.json
```

## Usage

React:

```tsx
import { SvRoutes } from "@/components/lumesec/sv-routes";

export function Example() {
  return (
    <SvRoutes />
  );
}
```

HTML:

```html
<script type="module" src="https://elements.lumesec.ai/cdn/sv-routes.js"></script>

<sv-routes></sv-routes>
```

## Behaviour

Host and path to upstream, in priority order. A route that a broader one above it always catches is marked as shadowed.

## API reference

### Events

Events bubble and cross the shadow boundary unless the description says otherwise.

| Event     | React prop  | Detail                                  | Description                                                                               |
| --------- | ----------- | --------------------------------------- | ----------------------------------------------------------------------------------------- |
| `reorder` | `onReorder` | `{ route: string, position: number }`   | Fires when a route moves. `route` is host plus path, `position` the new 1-based position. |
| `change`  | `onChange`  | `{ action: 'add-route', host: string }` | Fires when a route is added. `host` includes the path when it is not `/`.                 |

## Keyboard

| Keys                            | Action                                                                              |
| ------------------------------- | ----------------------------------------------------------------------------------- |
| Alt + ArrowUp / Alt + ArrowDown | On a drag handle: move the route up or down one position. Focus follows the handle. |

## Accessibility

* Routes are a `role="list"`. Each drag handle is a button whose `aria-label` names the route and the Alt and arrow keys.
* A polite live region announces the new position after a move.
* On an invalid new route the field gets `aria-invalid="true"` and focus, and the message is in an assertive live region.
* Reduced motion: no animation; with reduced motion only the shared button transitions are switched off.

## Theming

The element reads your shadcn theme tokens through its shadow root, so light and dark follow your theme. The accent comes from `--lumesec`. See [Theming](/docs/theming).

This component reads `--border`, `--card`, `--foreground`, `--lumesec`, `--lumesec-success`, `--lumesec-warning`, `--muted` and `--muted-foreground`.

To restyle only LumeSec elements, set the matching `--ui-*` overrides: `--ui-accent`, `--ui-border`, `--ui-fg`, `--ui-mono`, `--ui-muted`, `--ui-ok`, `--ui-raised`, `--ui-surface` and `--ui-warn`.

## Notes

* Built-in demo data: the six routes from `INFRA`, with api.lumesec.local/v1/infer placed below its catch-all so it starts shadowed. No attribute selects a record.
* A route is shadowed when an earlier route has the same host and a shorter path that is a prefix of its path.
* A new route needs a host like `docs.lumesec.local`, a path that starts with `/`, and a host and path that are not taken. It starts as Planned with TLS and points at one upstream: AIOP API, Admin UI, Identity, Grafana, Object store or Prometheus.
* Container query: compact rows and a two-column form under 480 px.


