asafefe.dev

Order Tracker

New

A delivery or job status card. The progress line fills step by step, the current step pulses, the ETA counts down live, and the courier and item list sit underneath. Works for shipping and repair shop jobs alike.

motionlucide-reactutilsavatarbuttonbutton-groupcarditemseparator@soultel/rolling-number@soultel/use-reduced-motion-safe
Order #4821
Placed Oct 24, Northside Store

Now: Out for delivery

Arriving in

Soon

  1. Order placed, done

    Oct 24, 9:12 AM
  2. Packed, done

    Oct 24, 4:40 PM
  3. Shipped, done

    Oct 25, 8:05 AM
  4. Out for delivery, in progress

    10:24 AM

    Daniel is 6 stops away and heading your way.

  5. Delivered

D
Daniel Okafor

Cargo bike·Rated 4.9

Installation

$ pnpm dlx shadcn@latest add @soultel/order-tracker

No namespace set up? npx shadcn@latest add https://asafefe.dev/r/order-tracker.json works too.

Manual installation
  1. 1. Install the dependencies.
    terminal1 lines
    npm install motion lucide-react
  2. 2. Copy the source from the Code tab into components/order-tracker.tsx.

Usage

example.tsx23 lines
import { OrderTracker } from "@/components/order-tracker"

export function RepairStatus({ job }: { job: Job }) {
  return (
    <OrderTracker
      title={`Repair job ${job.number}`}
      subtitle="MacBook Pro 14, battery and keyboard"
      etaLabel="Ready in"
      doneLabel="Ready for pickup"
      eta={job.readyAt}
      currentStep={job.stage}
      steps={[
        { id: "in", label: "Checked in", time: "Mon 10:02 AM" },
        { id: "diag", label: "Diagnosis", description: "A technician is testing the battery and keyboard." },
        { id: "parts", label: "Parts ordered" },
        { id: "repair", label: "Repair" },
        { id: "qa", label: "Quality check" },
      ]}
      courier={{ name: job.technician, vehicle: "Technician", rating: 4.9 }}
      onContact={(method) => (method === "call" ? callShop() : openChat())}
    />
  )
}

Props

PropTypeDefaultDescription
titlestring-e.g. "Order #4821" or "Repair job 1093".
subtitlestring-Line under the title.
stepsOrderStep[]-{ id, label, description, time }[]. The description shows while the step is current.
currentStepnumber0Index of the step in progress. Earlier steps show as done, steps.length marks everything done.
etaDate | string | number-Expected arrival. Drives the live countdown and the Expected time.
etaLabelstring"Arriving in"Label over the countdown, e.g. "Ready in".
doneLabelstring"Delivered"Shown once every step is done.
courierOrderCourier-name, and optional avatar (photo URL), vehicle and rating.
onContact(method: "call" | "message") => void-Adds call and message buttons by the courier.
itemsOrderItem[]-{ id, name, quantity, and optional variant, price, image, imageAlt }[], shown in an expandable list.
totalnumber-Overrides the sum of item prices.
defaultItemsOpenbooleanfalseStart with the item list open.
currencystring"$"Symbol shown before prices.
localestring"en-US"Used for the Expected time.