Theme

Customize appearance

Components

Message Scroller

Keep a conversation scrollable as messages are added.

View component source ↗

Preview

A minimal example to get started.

Message 1: your latest project update.

Message 2: your latest project update.

Message 3: your latest project update.

Message 4: your latest project update.

Message 5: your latest project update.

Message 6: your latest project update.

Message 7: your latest project update.

Message 8: your latest project update.

Installation

Install this component and its dependencies in a project initialized with shadcn.

pnpm dlx shadcn@latest add https://ui.hyunjoon.net/r/message-scroller.json

Usage

This is the basic example. Use the Code tab above for the selected example. Adjust import aliases to match your project.

import {
  MessageScrollerProvider,
  MessageScroller,
  MessageScrollerViewport,
  MessageScrollerContent,
  MessageScrollerItem,
  MessageScrollerButton,
} from "@/components/ui/message-scroller";

export default function Example() {
  return (
    <div className="h-56 w-full max-w-sm rounded-lg border">
      <MessageScrollerProvider>
        <MessageScroller>
          <MessageScrollerViewport>
            <MessageScrollerContent className="p-4">
              {Array.from({ length: 8 }, (_, index) => (
                <MessageScrollerItem key={index} messageId={String(index)}>
                  <p className="rounded-lg bg-muted p-3 text-sm">
                    Message {index + 1}: your latest project update.
                  </p>
                </MessageScrollerItem>
              ))}
            </MessageScrollerContent>
          </MessageScrollerViewport>
          <MessageScrollerButton aria-label="Scroll to latest message" />
        </MessageScroller>
      </MessageScrollerProvider>
    </div>
  );
}

API reference

Derived from the installed component types. Native DOM props are also supported where applicable. A dash means no explicit default is documented. Some props depend on the selected mode.

MessageScrollerProvider
MessageScrollerProvider properties
PropTypeDefaultDescription
children
React.ReactNode
React.ReactNode
—Content rendered inside this component.
autoScroll
boolean | undefined
boolean | undefined
—Configures auto scroll; see the accepted type.
defaultScrollPosition
MessageScrollerDefaultScrollPosition | undefined
MessageScrollerDefaultScrollPosition | undefined
—Configures default scroll position; see the accepted type.
scrollEdgeThreshold
number | undefined
number | undefined
—Configures scroll edge threshold; see the accepted type.
scrollPreviousItemPeek
number | undefined
number | undefined
—Configures scroll previous item peek; see the accepted type.
scrollMargin
number | undefined
number | undefined
—Configures scroll margin; see the accepted type.
MessageScroller
MessageScroller properties
PropTypeDefaultDescription
ref
React.Ref<HTMLDivElement> | undefined
React.Ref<HTMLDivElement> | undefined
—Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
defaultChecked
boolean | undefined
boolean | undefined
—Initial checked state for an uncontrolled control.
defaultValue
string | number | readonly string[] | undefined
string | number | readonly string[] | undefined
—Initial value for an uncontrolled component.
className
string | undefined
string | undefined
—Additional CSS classes merged with the component styles.
id
string | undefined
string | undefined
—Unique identifier used to associate labels and descriptions.
children
React.ReactNode
React.ReactNode
—Content rendered inside this component.
onFocus
React.FocusEventHandler<HTMLDivElement> | undefined
React.FocusEventHandler<HTMLDivElement> | undefined
—Called when the control receives focus.
onBlur
React.FocusEventHandler<HTMLDivElement> | undefined
React.FocusEventHandler<HTMLDivElement> | undefined
—Called when the control loses focus.
onChange
React.ChangeEventHandler<HTMLDivElement, Element> | undefined
React.ChangeEventHandler<HTMLDivElement, Element> | undefined
—Called when the underlying form control changes; inspect the event for its value.
onKeyDown
React.KeyboardEventHandler<HTMLDivElement> | undefined
React.KeyboardEventHandler<HTMLDivElement> | undefined
—Called when a key is pressed while this element is focused.
onClick
React.MouseEventHandler<HTMLDivElement> | undefined
React.MouseEventHandler<HTMLDivElement> | undefined
—Called when the element is activated.
MessageScrollerViewport
MessageScrollerViewport properties
PropTypeDefaultDescription
ref
React.Ref<HTMLDivElement> | undefined
React.Ref<HTMLDivElement> | undefined
—Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
defaultChecked
boolean | undefined
boolean | undefined
—Initial checked state for an uncontrolled control.
defaultValue
string | number | readonly string[] | undefined
string | number | readonly string[] | undefined
—Initial value for an uncontrolled component.
className
string | undefined
string | undefined
—Additional CSS classes merged with the component styles.
id
string | undefined
string | undefined
—Unique identifier used to associate labels and descriptions.
children
React.ReactNode
React.ReactNode
—Content rendered inside this component.
onFocus
React.FocusEventHandler<HTMLDivElement> | undefined
React.FocusEventHandler<HTMLDivElement> | undefined
—Called when the control receives focus.
onBlur
React.FocusEventHandler<HTMLDivElement> | undefined
React.FocusEventHandler<HTMLDivElement> | undefined
—Called when the control loses focus.
onChange
React.ChangeEventHandler<HTMLDivElement, Element> | undefined
React.ChangeEventHandler<HTMLDivElement, Element> | undefined
—Called when the underlying form control changes; inspect the event for its value.
onKeyDown
React.KeyboardEventHandler<HTMLDivElement> | undefined
React.KeyboardEventHandler<HTMLDivElement> | undefined
—Called when a key is pressed while this element is focused.
onClick
React.MouseEventHandler<HTMLDivElement> | undefined
React.MouseEventHandler<HTMLDivElement> | undefined
—Called when the element is activated.
preserveScrollOnPrepend
boolean | undefined
boolean | undefined
—Configures preserve scroll on prepend; see the accepted type.
MessageScrollerContent
MessageScrollerContent properties
PropTypeDefaultDescription
ref
React.Ref<HTMLDivElement> | undefined
React.Ref<HTMLDivElement> | undefined
—Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
defaultChecked
boolean | undefined
boolean | undefined
—Initial checked state for an uncontrolled control.
defaultValue
string | number | readonly string[] | undefined
string | number | readonly string[] | undefined
—Initial value for an uncontrolled component.
className
string | undefined
string | undefined
—Additional CSS classes merged with the component styles.
id
string | undefined
string | undefined
—Unique identifier used to associate labels and descriptions.
children
React.ReactNode
React.ReactNode
—Content rendered inside this component.
onFocus
React.FocusEventHandler<HTMLDivElement> | undefined
React.FocusEventHandler<HTMLDivElement> | undefined
—Called when the control receives focus.
onBlur
React.FocusEventHandler<HTMLDivElement> | undefined
React.FocusEventHandler<HTMLDivElement> | undefined
—Called when the control loses focus.
onChange
React.ChangeEventHandler<HTMLDivElement, Element> | undefined
React.ChangeEventHandler<HTMLDivElement, Element> | undefined
—Called when the underlying form control changes; inspect the event for its value.
onKeyDown
React.KeyboardEventHandler<HTMLDivElement> | undefined
React.KeyboardEventHandler<HTMLDivElement> | undefined
—Called when a key is pressed while this element is focused.
onClick
React.MouseEventHandler<HTMLDivElement> | undefined
React.MouseEventHandler<HTMLDivElement> | undefined
—Called when the element is activated.
spacerClassName
string | undefined
string | undefined
—Configures spacer class name; see the accepted type.
MessageScrollerItem
MessageScrollerItem properties
PropTypeDefaultDescription
ref
React.Ref<HTMLDivElement> | undefined
React.Ref<HTMLDivElement> | undefined
—Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
defaultChecked
boolean | undefined
boolean | undefined
—Initial checked state for an uncontrolled control.
defaultValue
string | number | readonly string[] | undefined
string | number | readonly string[] | undefined
—Initial value for an uncontrolled component.
className
string | undefined
string | undefined
—Additional CSS classes merged with the component styles.
id
string | undefined
string | undefined
—Unique identifier used to associate labels and descriptions.
children
React.ReactNode
React.ReactNode
—Content rendered inside this component.
onFocus
React.FocusEventHandler<HTMLDivElement> | undefined
React.FocusEventHandler<HTMLDivElement> | undefined
—Called when the control receives focus.
onBlur
React.FocusEventHandler<HTMLDivElement> | undefined
React.FocusEventHandler<HTMLDivElement> | undefined
—Called when the control loses focus.
onChange
React.ChangeEventHandler<HTMLDivElement, Element> | undefined
React.ChangeEventHandler<HTMLDivElement, Element> | undefined
—Called when the underlying form control changes; inspect the event for its value.
onKeyDown
React.KeyboardEventHandler<HTMLDivElement> | undefined
React.KeyboardEventHandler<HTMLDivElement> | undefined
—Called when a key is pressed while this element is focused.
onClick
React.MouseEventHandler<HTMLDivElement> | undefined
React.MouseEventHandler<HTMLDivElement> | undefined
—Called when the element is activated.
messageId
string | undefined
string | undefined
—Stable identifier for this message.
scrollAnchor
boolean | undefined
boolean | undefined
falseMarks a message as a scroll anchor.
MessageScrollerButton
MessageScrollerButton properties
PropTypeDefaultDescription
ref
React.Ref<HTMLButtonElement> | undefined
React.Ref<HTMLButtonElement> | undefined
—Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref).
disabled
boolean | undefined
boolean | undefined
—Prevents user interaction.
name
string | undefined
string | undefined
—Field name used in form data.
type
"button" | "submit" | "reset" | undefined
"button" | "submit" | "reset" | undefined
—The native input or button behavior.
value
string | number | readonly string[] | undefined
string | number | readonly string[] | undefined
—The current value when controlled by the application.
defaultChecked
boolean | undefined
boolean | undefined
—Initial checked state for an uncontrolled control.
defaultValue
string | number | readonly string[] | undefined
string | number | readonly string[] | undefined
—Initial value for an uncontrolled component.
className
string | undefined
string | undefined
—Additional CSS classes merged with the component styles.
id
string | undefined
string | undefined
—Unique identifier used to associate labels and descriptions.
children
React.ReactNode
React.ReactNode
—Content rendered inside this component.
onFocus
React.FocusEventHandler<HTMLButtonElement> | undefined
React.FocusEventHandler<HTMLButtonElement> | undefined
—Called when the control receives focus.
onBlur
React.FocusEventHandler<HTMLButtonElement> | undefined
React.FocusEventHandler<HTMLButtonElement> | undefined
—Called when the control loses focus.
onChange
React.ChangeEventHandler<HTMLButtonElement, Element> | undefined
React.ChangeEventHandler<HTMLButtonElement, Element> | undefined
—Called when the underlying form control changes; inspect the event for its value.
onKeyDown
React.KeyboardEventHandler<HTMLButtonElement> | undefined
React.KeyboardEventHandler<HTMLButtonElement> | undefined
—Called when a key is pressed while this element is focused.
onClick
React.MouseEventHandler<HTMLButtonElement> | undefined
React.MouseEventHandler<HTMLButtonElement> | undefined
—Called when the element is activated.
render
RenderProp<MessageScrollerButtonRenderState> | undefined
RenderProp<MessageScrollerButtonRenderState> | undefined
—Element or render function used to compose a custom root element.
behavior
ScrollBehavior | undefined
ScrollBehavior | undefined
—Configures behavior; see the accepted type.
direction
MessageScrollerButtonDirection | undefined
MessageScrollerButtonDirection | undefined
"end"Direction applied to layout or scrolling.
variant
"link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | null | undefined
"link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | null | undefined
"secondary"Visual treatment of the component.
size
"default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | null | undef…
"default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined
"icon-sm"Visual size of the component.

Usage notes

Wrap the scroller in MessageScrollerProvider and give its parent a fixed height. Assign each item a stable messageId.