Component
Message scroller
A chat-style scroll container that sticks to the latest message. New content auto-scrolls while pinned to the bottom, a jump button appears when you scroll up, and the instance exposes methods to scroll to the start, end, or any message.
Auto-scroll & jump button
Autumn note #1 β leaves, weather, and city recorded.
Autumn note #2 β leaves, weather, and city recorded.
Autumn note #3 β leaves, weather, and city recorded.
Autumn note #4 β leaves, weather, and city recorded.
Autumn note #5 β leaves, weather, and city recorded.
Autumn note #6 β leaves, weather, and city recorded.
Autumn note #7 β leaves, weather, and city recorded.
Autumn note #8 β leaves, weather, and city recorded.
import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
import { HbButtonComponent, HbMessageScrollerImports } from '@herbst/ui';
@Component({
selector: 'hb-demo-message-scroller-basic',
imports: [HbMessageScrollerImports, HbButtonComponent],
template: `
<div class="flex w-full max-w-md flex-col gap-2">
<hb-message-scroller hbAutoScroll class="h-64 rounded-md border border-border">
<hb-message-scroller-viewport>
<hb-message-scroller-content class="flex flex-col gap-2 p-3">
@for (line of lines(); track $index) {
<hb-message-scroller-item [hbMessageId]="'m-' + $index">
<div class="w-fit rounded-lg bg-muted px-3 py-2 text-sm">{{ line }}</div>
</hb-message-scroller-item>
}
</hb-message-scroller-content>
</hb-message-scroller-viewport>
<hb-message-scroller-button />
</hb-message-scroller>
<button hb-button hbSize="sm" class="self-start" (click)="send()">Send message</button>
</div>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class HbDemoMessageScrollerBasicComponent {
protected readonly lines = signal(
Array.from(
{ length: 8 },
(_, i) => `Autumn note #${i + 1} β leaves, weather, and city recorded.`,
),
);
protected send(): void {
this.lines.update((list) => [...list, `New note #${list.length + 1} just added.`]);
}
}
Programmatic controls & anchors
Message #1
Message #2
Message #3
Message #4
Message #5
Message #6
Message #7
Message #8
Message #9
Message #10 Β· anchor
Message #11
Message #12
Message #13
Message #14
Message #15
Message #16
atBottom: true
API reference
hb-message-scroller
| Property | Description | Type | Default |
|---|---|---|---|
| [hbAutoScroll] | Keep the view pinned to the bottom as new content arrives β until the user scrolls up. | boolean | true |
| [hbDefaultScrollPosition] | Where to land on first render: the end, the start, or the last anchored item. | 'end' | 'start' | 'last-anchor' | 'end' |
| [hbScrollPreviousItemPeek] | Pixels of the previous item to leave visible when scrolling to a message or anchor. | number | 0 |
| exportAs "hbMessageScroller" | Reference the instance to call scrollToEnd(), scrollToStart(), scrollToMessage(id), and read the atBottom(), scrollableStart(), scrollableEnd() signals. | methods / signals | β |
Parts
| Property | Description | Type | Default |
|---|---|---|---|
| hb-message-scroller-viewport | The scrollable region. Must wrap the content and drives the scroll tracking. | component | β |
| hb-message-scroller-content | The inner wrapper whose size is observed to trigger auto-scroll. | component | β |
| hb-message-scroller-item [hbMessageId] [hbScrollAnchor] | Wraps each message; the id is the scrollToMessage target, and hbScrollAnchor marks it for last-anchor positioning. | string / boolean | '' / false |
| hb-message-scroller-button [hbIcon] | A floating jump-to-latest button, shown only when there is content below. hbIcon sets the icon name. | string | 'phosphorCaretDown' |