Theme
Customize appearance
Components
Message Scroller
Keep a conversation scrollable as messages are added.
View component source ↗Preview
A minimal example to get started.
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.jsonUsage
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
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNodeReact.ReactNode | — | Content rendered inside this component. |
autoScroll | boolean | undefinedboolean | undefined | — | Configures auto scroll; see the accepted type. |
defaultScrollPosition | MessageScrollerDefaultScrollPosition | undefinedMessageScrollerDefaultScrollPosition | undefined | — | Configures default scroll position; see the accepted type. |
scrollEdgeThreshold | number | undefinednumber | undefined | — | Configures scroll edge threshold; see the accepted type. |
scrollPreviousItemPeek | number | undefinednumber | undefined | — | Configures scroll previous item peek; see the accepted type. |
scrollMargin | number | undefinednumber | undefined | — | Configures scroll margin; see the accepted type. |
MessageScroller
| Prop | Type | Default | Description |
|---|---|---|---|
ref | React.Ref<HTMLDivElement> | undefinedReact.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 | undefinedboolean | undefined | — | Initial checked state for an uncontrolled control. |
defaultValue | string | number | readonly string[] | undefinedstring | number | readonly string[] | undefined | — | Initial value for an uncontrolled component. |
className | string | undefinedstring | undefined | — | Additional CSS classes merged with the component styles. |
id | string | undefinedstring | undefined | — | Unique identifier used to associate labels and descriptions. |
children | React.ReactNodeReact.ReactNode | — | Content rendered inside this component. |
onFocus | React.FocusEventHandler<HTMLDivElement> | undefinedReact.FocusEventHandler<HTMLDivElement> | undefined | — | Called when the control receives focus. |
onBlur | React.FocusEventHandler<HTMLDivElement> | undefinedReact.FocusEventHandler<HTMLDivElement> | undefined | — | Called when the control loses focus. |
onChange | React.ChangeEventHandler<HTMLDivElement, Element> | undefinedReact.ChangeEventHandler<HTMLDivElement, Element> | undefined | — | Called when the underlying form control changes; inspect the event for its value. |
onKeyDown | React.KeyboardEventHandler<HTMLDivElement> | undefinedReact.KeyboardEventHandler<HTMLDivElement> | undefined | — | Called when a key is pressed while this element is focused. |
onClick | React.MouseEventHandler<HTMLDivElement> | undefinedReact.MouseEventHandler<HTMLDivElement> | undefined | — | Called when the element is activated. |
MessageScrollerViewport
| Prop | Type | Default | Description |
|---|---|---|---|
ref | React.Ref<HTMLDivElement> | undefinedReact.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 | undefinedboolean | undefined | — | Initial checked state for an uncontrolled control. |
defaultValue | string | number | readonly string[] | undefinedstring | number | readonly string[] | undefined | — | Initial value for an uncontrolled component. |
className | string | undefinedstring | undefined | — | Additional CSS classes merged with the component styles. |
id | string | undefinedstring | undefined | — | Unique identifier used to associate labels and descriptions. |
children | React.ReactNodeReact.ReactNode | — | Content rendered inside this component. |
onFocus | React.FocusEventHandler<HTMLDivElement> | undefinedReact.FocusEventHandler<HTMLDivElement> | undefined | — | Called when the control receives focus. |
onBlur | React.FocusEventHandler<HTMLDivElement> | undefinedReact.FocusEventHandler<HTMLDivElement> | undefined | — | Called when the control loses focus. |
onChange | React.ChangeEventHandler<HTMLDivElement, Element> | undefinedReact.ChangeEventHandler<HTMLDivElement, Element> | undefined | — | Called when the underlying form control changes; inspect the event for its value. |
onKeyDown | React.KeyboardEventHandler<HTMLDivElement> | undefinedReact.KeyboardEventHandler<HTMLDivElement> | undefined | — | Called when a key is pressed while this element is focused. |
onClick | React.MouseEventHandler<HTMLDivElement> | undefinedReact.MouseEventHandler<HTMLDivElement> | undefined | — | Called when the element is activated. |
preserveScrollOnPrepend | boolean | undefinedboolean | undefined | — | Configures preserve scroll on prepend; see the accepted type. |
MessageScrollerContent
| Prop | Type | Default | Description |
|---|---|---|---|
ref | React.Ref<HTMLDivElement> | undefinedReact.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 | undefinedboolean | undefined | — | Initial checked state for an uncontrolled control. |
defaultValue | string | number | readonly string[] | undefinedstring | number | readonly string[] | undefined | — | Initial value for an uncontrolled component. |
className | string | undefinedstring | undefined | — | Additional CSS classes merged with the component styles. |
id | string | undefinedstring | undefined | — | Unique identifier used to associate labels and descriptions. |
children | React.ReactNodeReact.ReactNode | — | Content rendered inside this component. |
onFocus | React.FocusEventHandler<HTMLDivElement> | undefinedReact.FocusEventHandler<HTMLDivElement> | undefined | — | Called when the control receives focus. |
onBlur | React.FocusEventHandler<HTMLDivElement> | undefinedReact.FocusEventHandler<HTMLDivElement> | undefined | — | Called when the control loses focus. |
onChange | React.ChangeEventHandler<HTMLDivElement, Element> | undefinedReact.ChangeEventHandler<HTMLDivElement, Element> | undefined | — | Called when the underlying form control changes; inspect the event for its value. |
onKeyDown | React.KeyboardEventHandler<HTMLDivElement> | undefinedReact.KeyboardEventHandler<HTMLDivElement> | undefined | — | Called when a key is pressed while this element is focused. |
onClick | React.MouseEventHandler<HTMLDivElement> | undefinedReact.MouseEventHandler<HTMLDivElement> | undefined | — | Called when the element is activated. |
spacerClassName | string | undefinedstring | undefined | — | Configures spacer class name; see the accepted type. |
MessageScrollerItem
| Prop | Type | Default | Description |
|---|---|---|---|
ref | React.Ref<HTMLDivElement> | undefinedReact.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 | undefinedboolean | undefined | — | Initial checked state for an uncontrolled control. |
defaultValue | string | number | readonly string[] | undefinedstring | number | readonly string[] | undefined | — | Initial value for an uncontrolled component. |
className | string | undefinedstring | undefined | — | Additional CSS classes merged with the component styles. |
id | string | undefinedstring | undefined | — | Unique identifier used to associate labels and descriptions. |
children | React.ReactNodeReact.ReactNode | — | Content rendered inside this component. |
onFocus | React.FocusEventHandler<HTMLDivElement> | undefinedReact.FocusEventHandler<HTMLDivElement> | undefined | — | Called when the control receives focus. |
onBlur | React.FocusEventHandler<HTMLDivElement> | undefinedReact.FocusEventHandler<HTMLDivElement> | undefined | — | Called when the control loses focus. |
onChange | React.ChangeEventHandler<HTMLDivElement, Element> | undefinedReact.ChangeEventHandler<HTMLDivElement, Element> | undefined | — | Called when the underlying form control changes; inspect the event for its value. |
onKeyDown | React.KeyboardEventHandler<HTMLDivElement> | undefinedReact.KeyboardEventHandler<HTMLDivElement> | undefined | — | Called when a key is pressed while this element is focused. |
onClick | React.MouseEventHandler<HTMLDivElement> | undefinedReact.MouseEventHandler<HTMLDivElement> | undefined | — | Called when the element is activated. |
messageId | string | undefinedstring | undefined | — | Stable identifier for this message. |
scrollAnchor | boolean | undefinedboolean | undefined | false | Marks a message as a scroll anchor. |
MessageScrollerButton
| Prop | Type | Default | Description |
|---|---|---|---|
ref | React.Ref<HTMLButtonElement> | undefinedReact.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 | undefinedboolean | undefined | — | Prevents user interaction. |
name | string | undefinedstring | 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[] | undefinedstring | number | readonly string[] | undefined | — | The current value when controlled by the application. |
defaultChecked | boolean | undefinedboolean | undefined | — | Initial checked state for an uncontrolled control. |
defaultValue | string | number | readonly string[] | undefinedstring | number | readonly string[] | undefined | — | Initial value for an uncontrolled component. |
className | string | undefinedstring | undefined | — | Additional CSS classes merged with the component styles. |
id | string | undefinedstring | undefined | — | Unique identifier used to associate labels and descriptions. |
children | React.ReactNodeReact.ReactNode | — | Content rendered inside this component. |
onFocus | React.FocusEventHandler<HTMLButtonElement> | undefinedReact.FocusEventHandler<HTMLButtonElement> | undefined | — | Called when the control receives focus. |
onBlur | React.FocusEventHandler<HTMLButtonElement> | undefinedReact.FocusEventHandler<HTMLButtonElement> | undefined | — | Called when the control loses focus. |
onChange | React.ChangeEventHandler<HTMLButtonElement, Element> | undefinedReact.ChangeEventHandler<HTMLButtonElement, Element> | undefined | — | Called when the underlying form control changes; inspect the event for its value. |
onKeyDown | React.KeyboardEventHandler<HTMLButtonElement> | undefinedReact.KeyboardEventHandler<HTMLButtonElement> | undefined | — | Called when a key is pressed while this element is focused. |
onClick | React.MouseEventHandler<HTMLButtonElement> | undefinedReact.MouseEventHandler<HTMLButtonElement> | undefined | — | Called when the element is activated. |
render | RenderProp<MessageScrollerButtonRenderState> | undefinedRenderProp<MessageScrollerButtonRenderState> | undefined | — | Element or render function used to compose a custom root element. |
behavior | ScrollBehavior | undefinedScrollBehavior | undefined | — | Configures behavior; see the accepted type. |
direction | MessageScrollerButtonDirection | undefinedMessageScrollerButtonDirection | 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.