Chat UIs are multi-pane layouts: channel sidebar, message feed, and optional detail panel. Once UI Pro blocks handle the composition — agents should start from Chat1, not invent bubble markup.
Chat layout zones
A production chat interface has three panes:
Zone
Purpose
Block
Left sidebar
Channels, DMs, search
Sidebar4
Center feed
Messages, threads, composer
Feed3
Right panel
Thread details, members, files
Sidebar5
Task bundle: packages/core/ai/tasks/chat.json
Pro block: packages/core/ai/examples/blocks/Chat1.tsx
Three-pane Row
The simplest chat shell is a full-height Row with three children: Sidebar4, Feed3, and Sidebar5.For resizable panes, wrap sections in SplitView — the dev sandbox (apps/dev/src/app/(main)/chat/page.tsx) uses this for adjustable sidebar widths.Install the blocks first:
npx once-ui add Chat1 Feed3 Sidebar4 Sidebar5
Then adapt imports from the Pro block source.
Message feed patterns
Feed3 uses a thread-without-bubbles style — messages are rows with avatar, name, timestamp, and body text. This reads cleaner in productivity apps (Linear, Discord, Slack) than chat bubbles.Each message row:
Add EmojiPickerDropdown beside the input for emoji selection — don't build a custom picker.
Scroll and fade edges
Long message lists need scroll affordance. Wrap the message list in a Fade component with edges top and bottom, and put the list inside a Scroller.Fade.edge is a common gotcha — the edges prop must be an array like ["top", "bottom"], not a boolean.
Streaming and agent replies
For AI chat, show activity while the model generates:
Stream tokens into the message body as they arrive. Keep the composer disabled until the stream completes, or allow the user to cancel with a stop button.
Members view swap
Chat1 swaps the center pane when the user selects "Members" from the sidebar — same shell, different content. Render Table1 with member data instead of Feed3 when the active sidebar item is Members.
This pattern avoids a separate route for every sidebar item.
Quality checklist
Check
Rule
Layout
Row fill — three panes, not nested Columns
Scroll
Scroller inside Fade with edge strips
Avatars
Avatar with size="m" in message rows
Emoji
EmojiPickerDropdown — don't invent picker UI
Badges
One status badge per row — no duplicate Badge
Agent note
chat.json references blocks Chat1, Feed3, Sidebar4, Sidebar5. Load examples/blocks/Chat1.tsx for structure before generating. Gotcha keys: Fade.edge, Badge.duplicate.