36 / 37 · Thread
Thread list
Conversation history with unread marks and actions that wait for hover.
Today
Installation
npx shadcn@latest add "@assistant-ui/elements-thread-list"
Usage
import { ThreadList } from "@/components/elements/thread-list";
<ThreadList
threads={[
{ title: "Composer polish", time: "2m", unread: true },
{ title: "Runtime migration", time: "1h" },
]}
activeIndex={activeIndex}
onActiveIndexChange={setActiveIndex}
/>Props
threads*readonly ThreadItem[]Conversation rows with title, time, and optional unread mark.
activeIndex*numberIndex of the currently selected thread.
onActiveIndexChange(index: number) => voidCalled when the user clicks a thread row.
classNamestringExtra classes merged onto the root.
Source
thread-list.tsx"use client";
import { PencilIcon, Trash2Icon } from "lucide-react";
import { cn } from "@/lib/utils";
import { field, mono } from "./surfaces";
export interface ThreadItem {
title: string;
time: string;
unread?: boolean;
}
export function ThreadList({
threads,
activeIndex,
onActiveIndexChange,
className,
}: {
threads: readonly ThreadItem[];
activeIndex: number;
onActiveIndexChange?: (index: number) => void;
className?: string;
}) {
return (
<div
className={cn("flex w-full max-w-[240px] flex-col gap-0.5", className)}
>
<div className={cn(mono, "text-foreground/35 px-3 pb-1.5")}>Today</div>
{threads.map((thread, i) => {
const active = i === activeIndex;
return (
<button
key={thread.title}
type="button"
onClick={() => onActiveIndexChange?.(i)}
className={cn(
"group flex w-full items-center justify-between gap-2 rounded-xl px-3 py-2 text-start text-[13.5px] transition-colors",
active ? field : "hover:bg-foreground/[0.03]",
)}
>
<span className="flex-1 truncate">{thread.title}</span>
<span
className={cn(
mono,
"text-foreground/35 flex items-center gap-1.5 tabular-nums group-hover:hidden",
)}
>
{thread.unread && !active && (
<span
aria-hidden
className="size-1.5 rounded-full bg-blue-500 dark:bg-blue-400"
/>
)}
{thread.time}
</span>
<span className="hidden items-center gap-0.5 group-hover:flex">
<span className="text-foreground/45 hover:bg-foreground/[0.06] hover:text-foreground/90 rounded-full p-1">
<PencilIcon className="size-3" />
</span>
<span className="text-foreground/45 hover:bg-foreground/[0.06] hover:text-foreground/90 rounded-full p-1">
<Trash2Icon className="size-3" />
</span>
</span>
</button>
);
})}
</div>
);
}