ThreadTemplate
StableA conversation that scrolls, with the message box fixed at the bottom.
Also known as chat layout, chat page layout
Install with npm install @tattva/ui (setup), or copy the code from the kit in Downloads.
A conversation with a message box
Onboarding email draft
AI can make mistakes. Check important information.
<div className="h-105 overflow-hidden rounded-card border border-line">
<AppShell>
<ThreadTemplate header="Onboarding email draft" composer={<Composer onSend={() => {}} />} footnote={<AIDisclosure />}>
<MessageList>
<Message role="user">Draft a welcome email for new customers.</Message>
<Message role="assistant">Here is a short draft you can adapt.</Message>
</MessageList>
</ThreadTemplate>
</AppShell>
</div>The title sits above the conversation. Messages scroll while the message box stays put.
When to use it
A conversation that scrolls, with the message box fixed at the bottom. Both share one width, so the text people read and the box they type in line up.
Made of: Title row · Scrolling conversation · Message box at the bottom · Note
Use it for
- Any chat once the first message is sent.
- A running workflow shown as a conversation, with checklists and approval requests.
- A screen with a title bar and controls such as Share.
Not for
- A new chat before the first message: use HomeTemplate.
- Work that should stay in view beside the chat: use SplitCanvasTemplate.
Do and avoid
Lisbon trip
Lisbon trip
Do
- Place it directly inside AppShell so it fills the main area.
- Wrap messages in MessageList so screen readers announce new ones.
- Use it for workflows too. It can hold a checklist, steps and approval requests.
- Use the note for the AI notice so it stays close to the input.
Avoid
- Do not put it in a space with no set height. The conversation cannot scroll and the message box will not stay at the bottom.
- Do not put the message box inside the conversation. It would scroll away.
- Do not give the conversation a different width. The shared width keeps text and input lined up.
On a phone
- Side padding is 1rem on a phone and 1.5rem from the sm breakpoint, and the column is capped at 48rem.
- The messages scroll in their own area while the composer stays at the bottom.
- The composer area adds the bottom safe area to its padding, so it clears the home bar on a phone.
Properties
| Prop | Type | Default | Description |
|---|---|---|---|
| header | ReactNode | none | Optional title row above the thread. Rendered in a 56px header element. |
| childrenrequired | ReactNode | none | The conversation or workflow body. Scrolls inside a max-w-3xl column. |
| composerrequired | ReactNode | none | The input, pinned to the bottom in the same column width as the body. |
| footnote | ReactNode | none | Rendered under the composer, for example AIDisclosure. |
"Show code under the preview gives the code for the example on the stage."
Tokens
Change one of these and every part that uses it follows.
max-w-3xl--fg-muted (header)px-4 sm:px-6 gutters
Built in
- The title bar holds the page's top heading.
- The message box sits outside the scrolling area, so it never scrolls away.
- Reading order goes title, conversation, message box, note.
What you need to do
- Wrap messages in MessageList, so screen readers hear new ones. The template announces nothing.
- Pass a header. Without one, the page's top heading is empty.
- Place it inside AppShell, which supplies the main area.
Built toward WCAG 2.2 AA and checked automatically; no independent audit yet. Read the accessibility guide