3

Message Scroller

An auto-scrolling viewport for chat messages, with a scroll-to-latest button. Built on @shadcn/react.

Last updated August 8, 2026

CreditsModifiedPublished

Copied from shadcn/ui.

  • Dropped upstream's scroll-fade-b/scrollbar-thin/scrollbar-gutter-stable custom Tailwind utilities (not available in this repo) in favor of plain overflow-y-auto
  • Replaced the multi-icon-library IconPlaceholder abstraction with a plain lucide-react ArrowDownIcon
  • Replaced physical inset positioning with logical start-1/2

Overview

Scroll up inside the viewport below, then use the button to jump back to the latest message.

Hey! Are you around?
Yep, what's up?
Can you review my PR?
Sure, sending feedback now.
Thanks, appreciate it!
"use client"
 
import { Bubble, BubbleContent } from "@/components/ui/bubble"
import {
  MessageScroller,
  MessageScrollerButton,
  MessageScrollerContent,
  MessageScrollerItem,
  MessageScrollerProvider,
  MessageScrollerViewport,
} from "@/components/ui/message-scroller"
 
const messages = [
  { id: "1", align: "start" as const, text: "Hey! Are you around?" },
  { id: "2", align: "end" as const, text: "Yep, what's up?" },
  { id: "3", align: "start" as const, text: "Can you review my PR?" },
  { id: "4", align: "end" as const, text: "Sure, sending feedback now." },
  { id: "5", align: "start" as const, text: "Thanks, appreciate it!" },
]
 
export function MessageScrollerDemoExample() {
  return (
    <MessageScrollerProvider>
      <MessageScroller className="h-56 w-full max-w-sm rounded-xl border border-border">
        <MessageScrollerViewport>
          <MessageScrollerContent className="p-4">
            {messages.map((message) => (
              <MessageScrollerItem key={message.id}>
                <Bubble align={message.align}>
                  <BubbleContent>{message.text}</BubbleContent>
                </Bubble>
              </MessageScrollerItem>
            ))}
          </MessageScrollerContent>
        </MessageScrollerViewport>
        <MessageScrollerButton />
      </MessageScroller>
    </MessageScrollerProvider>
  )
}

Installation

$ npx shadcn@latest add https://ui.persian-labs.ir/r/message-scroller.json

Usage

import {
  MessageScroller,
  MessageScrollerButton,
  MessageScrollerContent,
  MessageScrollerItem,
  MessageScrollerProvider,
  MessageScrollerViewport,
} from "@/components/ui/message-scroller"
 
export function Example() {
  return (
    <MessageScrollerProvider>
      <MessageScroller className="h-56">
        <MessageScrollerViewport>
          <MessageScrollerContent>
            {messages.map((message) => (
              <MessageScrollerItem key={message.id}>
                {message.text}
              </MessageScrollerItem>
            ))}
          </MessageScrollerContent>
        </MessageScrollerViewport>
        <MessageScrollerButton />
      </MessageScroller>
    </MessageScrollerProvider>
  )
}

RTL

سلام! هستی؟
بله، چیکار داری؟
میشه PR من رو بررسی کنی؟
حتماً، الان بازخورد می‌فرستم.
ممنون، لطف کردی!
"use client"
 
import { Bubble, BubbleContent } from "@/components/ui/bubble"
import {
  MessageScroller,
  MessageScrollerButton,
  MessageScrollerContent,
  MessageScrollerItem,
  MessageScrollerProvider,
  MessageScrollerViewport,
} from "@/components/ui/message-scroller"
 
const messages = [
  { id: "1", align: "start" as const, text: "سلام! هستی؟" },
  { id: "2", align: "end" as const, text: "بله، چیکار داری؟" },
  { id: "3", align: "start" as const, text: "میشه PR من رو بررسی کنی؟" },
  { id: "4", align: "end" as const, text: "حتماً، الان بازخورد می‌فرستم." },
  { id: "5", align: "start" as const, text: "ممنون، لطف کردی!" },
]
 
export function MessageScrollerRtlExample() {
  return (
    <MessageScrollerProvider>
      <MessageScroller className="h-56 w-full max-w-sm rounded-xl border border-border">
        <MessageScrollerViewport>
          <MessageScrollerContent className="p-4">
            {messages.map((message) => (
              <MessageScrollerItem key={message.id}>
                <Bubble align={message.align}>
                  <BubbleContent>{message.text}</BubbleContent>
                </Bubble>
              </MessageScrollerItem>
            ))}
          </MessageScrollerContent>
        </MessageScrollerViewport>
        <MessageScrollerButton />
      </MessageScroller>
    </MessageScrollerProvider>
  )
}

API Reference

MessageScrollerProvider

MessageScrollerItem

MessageScrollerButton