All Taste components
Animated app UI
Order tracking timeline
A delivery timeline that fills from the first step down to where the parcel is now, with the live step pulsing.
5 steps · done / live / upcoming · line fill · courier progress · status badge
Order #SX-20418
In transitArriving Thursday, 17 Oct
- OrderedPaid by card
- PackedBlue Pine Supply, Pune
- ShippedHanded to courier
- Out for deliveryWith Ravi, 6 stops away
- DeliveredBy 6 pm today
Ravi is on the way Koregaon Park · about 40 min
import { Check, MapPin, Truck } from "lucide-react";
import { cn } from "@/lib/utils";
/* Add once to globals.css:
@keyframes fill-down { from { transform: scaleY(0); } }
@keyframes breathe { from { transform: scale(1); opacity: .6; } to { transform: scale(1.35); opacity: .16; } }
*/
const steps = [
{ title: "Ordered", text: "Paid by card", time: "Mon 10:12" },
{ title: "Packed", text: "Blue Pine Supply, Pune", time: "Mon 16:40" },
{ title: "Shipped", text: "Handed to courier", time: "Tue 09:05" },
{ title: "Out for delivery", text: "With Ravi, 6 stops away", time: "Thu 08:30" },
{ title: "Delivered", text: "By 6 pm today", time: "" },
];
const current = 3;
const STEP = 0.38; // seconds per step — the line reaches each dot as it pops
export function OrderTracking() {
return (
<section aria-labelledby="order-title" className="mx-auto grid max-w-[440px] gap-[18px] rounded-lg border border-border bg-bg p-5 font-sans">
<div className="flex flex-wrap items-start justify-between gap-3">
<div>
<p className="text-xs tabular-nums text-fg-subtle">Order #SX-20418</p>
<h2 id="order-title" className="text-[17px] font-medium text-fg">Arriving Thursday, 17 Oct</h2>
</div>
<span className="inline-flex items-center gap-1.5 rounded-full bg-info-soft px-2 py-0.5 text-xs font-medium text-info-fg">
<span className="size-1.5 animate-pulse rounded-full bg-current motion-reduce:animate-none" />In transit
</span>
</div>
<ol className="grid">
{steps.map((s, i) => {
const done = i < current, now = i === current;
return (
<li key={s.title} aria-current={now ? "step" : undefined} className="relative grid grid-cols-[24px_1fr_auto] gap-x-3 pb-5 last:pb-0">
{i < steps.length - 1 && (
<span aria-hidden className="absolute bottom-0.5 left-[11px] top-[26px] w-0.5 overflow-hidden rounded bg-surface-2">
{done && <span className="block h-full origin-top bg-primary animate-[fill-down_.34s_linear_both] motion-reduce:animate-none" style={{ animationDelay: i * STEP + 0.08 + "s" }} />}
</span>
)}
<span
className={cn(
"relative grid size-6 place-items-center rounded-full border-[1.5px] animate-pop motion-reduce:animate-none",
done && "border-primary bg-primary text-primary-fg",
now && "border-primary bg-primary-soft",
!done && !now && "border-border-strong bg-bg",
)}
style={{ animationDelay: i * STEP + "s" }}
>
{done && <Check className="size-3.5" aria-hidden />}
{now && <span className="size-2 rounded-full bg-primary" />}
{now && <span aria-hidden className="absolute -inset-[5px] rounded-full border-2 border-primary animate-[breathe_1.6s_ease-in-out_infinite_alternate] motion-reduce:animate-none" />}
</span>
<span className="grid pt-0.5 text-[13.5px] animate-rise motion-reduce:animate-none" style={{ animationDelay: i * STEP + 0.08 + "s" }}>
<b className={done || now ? "font-medium text-fg" : "font-normal text-fg-muted"}>{s.title}</b>
<span className="text-xs text-fg-subtle">{s.text}</span>
</span>
<time className="pt-[3px] text-xs tabular-nums text-fg-subtle">{s.time}</time>
</li>
);
})}
</ol>
<div className="grid gap-2.5 rounded-lg bg-surface p-3.5 animate-rise [animation-delay:1500ms] motion-reduce:animate-none">
<div className="flex items-center gap-2.5">
<span className="grid size-8 place-items-center rounded bg-primary-soft text-primary-soft-fg"><Truck className="size-4" aria-hidden /></span>
<div className="min-w-0 flex-1">
<p className="text-[15px] font-medium text-fg">Ravi is on the way</p>
<p className="flex items-center gap-1 text-xs text-fg-subtle"><MapPin className="size-3" aria-hidden />Koregaon Park · about 40 min</p>
</div>
</div>
<div className="h-1.5 overflow-hidden rounded-full bg-surface-2">
<span className="block h-full w-[70%] origin-left rounded-full bg-primary animate-grow-x [animation-delay:1650ms] motion-reduce:animate-none" />
</div>
</div>
</section>
);
}
The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.