Transcript panel
In review
The composition shell for agent and chat feeds (WS1 #2652c). Every row already ships: chat bubble, agent message, tool-call card, the failure grammar, spawn cards. The shell owns what the rows can’t:
- Virtualization. Rows are keyed on a stable id (never an index). On Compose the
listStateparameter is the hook point (observe, restore, page); on Swift theScrollViewReaderproxy plays that role. - Day markers. A hairline-flanked muted label wherever consecutive items cross a
UTC day boundary;
dayLabelformats it. - Auto-follow. New items keep the panel pinned while the reader is AT the bottom; scrolling away suspends following, and the floating jump-to-latest circle appears (solid accent, the cyan floating-layer identity) to jump back and resume.
Same-sender grouping stays in the rows (the bubble grammar) by design.
NockerlAgentTranscriptPanel( items = listOf( NockerlTranscriptItem(key = "m1", epochMillis = t1) { NockerlChatBubble(/* … */) }, NockerlTranscriptItem(key = "m2", epochMillis = t2) { NockerlSpawnChildCard(/* … */) }, ), listState = rememberLazyListState(), // the virtualization hook modifier = Modifier.fillMaxWidth().weight(1f),)NockerlAgentTranscriptPanel( items: [ NockerlTranscriptItem(id: "m1", epochMillis: t1) { NockerlSpawnChildCard(name: "docs-reader", status: .success) }, ])| Prop | Type | Default | Description |
|---|---|---|---|
items |
List<NockerlTranscriptItem> |
n/a | The transcript, in order. key/id must be stable. |
listState |
LazyListState (Compose) |
remembered | The virtualization/scroll hook point. |
autoFollow |
Boolean |
true |
Pin to newest while at the bottom. |
dayLabel |
(Long) -> String |
day index | Formats a day marker from that day’s first millis. |
contentPadding |
PaddingValues (Compose) |
12dp vertical | List padding. |