Staaarter

Conversational Thread with Reactions

A rich conversational thread with time-grouped section headers like 'Today' and 'Yesterday', hand-formatted messages using bold text and lists, and a hover-revealed action bar on assistant messages with copy and thumbs up/down reaction buttons.

By Staaarter Team
Chat
Docs
Live preview

Docs

Installation

A real shadcn registry command, not a copy-paste stand-in: it fetches this block plus its avatar, avatar-initials, button dependencies and any missing npm packages, and installs them straight into your project.

npx shadcn add https://staaarter.com/r/conversational-thread-with-reactions.json

Prefer not to use the CLI? Copy the source from the Code toggle above into src/components/blocks/chat/chat12.tsx instead.

Usage

The file also exports chat12Demo, the exact props behind the preview above. Spread it to get a working section in one line, then replace it with your own data.

import { Chat12, chat12Demo } from "@/components/blocks/chat/chat12";

export default function Page() {
  return <Chat12 {...chat12Demo} />;
}

Props

PropTypeDefaultDescription
groupsChat12Group[]noneTime-grouped sections of messages, e.g. Today/Yesterday.
classNamestringnoneExtra classes for the outer wrapper element.

Types

export interface Chat12Message {
  id: string;
  role: "user" | "assistant";
  name: string;
  avatar?: { src: string; alt: string };
  timestamp: string;
  content: React.ReactNode;
  copyText: string;
}

export interface Chat12Group {
  label: string;
  messages: Chat12Message[];
}

Behavior notes

  • The action bar reveal on assistant messages is pure CSS (opacity-0 group-hover/msg:opacity-100 on a group wrapper), no JS is involved in showing/hiding it.
  • The thumbs up/down buttons are real per-message state (useState<Record<id, reaction>>), clicking toggles that message's reaction and highlights the active button.
  • The copy button calls navigator.clipboard.writeText with the message's plain-text copyText field and shows a real 'Copied' checkmark for 1.5s via useState + setTimeout, it is not decorative.
  • 'Today'/'Yesterday' are static literal group labels supplied as data, never computed from new Date(), so server and client render identically.
  • Rich formatting (bold, bullet lists) is hand-authored ReactNode content per message, there is no markdown parser dependency.