# Progress Line

A cross-platform React linear progress bar component for displaying completion status horizontally.
<!-- BEGIN:xui-mcp-instructions:progress-line -->
A thin, full-width track that communicates progress or a semantic state through fill and colour alone. Unlike Progress bar, it has no label, helper text, or icon slots — it is a purely visual indicator intended to be embedded as a decorative-functional element within other components or layout regions.

### When to use

As an inline loading indicator at the top of a card, modal, panel, or page section

Inside a multi-step flow to show how far the user has progressed without occupying vertical space

As a thin status stripe on a list item, table row, or media element (e.g. a video player scrubber base)

When the surrounding context already provides enough label information and a second text element would be redundant

### When not to use

When the user needs to understand the exact percentage or a numeric value — use Progress bar with Helper text instead

When the progress state needs an explanation (e.g. an error message) — use Progress bar with Label and Helper text
- For indeterminate loading — use a Spinner or animated skeleton
- As a standalone component on a page without any surrounding context — Progress line has no self-describing elements and will be meaningless without nearby copy

### Behaviour guidelines

Value as width — the indicator width maps directly to the progress percentage (0–100%). At 0% the track appears empty; at 100% the indicator fills the track completely.

Animation — animate the indicator width with a smooth CSS width transition when the value updates. Do not use instant jumps between values unless the component is being initialised.

State transitions — switch to State=Success only after backend confirmation of completion, not when the fill reaches 100%. Switch to State=Error immediately on failure and freeze the fill at its current width — do not reset to 0%.

Direction — the indicator always grows left to right in LTR. Mirror to right-to-left in RTL layouts using CSS logical properties or a transform.

Container width — Progress line always stretches to 100% of its parent container. Never set a fixed width on the component itself; control width by constraining the parent.

Stacking — when multiple Progress lines appear in a list (e.g. a file upload queue), align them to the same horizontal grid and use consistent size and spacing. Each line should map to exactly one process.

Indeterminate state — if the duration is unknown, do not use Progress line with a faked fill. Apply a looping animation (e.g. a sliding gradient or a bouncing indicator) as an indeterminate variant, or substitute a Spinner.

Completion hold — after transitioning to State=Success, keep the line visible for at least 600–800ms before removing or replacing it so users can register the completed state.

### Accessibility

Use role=*"progressbar"* with aria-valuenow, aria-valuemin=*"0"*, and aria-valuemax=*"100"* on the track element.

Always provide aria-label or aria-labelledby that describes what is progressing — for example, aria-label=*"File upload progress"*. Without this, screen readers cannot announce the purpose of the bar.

When State=Error is applied, pair the component with a visible error message nearby (outside the component) and link it via aria-describedby. Progress line itself has no error text slot.

For State=Success and State=Error transitions, use aria-live=*"polite"* on a nearby text region so the state change is announced to assistive technology without forcing the user to navigate to the component.

Do not rely on colour alone to communicate State — the track is too thin to show an icon. Always pair state changes with a text or icon announcement in the surrounding layout.
<!-- END:xui-mcp-instructions:progress-line -->

## Installation

```bash
npm install @xsolla/xui-progress-line
```

## Demo

### Basic Progress Line

```tsx
import * as React from "react";
import { ProgressLine } from "@xsolla/xui-progress-line";

export default function BasicProgressLine() {
  return <ProgressLine percent={75} aria-label="Task progress" />;
}
```

### Progress Line Sizes

```tsx
import * as React from "react";
import { ProgressLine } from "@xsolla/xui-progress-line";

export default function ProgressLineSizes() {
  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
      <ProgressLine percent={60} size="sm" aria-label="Small progress" />
      <ProgressLine percent={60} size="md" aria-label="Medium progress" />
      <ProgressLine percent={60} size="lg" aria-label="Large progress" />
    </div>
  );
}
```

### With Label

```tsx
import * as React from "react";
import { ProgressLine } from "@xsolla/xui-progress-line";

export default function ProgressLineWithLabel() {
  const [progress, setProgress] = React.useState(45);

  return (
    <div>
      <div
        style={{
          display: "flex",
          justifyContent: "space-between",
          marginBottom: 8,
        }}
      >
        <span id="upload-label">Uploading...</span>
        <span>{progress}%</span>
      </div>
      <ProgressLine percent={progress} aria-labelledby="upload-label" />
    </div>
  );
}
```

## Accessibility

ProgressLine includes `role="progressbar"` and appropriate `aria-valuenow`, `aria-valuemin`, and `aria-valuemax` attributes.

**Important:** You MUST provide an `aria-label` or `aria-labelledby` attribute so screen readers can describe what is progressing.

```tsx
<ProgressLine percent={50} aria-label="File upload progress" />
```

## API Reference

### ProgressLine

**ProgressLine Props:**

| Prop     | Type                                | Default     | Description                                                                                                   |
| :------- | :---------------------------------- | :---------- | :------------------------------------------------------------------------------------------------------------ |
| `testID` | `string`                            | —           | Test ID for testing frameworks. On web this renders as `data-testid`; on React Native it renders as `testID`. |
| percent  | `number`                            | `0`         | Progress percentage (0-100).                                                                                  |
| size     | `"sm" \| "md" \| "lg"`              | `"md"`      | Height of the progress line.                                                                                  |
| state    | `"default" \| "error" \| "success"` | `"default"` | Color state of the progress line.                                                                             |
