Chat
The Wally assistant panel: a header, a scrolling message log, and a footer gutter for suggestions, a docked approval card and the input. Chat is layout only — it holds no messages or agent state; the app renders UserMessage, AssistantMessage and ChatInput into ChatBody and ChatFooter from its own data. Header actions are composed from plain ghost Buttons and vertical Separators, so each one keeps its own aria-label and analytics attributes. background picks the decorative mesh: strong for an empty chat, subtle (default) once a conversation is running, none to drop it. Host the panel in a right-hand Drawer about 480px wide; ChatBody exposes its scroll element through ref for stick-to-bottom.
Usage
Examples
Header with thread select
Figma Variant2 (44:1465): children of ChatHeaderTitle follow a "/" joint — here a ghost thread
Select — and a New chat action leads the toolbar.
Greeting
The empty state (Figma 44:1464): the circle mark and a heading, with Large suggestion pills
centered under it, over the strong background.
Suggestions
Both placements: footer (Figma 91:1167) right-aligns Medium pills under a visible label,
greeting (Figma 44:1706) centers Large pills. The pill size follows the placement.
Backgrounds
The three background values side by side: strong (Figma Main, 12%), subtle (Figma Chat,
5%, the default) and none. The mesh is decorative and sits under every part.
Analytics
Analytics attributes go on the interactive parts only: data-analytics-id on a ChatSuggestion
lands on its <button>; header actions are plain DS Buttons and carry their own. Keep them off
the Chat root — a click anywhere inside would resolve to it.
Trigger
The app-header button that opens the panel (Figma 101:1034): the Wally mascot in a ghost small
Button, with an "Ask Wally" tooltip that doubles as its accessible name (label).
Trigger with drawer
ChatTrigger under DrawerTrigger asChild: the drawer owns the open state and aria-expanded,
the tooltip keeps its anchor through the shared trigger id.
Empty panel
The full empty panel: the greeting with Large suggestion pills over the strong background,
and the composer in the footer. A pill click would send its text as the first message.
Conversation
A finished turn: the user's question, then Wally's answer with collapsed reasoning, rendered markdown and a visible actions row; follow-up suggestions sit above the composer.
Streaming
A reply in flight: ChatBody and the message carry aria-busy, the running step shimmers,
and the submit is Stop. Stop (or Esc in the textarea) ends the run in this demo.
Approval docked
Human-in-the-loop: the pending ApprovalCard is docked in ChatFooter above the composer
while the run waits. Allow or Reject resolves it in place (so its live region and focus work)
and the answer continues.
Approval resolved
After the decision the docked card collapses to a one-line status and the answer completes.
Permissions
The per-conversation tool permissions sit inside the composer, between textarea and submit.
In drawer
The real host: ChatTrigger opens a 480px right-hand Drawer holding the conversation, and
Close is a DrawerClose. Esc in the textarea while running stops the reply instead of closing
the drawer; ChatInput handles that itself, so the host needs no onEscapeKeyDown.