Chat
A messaging demo at /chat: a searchable conversation list on the left, a message thread with sent and received bubbles on the right, and a composer that keeps the thread pinned to the newest message. No chat library, just Input, Button, cn, and a little state.
See it live
Open /chat (sidebar → shadcn/ui → Chat). Pick a conversation, type a message, press Enter or Send.
Anatomy
Data
model
type Msg = { id: number; from: "me" | "them"; text: string; time: string };
type Convo = {
id: number;
name: string;
role: string;
color: string; // avatar bg (static Tailwind class)
messages: Msg[];
};Auto-scroll
A ref on the thread, plus an effect keyed on the message count, keeps the view pinned to the latest bubble.
auto-scroll
React.useEffect(() => {
const el = scrollRef.current;
if (el) el.scrollTop = el.scrollHeight;
}, [active.messages.length, activeId]);Swap the demo state for your API
Conversations and messages live in local state here. Point
setConvos at your backend (or a socket) and the UI stays exactly the same. Avatar colors follow the same static-Tailwind convention as the tab and calendar color labels.