RefundStatusTracker
ImplementedRead-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.
components/molecules/refundstatustracker/RefundStatusTracker.tsxRead-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).
- Pending review
- Under review
- Approved
- Processing
- 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.
Claim window has expired
- Pending review
- Under review
- Approved
- Processing
- Completed
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.
- Pending review
- Under review
- Approved
- Processing
- 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 exceptrejected, which switches torole="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 carriesaria-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
refundId*stringRefund 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*RefundStatusLabelsConsumer-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*stringAccessible name for the live-region root. Required — names the region for screen readers.
estimatedDatestringExpected completion date, pre-formatted by the consumer (locale-aware). Rendered as plain text — the component never formats dates.
reasonstringConsumer-localized explanation (e.g. why a refund was rejected). Rendered as muted secondary text.
requestedAtstringWhen the refund was requested, pre-formatted by the consumer (locale-aware). Rendered as plain text.
classNamestringAdditional classes on the root element.
idstringStable root id; falls back to an SSR-safe useId() value.
Props
RefundStatusTracker
refundIdstring—Refund request identifier (displayed in summary).
statusRefundStatus—'pending' | 'reviewing' | 'approved' | 'processing' | 'completed' | 'rejected'.
labelsRefundStatusLabels—Consumer-supplied localized labels for all six statuses (i18n contract — component never hardcodes strings).
ariaLabelstring—Names the role=region live-region landmark for screen readers.
estimatedDatestring—Consumer pre-formatted, locale-aware display string.
reasonstring—Consumer-localized explanation (rendered as muted secondary text).
requestedAtstring—Consumer pre-formatted display string for the request date.
classNamestring—Additional CSS classes.
idstring—Root element id.
<RefundStatusTracker />Accessibility
Type
2 rulesARIA
2 rulesi18n
1 rulea11y
1 ruleUsage
Import
import { RefundStatusTracker } from "@epasslive/design-system"Example 1
<RefundStatusTracker refundId="rf_123" status="processing" labels={labels} ariaLabel="Refund status" />Example 2
<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