shadcn.io is not affiliated with official shadcn/ui
Chat History Timeline Block for Radix UI
A team-chat archive of sixteen messages on a rail inside a fixed-height scroll region, with day heads, derived quiet-gap markers like 3 h 28 min later, a pin toggle per message and a Pinned moments list that scrolls to and focuses the message.
Installation
Overview
Keep the moments that mattered in a long conversation with this chat history timeline for React with Radix UI. It is written for Huddlemark, a fictional team-chat archive. A hairline frame with a plus mark on each corner holds sixteen messages from three days of an office-move channel on a vertical rail, inside a scroll region of fixed height that you can reach with the keyboard. Each sender has a lettermark avatar, your own messages sit one step in and tinted, and day heads and "3 h 28 min later" markers, derived from the typed times, break the log wherever more than an hour passed on one day. A Toggle with a pin on each message adds it to "Pinned moments" at the end of the panel, with its time and first words. Choosing a pinned moment scrolls the region to that message and focuses it, and the unpin button removes it; an Empty state holds the place when nothing is pinned. The header counts the pins. On a phone the pinned list drops under the region. For team archives, support logs and meeting follow-ups. The people and messages are example data.
FAQ
How do I change the messages?
Edit MESSAGES at the top of the file, oldest first. Each has an id, a from, an ISO time at in UTC and the text. The day heads and the quiet markers are derived from the times; QUIET_AFTER sets how many minutes count as quiet. A sender called "You" is drawn as your own message.
How does the jump work?
jumpTo finds the message by a data-msg attribute inside the scroll region, scrolls the region (not the page) so the message sits near the top, and focuses it. Under reduced motion it jumps without animation. The message is focusable but is not in the tab order.
Are the pins saved?
No. They are local state, two are set when the page loads, and nothing is sent. To keep them, store the pinned ids per person on your server and pass them in as the initial value.
Is it accessible?
The log is an ordered list inside a named, focusable region, with day heads as headings. Each pin is a toggle with an aria-pressed state and a name that says whose message and what time. The pinned moments are real buttons. The status line is a polite live region that says Pinned, Unpinned or Jumped.