Order Status

Commerce

Order tracking with step progress indicator.

Preview

Order #2026-4521
Shipped
3
4
Order PlacedProcessingShippedDelivered

Usage

example.jsx
import { OrderStatus } from "@/components/ui/order-status";

export default function Example() {
  return <OrderStatus />;
}

Source Code

Copy this file into components/ui/order-status.jsx in your project.

order-status.jsx
import { forwardRef } from "react";
import { cn } from "@/lib/utils";

const statusConfig = {
  pending: { label: "Pending", color: "bg-yellow-100 text-yellow-700 dark:bg-yellow-900 dark:text-yellow-300" },
  processing: { label: "Processing", color: "bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-300" },
  shipped: { label: "Shipped", color: "bg-purple-100 text-purple-700 dark:bg-purple-900 dark:text-purple-300" },
  delivered: { label: "Delivered", color: "bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-300" },
  cancelled: { label: "Cancelled", color: "bg-red-100 text-red-700 dark:bg-red-900 dark:text-red-300" },
};

const OrderStatus = forwardRef(({ className, status = "pending", orderId, date, steps = [], ...props }, ref) => {
  const config = statusConfig[status] || statusConfig.pending;
  const stepNames = steps.length ? steps : ["Ordered", "Processing", "Shipped", "Delivered"];
  const stepMap = { pending: 0, processing: 1, shipped: 2, delivered: 3 };
  const currentStep = stepMap[status] ?? 0;

  return (
    <div ref={ref} className={cn("space-y-4", className)} {...props}>
      <div className="flex items-center justify-between">
        <div>
          {orderId && <span className="text-sm text-muted-foreground">Order #{orderId}</span>}
          {date && <span className="ml-2 text-sm text-muted-foreground">· {date}</span>}
        </div>
        <span className={cn("rounded-full px-2.5 py-0.5 text-xs font-medium", config.color)}>{config.label}</span>
      </div>
      <div className="flex items-center">
        {stepNames.map((s, i) => (
          <div key={i} className="flex flex-1 items-center">
            <div className={cn("flex h-7 w-7 items-center justify-center rounded-full text-xs font-bold",
              i <= currentStep ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"
            )}>{i < currentStep ? "✓" : i + 1}</div>
            {i < stepNames.length - 1 && <div className={cn("mx-1 h-0.5 flex-1", i < currentStep ? "bg-primary" : "bg-muted")} />}
          </div>
        ))}
      </div>
      <div className="flex justify-between text-xs text-muted-foreground">{stepNames.map((s, i) => <span key={i}>{s}</span>)}</div>
    </div>
  );
});
OrderStatus.displayName = "OrderStatus";

export { OrderStatus };

Quick Install

Make sure you have the cn() utility set up. It requires clsx and tailwind-merge.

npm install clsx tailwind-merge