Passer au contenu principal

RefundStatusTracker

Implemented

Read-only refund-progress tracker for order history — status pill + summary line (id, dates, reason) + 5-stage linear track with terminal rejected branch; live-region announcement; consumer-supplied localized labels.

Categorymolecules
Sourcecomponents/molecules/refundstatustracker/RefundStatusTracker.tsx
AI HintRead-only refund-progress display for order history / account order detail. role=status live region (WCAG 4.1.3) switching to role=alert on rejected; stage track via ol[role=list] with aria-current=step. ALL strings (six status labels, ariaLabel, dates, reason) are consumer-supplied — component renders verbatim, never formats. See Stepper for interactive wizards; StatusBadge for single-state pills. Status enum: pending/reviewing/approved/processing/completed/rejected.

Read-only refund-progress tracker for order history: linear 5-stage track with a terminal rejected branch, live-region announcement, and consumer-supplied localized labels.

RefundStatusTracker

Commerce — Family 7

Read-only refund-progress display: status pill + summary line (refundId, dates, reason) + 5-stage linear track (pending → reviewing → approved → processing → completed). Terminal rejected renders an error node instead of a current stage. All strings consumer-supplied (i18n contract).

Processingrf_12345
Requested 25 Aug 2026Estimated 2 Sep 2026
  1. Pending review
  2. Under review
  3. Approved
  4. Processing
  5. Completed

RefundStatusTracker — rejected

Commerce — Family 7

Terminal rejected: the linear track renders with no current or completed stage (aria-current nowhere), the root switches to role="alert" (assertive live region), and an error-tinted node carries the rejected label + reason.

RefundStatusTracker — completed

Commerce — Family 7

Completed: the first four stages render check icons (completed), the final stage carries aria-current="step", and the status pill uses the success tint.

Completedrf_67890
Requested 18 Aug 2026
  1. Pending review
  2. Under review
  3. Approved
  4. Processing
  5. Completed

Usage

Data-in molecule: pass the required refundId, status, labels (all six, consumer-supplied — i18n contract) and ariaLabel. The component never formats dates or numbers — pass pre-formatted strings for estimatedDate / requestedAt.

import { RefundStatusTracker } from "@epasslive/design-system";

const labels = {
  pending: "Pending review",
  reviewing: "Under review",
  approved: "Approved",
  processing: "Processing",
  completed: "Completed",
  rejected: "Rejected",
};

// Mid-progress refund
<RefundStatusTracker
  refundId="rf_12345"
  status="processing"
  labels={labels}
  ariaLabel="Refund status"
  requestedAt="Requested 25 Aug 2026"
  estimatedDate="Estimated 2 Sep 2026"
/>

// Rejected (terminal) — root becomes role="alert"
<RefundStatusTracker
  refundId="rf_99999"
  status="rejected"
  labels={labels}
  ariaLabel="Refund status"
  reason="Claim window has expired"
/>

Status model

Five linear stages — pending → reviewing → approved → processing → completed — map onto the stage track. Stages before the current one render a check icon (completed); the current stage carries aria-current="step"; future stages are muted. rejected is a terminal branch, not a sixth step: the linear track renders with no current or completed stage and a separate error-tinted node carries the rejection. The status pill uses StatusBadge-style semantic tints (pending → warning, reviewing/processing → info, approved/completed → success, rejected → error) — theme-stable, WCAG AA in both themes.

Accessibility

  • The root is the live region (WCAG 4.1.3): role="status" + aria-live="polite" for all statuses except rejected, which switches to role="alert" (assertive). Only one live region exists — at the root, never nested.
  • The stage track renders as a real <ol role="list"> / <li role="listitem"> list; the current stage carries aria-current="step".
  • Check icons and connector rules are decorative (aria-hidden); the stage labels carry the meaning.
  • Non-interactive by design — no focus targets, no keyboard navigation. For interactive wizards use Stepper; this molecule is its read-only, live-region counterpart for refund progress.
  • i18n contract: every user-visible string is consumer-supplied (labels, ariaLabel, reason, pre-formatted dates). The component contains no hardcoded copy.

Props

Prop
Type
Default
Description
refundId*
string
—

Refund identifier shown to the user in the summary line (e.g. an order-history reference).

status*
"pending" | "reviewing" | "approved" | "processing" | "completed" | "rejected"
—

Current refund stage. The 5 linear stages map to the track (aria-current="step" on the current one); "rejected" is a terminal branch that renders an error node with role="alert" on the root.

labels*
RefundStatusLabels
—

Consumer-supplied localized labels for all six statuses: { pending, reviewing, approved, processing, completed, rejected }. The component never hardcodes status strings — pass localized text (FR/EN/…) from your i18n layer (cf. Calendar weekdayLabels).

ariaLabel*
string
—

Accessible name for the live-region root. Required — names the region for screen readers.

estimatedDate
string
—

Expected completion date, pre-formatted by the consumer (locale-aware). Rendered as plain text — the component never formats dates.

reason
string
—

Consumer-localized explanation (e.g. why a refund was rejected). Rendered as muted secondary text.

requestedAt
string
—

When the refund was requested, pre-formatted by the consumer (locale-aware). Rendered as plain text.

className
string
—

Additional classes on the root element.

id
string
—

Stable root id; falls back to an SSR-safe useId() value.

Props

Preview

RefundStatusTracker

Prop
Type
Required
Default
Description
refundId
string
Required
—

Refund request identifier (displayed in summary).

status
RefundStatus
Required
—

'pending' | 'reviewing' | 'approved' | 'processing' | 'completed' | 'rejected'.

labels
RefundStatusLabels
Required
—

Consumer-supplied localized labels for all six statuses (i18n contract — component never hardcodes strings).

ariaLabel
string
Required
—

Names the role=region live-region landmark for screen readers.

estimatedDate
string
Optional
—

Consumer pre-formatted, locale-aware display string.

reason
string
Optional
—

Consumer-localized explanation (rendered as muted secondary text).

requestedAt
string
Optional
—

Consumer pre-formatted display string for the request date.

className
string
Optional
—

Additional CSS classes.

id
string
Optional
—

Root element id.

Quick use:<RefundStatusTracker />

Accessibility

ARIA rolestatus

Type

2 rules

NASA Rule 5

status must be valid RefundStatus enum value

NASA Rule 1

labels must provide all six status labels (i18n contract — no hardcoded UI strings)

ARIA

2 rules

WCAG 4.1.3

Root live region: role=status + aria-live=polite; rejected switches to role=alert (assertive)

WCAG 1.3.1

Stage track uses ol[role=list] with aria-current=step on current stage

i18n

1 rule

i18n contract

estimatedDate/requestedAt/reason are pre-formatted consumer strings; component never formats dates

a11y

1 rule

ADR-027

Status tints use ep-semantic-{success,warning,info,error}-{tint,fg} tokens — WCAG AA 4.5:1 in light + dark

Usage

Import

tsxSnippet
import { RefundStatusTracker } from "@epasslive/design-system"

Example 1

tsxSnippet
<RefundStatusTracker refundId="rf_123" status="processing" labels={labels} ariaLabel="Refund status" />

Example 2

tsxSnippet
<RefundStatusTracker refundId="rf_123" status="rejected" labels={labels} ariaLabel="Statut de remboursement" reason={t("refund.rejected")} />

Anti-patterns

— Do not hardcode status labels — pass localized labels prop

— Do not format dates inside the component — render pre-formatted strings

— Avoid complex business logic in molecules

Design System v4.1.0 | ePassLive