All Taste components
App screens
Support inbox
A three-pane help desk: the conversation list, the thread with an internal note, and the customer’s details.
conversation list · unread · thread · internal note · reply/note composer · customer panel
Inbox
Search conversations
Kavya Reddy
Refund for order #3287
I sent the parcel back on Monday but…Refund
Imran Qureshi
Change delivery address
Can you deliver to my office instead?
Lakshmi Pillai
Bulk order for Diwali
We need 120 gift boxes by the 28th.Sales
Tenzin Norbu
Coupon not applying
FESTIVE10 says it has expired.
Harpreet Gill
Invoice with GST number
Please add our GSTIN to the bill.
Refund for order #3287
via email · Ticket 4821
KR
Hi, I sent the parcel back on Monday but haven’t got my refund yet. The courier says it was delivered to your warehouse on Wednesday.
SR
Internal note: return scanned in at 4:12 pm Wed. Quality check passed. OK to refund ₹1,640.
DK
Thanks for waiting, Kavya. Your return has been checked and we’ve started the refund of ₹1,640 to your UPI. It usually lands within 2 working days.
"use client";
import { useState } from "react";
import { BarChart3, BookOpen, ChevronDown, Filter, Inbox, Paperclip, Search, Send, Settings, Users, Zap } from "lucide-react";
import { cn } from "@/lib/utils";
const conversations = [
{ id: 4821, name: "Kavya Reddy", time: "2m", subject: "Refund for order #3287", preview: "I sent the parcel back on Monday but…", unread: true, tag: { label: "Refund", tone: "bg-danger-soft text-danger-fg" } },
{ id: 4820, name: "Imran Qureshi", time: "18m", subject: "Change delivery address", preview: "Can you deliver to my office instead?", unread: true },
{ id: 4817, name: "Lakshmi Pillai", time: "1h", subject: "Bulk order for Diwali", preview: "We need 120 gift boxes by the 28th.", tag: { label: "Sales", tone: "bg-info-soft text-info-fg" } },
{ id: 4815, name: "Tenzin Norbu", time: "3h", subject: "Coupon not applying", preview: "FESTIVE10 says it has expired." },
{ id: 4809, name: "Harpreet Gill", time: "Yesterday", subject: "Invoice with GST number", preview: "Please add our GSTIN to the bill." },
];
const messages = [
{ from: "customer", initials: "KR", meta: "Kavya · 10:31", text: "Hi, I sent the parcel back on Monday but haven’t got my refund yet. The courier says it was delivered to your warehouse on Wednesday." },
{ from: "note", initials: "SR", meta: "Sanjay · 10:36 · only your team sees this", text: "Internal note: return scanned in at 4:12 pm Wed. Quality check passed. OK to refund ₹1,640." },
{ from: "agent", initials: "DK", meta: "Divya · 10:41 · Seen", text: "Thanks for waiting, Kavya. Your return has been checked and we’ve started the refund of ₹1,640 to your UPI. It usually lands within 2 working days." },
] as const;
const customer = [
["Location", "Hyderabad"],
["Orders", "7"],
["Lifetime spend", "₹14,920"],
["Customer since", "Mar 2025"],
];
const rail = [
{ label: "Inbox", icon: Inbox, current: true },
{ label: "Customers", icon: Users },
{ label: "Help articles", icon: BookOpen },
{ label: "Reports", icon: BarChart3 },
];
export default function InboxPage() {
const [active, setActive] = useState(4821);
const [mode, setMode] = useState<"reply" | "note">("reply");
return (
<div className="flex h-screen bg-bg font-sans text-sm text-fg">
<nav aria-label="Main" className="hidden w-14 shrink-0 flex-col items-center gap-1 border-r border-border bg-surface py-3 md:flex">
<span className="mb-2 grid size-7 place-items-center rounded-sm bg-primary text-xs font-semibold text-primary-fg">H</span>
{rail.map(({ label, icon: Icon, current }) => (
<a key={label} href="#" aria-label={label} aria-current={current ? "page" : undefined}
className={cn("grid size-9 place-items-center rounded text-fg-muted hover:bg-surface-2 hover:text-fg", current && "bg-bg text-fg ring-1 ring-border")}>
<Icon className="size-4" aria-hidden />
</a>
))}
<a href="#" aria-label="Settings" className="mt-auto grid size-9 place-items-center rounded text-fg-muted hover:bg-surface-2"><Settings className="size-4" aria-hidden /></a>
</nav>
<section aria-label="Conversations" className="flex w-full flex-col border-r border-border sm:w-72 sm:shrink-0">
<div className="grid gap-2 px-4 pt-3">
<div className="flex items-center justify-between">
<h1 className="text-base font-medium">Inbox</h1>
<button type="button" aria-label="Filter" className="grid size-8 place-items-center rounded text-fg-muted hover:bg-surface-2"><Filter className="size-4" /></button>
</div>
<label className="flex h-9 items-center gap-2 rounded border border-border bg-surface px-2.5 text-fg-subtle">
<Search className="size-4" aria-hidden />
<input placeholder="Search conversations" className="w-full bg-transparent text-[13px] text-fg outline-none placeholder:text-fg-subtle" />
</label>
</div>
<ul className="mt-2 flex-1 overflow-y-auto border-t border-border">
{conversations.map((c) => (
<li key={c.id}>
<button type="button" onClick={() => setActive(c.id)} aria-current={active === c.id}
className={cn("relative grid w-full gap-0.5 border-b border-border px-4 py-2.5 text-left hover:bg-surface",
active === c.id && "bg-primary-soft before:absolute before:inset-y-0 before:left-0 before:w-0.5 before:bg-primary")}>
<span className="flex items-center gap-1.5 text-[13px]">
{c.unread && <span className="size-1.5 rounded-full bg-primary" aria-label="Unread" />}
<span className="font-medium">{c.name}</span>
<time className="ml-auto text-[11px] tabular-nums text-fg-subtle">{c.time}</time>
</span>
<span className="truncate text-[13px] font-medium">{c.subject}</span>
<span className="flex items-center gap-2">
<span className="flex-1 truncate text-xs text-fg-muted">{c.preview}</span>
{c.tag && <span className={cn("rounded-full px-1.5 py-px text-[10.5px] font-medium", c.tag.tone)}>{c.tag.label}</span>}
</span>
</button>
</li>
))}
</ul>
</section>
<section aria-label="Conversation" className="hidden min-w-0 flex-1 flex-col sm:flex">
<header className="flex h-14 items-center border-b border-border px-5">
<div><h2 className="font-medium">Refund for order #3287</h2><p className="text-xs text-fg-subtle">via email · Ticket 4821</p></div>
</header>
<ol className="flex flex-1 flex-col gap-4 overflow-y-auto bg-surface px-5 py-4">
{messages.map((m) => (
<li key={m.meta} className={cn("flex max-w-[88%] gap-2.5", m.from === "agent" && "flex-row-reverse self-end")}>
<span className={cn("grid size-7 shrink-0 place-items-center rounded-full text-[11px] font-semibold",
m.from === "note" ? "bg-surface-2 text-fg-muted" : "bg-primary-soft text-primary-soft-fg")}>{m.initials}</span>
<div>
<p className={cn("rounded-lg border px-3 py-2 text-[13px] leading-relaxed",
m.from === "customer" && "border-border bg-bg",
m.from === "note" && "border-dashed border-warning bg-warning-soft text-warning-fg",
m.from === "agent" && "border-transparent bg-primary text-primary-fg")}>{m.text}</p>
<p className={cn("mt-1 text-[11px] text-fg-subtle", m.from === "agent" && "text-right")}>{m.meta}</p>
</div>
</li>
))}
</ol>
<form onSubmit={(e) => e.preventDefault()} className="m-4 mt-3 rounded-lg border border-border-strong focus-within:ring-[3px] focus-within:ring-primary/20">
<div role="tablist" className="flex gap-3.5 border-b border-border px-3">
{(["reply", "note"] as const).map((t) => (
<button key={t} type="button" role="tab" aria-selected={mode === t} onClick={() => setMode(t)}
className="-mb-px h-8 border-b-2 border-transparent text-xs font-medium capitalize text-fg-muted aria-selected:border-primary aria-selected:text-fg">{t}</button>
))}
</div>
<textarea aria-label={mode === "reply" ? "Reply" : "Internal note"} rows={3}
placeholder={mode === "reply" ? "Write a reply…" : "Only your team sees notes"}
className={cn("block w-full resize-none bg-transparent px-3 py-2.5 text-[13px] outline-none placeholder:text-fg-subtle", mode === "note" && "bg-warning-soft")} />
<div className="flex items-center gap-1 px-2 pb-2">
<button type="button" aria-label="Attach file" className="grid size-8 place-items-center rounded text-fg-muted hover:bg-surface-2"><Paperclip className="size-4" /></button>
<button type="button" aria-label="Insert saved reply" className="grid size-8 place-items-center rounded text-fg-muted hover:bg-surface-2"><Zap className="size-4" /></button>
<button type="button" className="ml-auto h-8 rounded border border-border-strong px-3 text-[13px] font-medium hover:bg-surface">Send and close</button>
<button type="submit" className="inline-flex h-8 items-center gap-1.5 rounded bg-primary px-3 text-[13px] font-medium text-primary-fg hover:bg-primary-hover"><Send className="size-3.5" aria-hidden />Send</button>
</div>
</form>
</section>
<aside aria-label="Customer details" className="hidden w-60 shrink-0 flex-col gap-5 border-l border-border p-4 xl:flex">
<div className="flex items-center gap-2.5">
<span className="grid size-9 place-items-center rounded-full bg-primary-soft text-[13px] font-medium text-primary-soft-fg">KR</span>
<div className="min-w-0"><p className="font-medium">Kavya Reddy</p><p className="truncate text-xs text-fg-subtle">kavya.r@mailbox.in</p></div>
</div>
<div>
<h3 className="mb-2 text-[11px] font-medium text-fg-subtle">Customer</h3>
<dl className="grid gap-2 text-xs">
{customer.map(([k, v]) => (
<div key={k} className="flex justify-between"><dt className="text-fg-subtle">{k}</dt><dd className="font-medium tabular-nums">{v}</dd></div>
))}
</dl>
</div>
<div>
<h3 className="mb-2 text-[11px] font-medium text-fg-subtle">Assignee</h3>
<button type="button" className="flex h-8 w-full items-center gap-2 rounded border border-border-strong px-2.5 text-[13px] font-medium">
<span className="grid size-5 place-items-center rounded-full bg-primary-soft text-[9px] font-semibold text-primary-soft-fg">DK</span>
Divya Krishnan<ChevronDown className="ml-auto size-3.5 text-fg-subtle" aria-hidden />
</button>
</div>
</aside>
</div>
);
}
The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.