Message Scroller
Scrolls a conversation, sticking to the newest message as it streams.
What is Constella?
Constella is a component library on Base UI and StyleX. Every value comes from a token, so a theme is one file, and the motion stays quiet: a press that gives, a popover that settles.
<MessageScrollerProvider> <MessageScroller> <MessageScrollerViewport aria-label="Conversation"> <MessageScrollerContent> {turns.map((turn) => ( <MessageScrollerItem key={turn.id} messageId={turn.id} scrollAnchor={turn.from === "user"} > <Message from={turn.from}>…</Message> </MessageScrollerItem> ))} </MessageScrollerContent> </MessageScrollerViewport> <MessageScrollerButton /> </MessageScroller></MessageScrollerProvider>Installation
$ npx shadcn@latest add @constella/message-scrollerUsage
import { MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport,} from "@/components/ai/message-scroller";It opens at the newest message and follows a streaming answer while the reader is at the end; scrolled up, it stays put and shows the button to jump back. History loaded above keeps the reader's place. Mark each user message a scrollAnchor, so a new question scrolls to the top. The behavior is shadcn's @shadcn/react/message-scroller.
Composition
MessageScrollerProvider└── MessageScroller ├── MessageScrollerViewport │ └── MessageScrollerContent │ └── MessageScrollerItem └── MessageScrollerButtonAPI Reference
| Part | Adds |
|---|---|
MessageScrollerItem | messageId; scrollAnchor |
MessageScrollerButton | A pill that rises in while there's more below |
useMessageScroller | scrollToEnd, scrollToStart, scrollToMessage |
Every part takes sx, applied last.