Skip to content
All Taste components

App screens

Store orders

An online store’s order list with today’s numbers, status tabs, bulk actions and payment and fulfilment badges.

sidebar · stat strip · tabs · bulk-action bar · selectable table · 7 statuses

Orders

Orders

2 orders are waiting to be packed for today’s 4 pm pickup.

Orders today
38
↑ 6 vs yesterday
To fulfil
14
2 selected
Revenue today
₹61,820
↑ 8.4%
Returns
3
1.1% of orders
2 selected
OrderDateCustomerPaymentFulfilmentTotal
#3291Today, 10:42Priya Menon · BengaluruPaidUnfulfilled₹2,340
#3290Today, 09:15Arjun Kapoor · PunePaidUnfulfilled₹1,180
#3289Today, 08:03Fatima Shaikh · MumbaiCODPacked₹860
#3288YesterdayRohan Das · KolkataPaidShipped₹4,520
#3287YesterdayNeha Iyer · ChennaiRefundedReturned₹1,640
#3286YesterdayVikram Singh · JaipurPaidDelivered₹3,075
#328513 OctAnanya Bose · DelhiPendingUnfulfilled₹990
"use client";
import { useState } from "react";
import { Bell, Download, Globe, Home, Inbox, LineChart, Package, Percent, Plus, Search, Settings, Tag, Users } from "lucide-react";
import { cn } from "@/lib/utils";

const nav = [
  { label: "Home", icon: Home },
  { label: "Orders", icon: Inbox, count: 14, current: true },
  { label: "Products", icon: Tag },
  { label: "Customers", icon: Users },
  { label: "Discounts", icon: Percent },
  { label: "Analytics", icon: LineChart },
  { label: "Settings", icon: Settings },
];

const stats = [
  { label: "Orders today", value: "38", note: "↑ 6 vs yesterday" },
  { label: "To fulfil", value: "14", note: "Pickup at 4 pm" },
  { label: "Revenue today", value: "₹61,820", note: "↑ 8.4%" },
  { label: "Returns", value: "3", note: "1.1% of orders" },
];

const tabs = ["All", "Unfulfilled · 14", "Unpaid · 4", "Returns", "Archived"];

type Tone = "success" | "warning" | "info" | "danger" | "neutral";
const tone: Record<Tone, string> = {
  success: "bg-success-soft text-success-fg",
  warning: "bg-warning-soft text-warning-fg",
  info: "bg-info-soft text-info-fg",
  danger: "bg-danger-soft text-danger-fg",
  neutral: "bg-surface-2 text-fg-muted",
};

const orders: { id: string; date: string; customer: string; city: string; payment: [string, Tone]; fulfilment: [string, Tone]; total: string }[] = [
  { id: "#3291", date: "Today, 10:42", customer: "Priya Menon", city: "Bengaluru", payment: ["Paid", "success"], fulfilment: ["Unfulfilled", "warning"], total: "₹2,340" },
  { id: "#3290", date: "Today, 09:15", customer: "Arjun Kapoor", city: "Pune", payment: ["Paid", "success"], fulfilment: ["Unfulfilled", "warning"], total: "₹1,180" },
  { id: "#3289", date: "Today, 08:03", customer: "Fatima Shaikh", city: "Mumbai", payment: ["COD", "neutral"], fulfilment: ["Packed", "info"], total: "₹860" },
  { id: "#3288", date: "Yesterday", customer: "Rohan Das", city: "Kolkata", payment: ["Paid", "success"], fulfilment: ["Shipped", "info"], total: "₹4,520" },
  { id: "#3287", date: "Yesterday", customer: "Neha Iyer", city: "Chennai", payment: ["Refunded", "danger"], fulfilment: ["Returned", "neutral"], total: "₹1,640" },
  { id: "#3286", date: "Yesterday", customer: "Vikram Singh", city: "Jaipur", payment: ["Paid", "success"], fulfilment: ["Delivered", "success"], total: "₹3,075" },
  { id: "#3285", date: "13 Oct", customer: "Ananya Bose", city: "Delhi", payment: ["Pending", "warning"], fulfilment: ["Unfulfilled", "warning"], total: "₹990" },
];

export default function OrdersPage() {
  const [tab, setTab] = useState(0);
  const [selected, setSelected] = useState<string[]>(["#3291", "#3290"]);
  const toggle = (id: string) => setSelected((s) => (s.includes(id) ? s.filter((x) => x !== id) : [...s, id]));

  return (
    <div className="flex min-h-screen bg-bg font-sans text-sm text-fg">
      <aside aria-label="Main" className="hidden w-56 shrink-0 flex-col gap-0.5 border-r border-border bg-surface p-3 lg:flex">
        <p className="mb-2 flex h-8 items-center gap-2 px-1.5 font-medium">
          <span className="grid size-6 place-items-center rounded-sm bg-primary text-xs font-semibold text-primary-fg">K</span>Kaveri Store
        </p>
        <nav className="grid gap-0.5">
          {nav.map(({ label, icon: Icon, current, count }) => (
            <a key={label} href="#" aria-current={current ? "page" : undefined}
              className={cn("flex h-8 items-center gap-2.5 rounded px-2 font-medium text-fg-muted hover:bg-surface-2 hover:text-fg",
                current && "bg-bg text-fg shadow-sm ring-1 ring-border")}>
              <Icon className="size-4" aria-hidden />{label}
              {count && <span className="ml-auto text-xs tabular-nums text-fg-subtle">{count}</span>}
            </a>
          ))}
        </nav>
        <p className="px-2 pb-1 pt-4 text-[11px] font-medium text-fg-subtle">Sales channels</p>
        <a href="#" className="flex h-8 items-center gap-2.5 rounded px-2 font-medium text-fg-muted hover:bg-surface-2"><Globe className="size-4" aria-hidden />Online store</a>
        <a href="#" className="flex h-8 items-center gap-2.5 rounded px-2 font-medium text-fg-muted hover:bg-surface-2"><Package className="size-4" aria-hidden />Wholesale</a>
      </aside>

      <div className="flex min-w-0 flex-1 flex-col">
        <header className="flex h-14 items-center gap-3 border-b border-border px-4 sm:px-6">
          <p className="font-medium">Orders</p>
          <label className="ml-auto hidden h-9 w-64 items-center gap-2 rounded border border-border bg-surface px-2.5 text-fg-subtle md:flex">
            <Search className="size-4" aria-hidden />
            <input placeholder="Search orders" className="w-full bg-transparent text-[13px] text-fg outline-none placeholder:text-fg-subtle" />
          </label>
          <button type="button" aria-label="Notifications" className="grid size-9 place-items-center rounded text-fg-muted hover:bg-surface-2"><Bell className="size-4" aria-hidden /></button>
        </header>

        <main className="grid gap-4 p-4 sm:p-6">
          <div className="flex flex-wrap items-end justify-between gap-3">
            <div>
              <h1 className="text-xl font-medium tracking-tight">Orders</h1>
              <p className="text-fg-muted">2 orders are waiting to be packed for today’s 4 pm pickup.</p>
            </div>
            <div className="flex gap-2">
              <button type="button" className="inline-flex h-9 items-center gap-1.5 rounded border border-border-strong px-3 font-medium hover:bg-surface"><Download className="size-4" aria-hidden /> Export</button>
              <button type="button" className="inline-flex h-9 items-center gap-1.5 rounded bg-primary px-3 font-medium text-primary-fg hover:bg-primary-hover"><Plus className="size-4" aria-hidden /> Create order</button>
            </div>
          </div>

          <section aria-label="Today" className="grid grid-cols-2 gap-3 xl:grid-cols-4">
            {stats.map((s) => (
              <div key={s.label} className="rounded-lg border border-border px-4 py-3">
                <p className="text-xs text-fg-muted">{s.label}</p>
                <p className="mt-0.5 text-xl font-medium tabular-nums">{s.value}</p>
                <p className="text-xs text-fg-subtle">{s.note}</p>
              </div>
            ))}
          </section>

          <section aria-label="Order list" className="overflow-hidden rounded-lg border border-border">
            <div role="tablist" className="flex gap-4 overflow-x-auto border-b border-border px-4">
              {tabs.map((t, i) => (
                <button key={t} role="tab" type="button" aria-selected={tab === i} onClick={() => setTab(i)}
                  className="-mb-px h-10 whitespace-nowrap border-b-2 border-transparent text-[13px] font-medium text-fg-muted aria-selected:border-primary aria-selected:text-fg">{t}</button>
              ))}
            </div>
            {selected.length > 0 && (
              <div className="flex items-center gap-2 border-b border-border bg-primary-soft px-4 py-2 text-[13px] text-primary-soft-fg">
                <span className="font-medium">{selected.length} selected</span>
                <button type="button" className="ml-2 h-7 rounded border border-border-strong bg-bg px-2.5 text-xs font-medium text-fg">Mark as packed</button>
                <button type="button" className="h-7 rounded border border-border-strong bg-bg px-2.5 text-xs font-medium text-fg">Print labels</button>
                <button type="button" onClick={() => setSelected([])} className="ml-auto text-xs font-medium">Clear</button>
              </div>
            )}
            <div className="overflow-x-auto">
              <table className="w-full text-[13px]">
                <thead className="bg-surface text-left text-xs text-fg-subtle">
                  <tr>
                    <th className="w-10 px-4 py-2"><input type="checkbox" aria-label="Select all" className="size-4 accent-primary"
                      checked={selected.length === orders.length} onChange={(e) => setSelected(e.target.checked ? orders.map((o) => o.id) : [])} /></th>
                    <th className="px-4 py-2 font-medium">Order</th><th className="px-4 py-2 font-medium">Date</th><th className="px-4 py-2 font-medium">Customer</th>
                    <th className="px-4 py-2 font-medium">Payment</th><th className="px-4 py-2 font-medium">Fulfilment</th><th className="px-4 py-2 text-right font-medium">Total</th>
                  </tr>
                </thead>
                <tbody className="divide-y divide-border">
                  {orders.map((o) => (
                    <tr key={o.id} className={cn("whitespace-nowrap hover:bg-surface", selected.includes(o.id) && "bg-surface")}>
                      <td className="px-4 py-2.5"><input type="checkbox" className="size-4 accent-primary" aria-label={"Select order " + o.id} checked={selected.includes(o.id)} onChange={() => toggle(o.id)} /></td>
                      <td className="px-4 py-2.5 font-medium tabular-nums">{o.id}</td>
                      <td className="px-4 py-2.5 text-fg-muted">{o.date}</td>
                      <td className="px-4 py-2.5"><span className="font-medium">{o.customer}</span> <span className="text-fg-subtle">· {o.city}</span></td>
                      <td className="px-4 py-2.5"><span className={cn("rounded-full px-2 py-0.5 text-xs font-medium", tone[o.payment[1]])}>{o.payment[0]}</span></td>
                      <td className="px-4 py-2.5"><span className={cn("inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-xs font-medium", tone[o.fulfilment[1]])}><span className="size-1.5 rounded-full bg-current" />{o.fulfilment[0]}</span></td>
                      <td className="px-4 py-2.5 text-right font-medium tabular-nums">{o.total}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </section>
        </main>
      </div>
    </div>
  );
}

The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.