<!-- Generated by scripts/gen-docs.mts from the JSDoc in registry/. Do not edit; run `pnpm run docs`. -->

# RouteProgress

The thin bar across the top of the screen while the app loads the next page or submits a form, so a click that waits on the server never feels frozen: one global affordance instead of a pending state on every action. Once `active` has held for 150ms the bar fades in, and screen readers hear "Loading" once; a faster navigation shows and says nothing. While it shows, it creeps toward 90% of the width, more slowly the nearer it gets; when `active` turns false it fills to the end and fades out. With reduced motion it is the whole width from the start and only fades.

```tsx
import { RouteProgress } from "@/components/ouro/route-progress/route-progress";
```

## Example

```tsx
// React Router, in the root route:
const navigation = useNavigation();
<RouteProgress active={navigation.state !== "idle"} />
```

## Usage

Render it once, in the root layout, with your router's navigation state.

## Use instead when

- Use `Progress` instead for a task whose amount is known, `Spinner` inside the control that is busy, and `Button`'s `loading` for the one action a person just took.

## Props

Type: `RouteProgressProps`.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `active` (required) | `boolean` |  | Whether a navigation or a form submission is under way: in React Router, `useNavigation().state !== "idle"`; in Next.js, the pending state of `useTransition` around `router.push`. |
| `className` | `string` |  | Layout only: rarely needed, since the bar places itself at the top of the screen. Appearance classes warn in development. |
| `label` | `string` | `"Loading"` | What screen readers hear when a navigation starts. |
| `ref` | `Ref<HTMLDivElement>` |  | Reaches the root, the status region. |

## Don't use

These are not props. Passing one fails the type check with the fix in the error, and in development a console message names the fix.

- `isLoading`: Not a prop. Ouro UI uses `active`: `<RouteProgress active={navigation.state !== "idle"} />`.
- `loading`: Not a prop. Ouro UI uses `active`: `<RouteProgress active={navigation.state !== "idle"} />`.
- `value`: Not a prop. RouteProgress shows that something is loading, not how much; use `Progress` for a known amount.

## `className` is for layout only

Pass margins, width and grid placement (`mt-4`, `w-full`, `col-span-2`). Your classes always win over Ouro UI's: RouteProgress merges `className` last with `cn` (tailwind-merge), so a class that conflicts with its own replaces it.[^layout-classes]

Appearance comes from props, not classes. In development, a class that sets appearance logs one warning per component instance, naming the prop to use instead. A class sets appearance when, after its variants (`hover:`, `sm:`) and any `!` are removed, it starts with `bg-`, `text-`, `border-`, `rounded-`, `shadow-`, `font-`, `ring-`, `from-`, `via-`, `to-`, `fill-` or `stroke-`, or is `border`, `rounded`, `shadow` or `ring`, or has a `dark:` variant. Text wrapping, overflow and table layout classes (`text-wrap`, `text-ellipsis`, `border-collapse`) are layout and do not warn.

Alignment classes (`text-center`) warn too: set alignment on a parent element.

[^layout-classes]: test:registry/ouro/components/ouro/route-progress/route-progress.test.tsx::RouteProgress > forwards a ref and lets app layout classes win verify:testExists(registry/ouro/components/ouro/route-progress/route-progress.test.tsx::RouteProgress > forwards a ref and lets app layout classes win)
