Chat composer
A chat page splits into two regions: the scrollable transcript and a sticky composer. r-conversation owns the transcript (bottom-follow, row reconciliation, and a footer slot). The composer is plain markup you place in that slot.
Layout shell
Wire streaming rows and send handling in script; this demo shows only structure.
Pieces
| Piece | Role |
|---|---|
r-conversation |
Renders the event log; footer stays above the keyboard-safe area |
r-markdown |
Typical row for assistant prose (mode="streaming" during tokens) |
r-input or <textarea> |
Text entry; paste/drag for files stays on the host you choose |
r-attachments |
Staged files; call add() from picker, paste, or drop |
r-voice-button |
Speech-to-text into the input when you wire createSpeechRecognizer |
r-token-meter |
Context window fill; drive used from stream usage chunks |
Event shape and SSE folding live in ranuts/stream and ranuts/conversation. For a full wiring walkthrough, see Build AI chat.