Components / Message Scroller
Message Scroller
The scrollable transcript region for chat UIs: anchored turns that keep part of the previous message in view, an AutoScroll follow that disengages the moment the reader scrolls away, prepend preservation for loading older history, and jump-to-message. A chat extra outside the Base UI set, no Radix or Base UI counterpart, same precedent as DataGrid. Click "Add message" below and scroll up to feel the disengage. This preview is the real component running in WebAssembly.
Examples
<ZitsMessageScrollerProvider AutoScroll="true" DefaultScrollPosition="end">
<ZitsMessageScroller class="h-80 rounded-2xl border">
<ZitsMessageScrollerViewport class="px-4 py-3">
<ZitsMessageScrollerContent>
@foreach (var m in _messages)
{
<ZitsMessageScrollerItem @key="m.Id" MessageId="m.Id" ScrollAnchor="m.Anchor">
<ZitsMessage Align="@(m.Role == "user" ? "end" : "start")">
<ZitsMessageContent>
<ZitsBubble>
<ZitsBubbleContent>@m.Text</ZitsBubbleContent>
</ZitsBubble>
</ZitsMessageContent>
</ZitsMessage>
</ZitsMessageScrollerItem>
}
</ZitsMessageScrollerContent>
</ZitsMessageScrollerViewport>
<ZitsMessageScrollerButton />
</ZitsMessageScroller>
</ZitsMessageScrollerProvider>Anatomy
The provider renders no DOM of its own: it owns the scroll state and cascades it to everything inside, so the frame can sit anywhere below it.
ZitsMessageScrollerProvider (no DOM; owns scroll state)
└── ZitsMessageScroller (frame, fills its parent)
├── ZitsMessageScrollerViewport (scroll container)
│ └── ZitsMessageScrollerContent
│ └── ZitsMessageScrollerItem (one per row)
└── ZitsMessageScrollerButton (scroll-to-end control)Installation
navius add chatAPI reference
ZitsMessageScrollerProvider (root, no DOM):
| Prop | Type | Default |
|---|---|---|
| AutoScroll | bool | false |
| DefaultScrollPosition | string | "end" |
| ScrollEdgeThreshold | double | 8 |
| ScrollMargin | double | 0 |
| ScrollPreviousItemPeek | double | 64 |
ZitsMessageScrollerViewport (the scroll container, needs a bounded height from its ancestors):
| Prop | Type | Default |
|---|---|---|
| PreserveScrollOnPrepend | bool | true |
ZitsMessageScrollerContent:
| Prop | Type | Default |
|---|---|---|
| SpacerClass | string? | - |
ZitsMessageScrollerItem (one per row; give it a stable MessageId and @key):
| Prop | Type | Default |
|---|---|---|
| MessageId | string? | - |
| ScrollAnchor | bool | false |
ZitsMessageScrollerButton (scroll-to-start/end control, appears only while the viewport can scroll that way):
| Prop | Type | Default |
|---|---|---|
| Direction | string | "end" |
| Behavior | string | "smooth" |
| Variant | string | "secondary" |
| Size | string | "icon-sm" |
For programmatic control, inject the cascaded MessageScrollerContext (from Navius.Primitives.Components.MessageScroller) anywhere inside the provider: ScrollToMessageAsync, ScrollToStartAsync, ScrollToEndAsync, plus the ScrollableStart/ScrollableEnd, CurrentAnchorId, and VisibleMessageIds readouts.