DocsSupportPricing
Roadmap (has updates coming soon)XFigma3.7K
Sign inGet All-Access
  1. Components
  2. Message Scroller
MarkdownPro 13 blocks

Shadcn Message Scroller

Browse 6 production-ready shadcn message scroller components for AI chat transcripts, streaming replies, anchored turns, jump-to-latest controls, and history that prepends above the reader. The scroll container is headless underneath and composes with Message, Bubble, Card and Input Group, so the transcript matches your Shadcn Create tokens without a chat framework.

For AI Agents

Hand your agent this brief or the ReUI MCP, not a screenshot. Free to install.

When to use

  • Chat and assistant transcripts in a bounded panel that open on the newest turn and offer a jump back to it
  • Streaming replies that follow the bottom until the reader scrolls up, with sent questions lifted near the top
  • Saved threads that reopen at a chosen turn, load older history above the reader or step between questions

When not to use

  • The layout of a single turn, its avatar, sender name and timestamp around the body: use the Message component
  • A sidebar, settings list or panel that overflows but never grows at the bottom: use the Scroll Area component
  • A finished assistant screen with composer, thread list, citations and docked panels: use the AI Chat blocks

Agent notes

  • The parts and hooks throw outside MessageScrollerProvider, so a header or footer control that calls a hook needs the provider above it too
  • MessageScroller fills its parent through size-full, so bound the parent height or the page scrolls instead of the transcript
  • Render MessageScrollerButton as a sibling of MessageScrollerViewport; placed inside it, the control scrolls away with the rows
Markdownhttps://web.dev.reui.io/components/message-scroller.md
MCPget_component("message-scroller")
Installnpx shadcn@latest add message-scroller
Full index for agents:llms.txtReUI MCP setup

Shadcn Message Scroller: Streaming, Anchored Turns and Prepended History

Shadcn Message Scroller is the scroll container under a chat transcript. It owns the 4 things that go wrong when the scrolling is written by hand: opening at the newest message, following a reply while tokens arrive, letting go the instant the reader scrolls up, and holding the reader's place when older turns mount above them.

The 6 components here take those one at a time. A transcript that opens at the live edge with a jump-to-latest control. A reply that streams and follows the bottom until the reader intervenes. A sent message anchored near the top with a peek of the turn before it. The 3 opening positions compared side by side. Older messages prepended with no jump. A footer navigator that steps between turns from outside the scroll area.

It is composed, not configured. A headless provider holds the scroll state, the viewport is the element that scrolls, the content region is the log, each row is an item, and the button is the jump control. Rows are yours: pair them with Shadcn Message for layout, Shadcn Bubble for the body, and Shadcn Marker for day separators and system notes.

What is Shadcn Message Scroller?

A message scroller is a bounded scroll region for a list that grows at the bottom. Shadcn Message Scroller splits that into 6 parts: MessageScrollerProvider holds the state and renders no DOM, MessageScroller is the positioning root, MessageScrollerViewport is the element that actually scrolls, MessageScrollerContent is the log, MessageScrollerItem is a row, and MessageScrollerButton is the jump control. The button is a sibling of the viewport rather than a child of it, because the root is what positions it.

The accessible defaults are already wired. The viewport ships a region role, an aria-label of 'Messages' and tabIndex 0, so the transcript is reachable and scrollable from the keyboard with no prop of your own. The content region is a log with aria-relevant set to additions, so assistive technology announces the new turn instead of re-reading the thread. Rows carry content-visibility auto, so a long transcript only pays layout for what is near the viewport.

Why Use Shadcn Message Scroller?

Hand-rolled chat scrolling fails in a predictable order. An effect that calls scrollIntoView on every token fights the reader who scrolled up to re-read something. An at-the-bottom check that tests for exact zero never fires on a fractional device pixel. Loading older messages resets the scroll offset and throws the reader to the top of the thread. This component answers each one: autoScroll follows the live edge only while the reader is already there, scrollEdgeThreshold gives at-the-bottom an 8 pixel tolerance, and preserveScrollOnPrepend restores the reader's row after older turns mount above it.

These 6 components stop at the transcript, which is where the paid work starts. The composer with context chips, a stop control while the model is still typing, citations, branching threads, and the assistant panel docked beside a page all live in the ReUI Pro AI Chat blocks, 12 assembled screens built on this exact component. 11 of those 12 import the same shadcn MessageScroller you install from this page, so what you evaluate for free here is the foundation they sit on.

Shadcn Message Scroller Features

  • Follow the Live Edge. autoScroll pins the viewport to the newest message while a reply streams, and releases the moment the reader scrolls, spins the wheel, drags on touch, or presses ArrowUp, ArrowDown, PageUp, PageDown, Home, End or Space. The jump-to-latest button re-engages it.
  • 3 Opening Positions. defaultScrollPosition takes 'start', 'end' (the default) or 'last-anchor'. The last option opens a reopened thread at the top of the final exchange rather than at its last line, which is what makes a saved conversation readable again.
  • Anchored Turns. scrollAnchor on a row lifts it near the top when it arrives, and scrollPreviousItemPeek (64 pixels by default) keeps a slice of the previous turn on screen so the thread reads as continuous instead of restarted.
  • Prepend Without a Jump. preserveScrollOnPrepend is on by default. When older messages mount above the reader, the row they were reading stays where it was. Give rows a stable messageId so the restore has a specific row to hold.
  • A Jump Control That Goes Inert. MessageScrollerButton takes a direction of 'start' or 'end' and smooth or instant behavior. With nothing to scroll toward it drops to tabIndex -1 and reports itself inactive, so it fades out and leaves no empty keyboard stop behind. It renders through a Shadcn Button, so variant and size are yours.
  • Hooks for Controls Outside the Frame. useMessageScroller returns scrollToEnd, scrollToStart and scrollToMessage. useMessageScrollerScrollable reports whether more thread exists in either direction. useMessageScrollerVisibility reports the current anchor and the visible message ids, and only tracks while something subscribes to it.
  • Shadcn Create Compatible. All 8 Shadcn Create styles (Vega, Nova, Maia, Lyra, Mira, Luma, Sera and Rhea) and the Radius, Font Family and Color Scale controls apply to these previews and to the code you export, so the transcript matches the rest of your app.

Composing the Transcript Around It

The scroller owns scrolling and nothing else, so the row is yours to build. Shadcn Message places an avatar beside the body and flips the side for the reader's own turns, Shadcn Bubble styles the body, Shadcn Avatar fills the media slot, and Shadcn Marker handles day separators, system notes and handoff rows. Wrap the whole thing in a Shadcn Card: the root fills its parent, so the parent is what gives it a height to scroll inside.

The chrome around the transcript is ordinary shadcn too. A composer is a Shadcn Input Group in the card footer. A working or answered state is a Shadcn Badge in the header, with a Shadcn Spinner while a reply is in flight. Code inside an answer is a Shadcn Code Block, which brings its own stick-to-bottom handling for source that is still streaming. None of it assumes a chat SDK.

Integrating With Other Components

Build the row from Shadcn Message for the avatar and side, Shadcn Bubble for the body, and Shadcn Avatar in the media slot. Use Shadcn Marker for day separators, system notes and handoff rows, and mark only the turn-starting rows with scrollAnchor so anchoring and the last-anchor opening position have something to aim at.

Give the scroller a height with a Shadcn Card, then fill the chrome around it: a Shadcn Input Group composer in the footer, a Shadcn Badge and a Shadcn Spinner for reply state in the header, Shadcn Tabs when one panel holds several threads, and a Shadcn Code Block for source inside an answer.

When the transcript is done and the product around it is not, the ReUI Pro AI Chat blocks are 12 assembled screens on this same component, 11 of them importing the shadcn MessageScroller from this page: copilot shells, docked and floating panels, welcome screens, branching threads and grounded answers with citations. Next to them sit 5 Agent Activity blocks for the operator view of a run and 10 Agents dashboards, which lay their feeds out themselves rather than through this scroller.

AI Chat Blocks in ReUI Pro

The free examples above pair with 13 production ready ai chat blocks in ReUI Pro, complete sections built on the same primitives and ready to copy into your app.

  • AI Chat (13 blocks)Conversation surfaces for AI products, from full chat shells to embeddable threads, sheets, and launchers.

Browse all AI & Agents blocks

Frequently Asked Questions

How do I stop the transcript from scrolling while someone is reading?

Pass autoScroll and let it release itself. Following the live edge stops on any sign of reader intent: a scroll, a wheel tick, a touch drag, or ArrowUp, ArrowDown, PageUp, PageDown, Home, End or Space. It resumes when the reader returns to the bottom or presses the jump-to-latest button. There is no flag of yours to manage.

Why is the transcript invisible for one frame on first paint?

That is deliberate. The root reports a pending scroll until the opening position has been applied, and the viewport stays invisible for that frame. The trade is a blank frame instead of watching the view jump from the top of the thread to the bottom. It resolves on the first paint after mount.

How do I load older messages without throwing the reader to the top?

preserveScrollOnPrepend is already on, so mounting older rows above the reader keeps their row in place. One placement rule matters: put the load control outside the content list, in the card header for example. The viewport recognises a prepend by the row that used to be first moving down the list, so a permanent 'Load earlier' row rendered as the first child never moves and the restore never runs.

What does the last-anchor opening position do?

It opens the thread at the top of the last anchored turn rather than at the very bottom, so someone reopening a conversation lands on the question and reads down into the answer. It keys on rows marked with scrollAnchor, not on who sent them, and falls back to the end when there is no anchor to use.

Can I drive the scroll from a control outside the transcript?

Yes, and that is the reason the provider is separate from the scroll frame. Put the provider around the whole card and any header chip or footer navigator can call useMessageScroller to run scrollToEnd, scrollToStart or scrollToMessage, read useMessageScrollerScrollable for whether more thread exists either way, or read useMessageScrollerVisibility for the turn being read. The hooks only work inside the provider.

Is it accessible to keyboard and screen reader users?

The defaults cover the structural part: the viewport is a focusable region with an aria-label you should replace with something specific, the content is a log that announces additions, and the jump button carries an sr-only label and stops being a focus stop when it is inactive. You still own the rest. Set aria-busy on the content while a reply streams and announce the in-flight state from a separate live region, or the log narrates every token.

Does it lock me into a chat SDK or a framework?

No. The behavior comes from the framework-neutral @shadcn/react package, the parts render plain elements, and the component never touches your data. Rows come from whatever state you already have, streaming or not. Installing it through the shadcn CLI pulls the package and the Shadcn Button it renders the jump control with, and nothing else.
Previous7 Shadcn Message Components
Next6 Shadcn Native Select Components

Start building with ReUI Pro today.

Every Pro block, every style, and every future addition, with one license for unlimited projects.

Get All-Access

From $249, once. Lifetime updates.

Application

  • App Shell
  • Auth
  • Card
  • Dashboard
  • Dialog
  • Empty State
  • Event Calendar
  • Flow
  • Form
  • Gantt
  • Kanban Board
  • List
  • Navbar
  • Onboarding
  • Profile
  • Rich Text Editor
  • Schedule
  • Settings
  • Sheet
  • Stats2 meter cards moved here from Charts, 17 in all
  • Timeline
  • Whiteboard
  • Wizard

Data Grid

  • Base
  • AdvancedAdded 2 new Data Grid Advanced blocks, 5 in all
  • Columns
  • Drag & Drop
  • Editing
  • Expansion
  • Filtering
  • Grouping
  • Virtualization

Charts

  • Area ChartAdded a new Inbound Leads area chart block
  • Bar Chart
  • Composed Chart
  • Line Chart
  • Pie Chart
  • Radial Chart
  • Sankey ChartNew Sankey Chart category with 3 flow chart blocks
  • Slope ChartNew Slope Chart category with 2 rank-shift chart blocks
  • Sparkline
  • Status Tracker

AI & Agents

  • AI Chat
  • Agent Activity
  • AI UsageNew AI Usage category with 2 spend blocks

Solutions

  • Dev Ops
  • AI Ops
  • CRM
  • Agents
  • Analytics
  • Billing
  • Bookings
  • Files
  • Inventory
  • Users
  • Digital TwinNew Digital Twin category with 2 interactive 3D blocks

Templates

  • All templates

eCommerce

  • Category Card
  • Checkout
  • Comparison
  • Coupon
  • Filter Sidebar
  • Product Card
  • Product Detail
  • Product Grid
  • Receipt
  • Review
  • Shopping Cart
  • Wishlist
  • Shop Hero

Marketing

  • Blog
  • Compare
  • Contact
  • CTA
  • FAQ
  • Hero
  • How It Works
  • Pricing

Resources

  • Components
  • Blocks
  • Icons
  • MCP for Agents
  • Docs
  • Support
  • Pricing
  • Tailwind Plus Alternative
  • Roadmap(has updates coming soon)
  • AffiliateSoon

Legal

  • Privacy Policy
  • Terms & Conditions
  • License
  • Refunds
  • Cookies

© 2026 ReUI. All rights reserved.

3.7K

A scroll region that opens at the live edge with a jump to latest control.

autoScroll pins the viewport while tokens arrive, and releases the moment the reader scrolls up.

scrollAnchor lifts a sent message near the top while a slice of the previous turn stays visible.

Compare start, end and last-anchor as the place a reopened thread opens at.

Older turns prepend above the reader while the row they were reading stays put.

A footer navigator that reports the turn you are reading and jumps between turns.