For AI agents: the complete documentation index is available at https://wallarm.github.io/design-system/llms.txt, the full documentation bundle is available at https://wallarm.github.io/design-system/llms-full.txt, and this page is available as Markdown at https://wallarm.github.io/design-system/components/chat.md.

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.

Source · Storybook

Usage

import { Button } from '@wallarm-org/design-system/Button';
import { Chat, ChatBody, ChatHeader, ChatHeaderActions, ChatHeaderTitle } from '@wallarm-org/design-system/Chat';
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@wallarm-org/design-system/DropdownMenu';
import { Ellipsis, History, X } from '@wallarm-org/design-system/icons';
import { Separator } from '@wallarm-org/design-system/Separator';

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.

Props

PropTypeDefaultDescription
backgroundChatBackground | undefinedsubtleDecorative mesh behind the panel (Figma chat-bg 67:1254). 'strong' is Main (12%, for an empty chat), 'subtle' is Chat (5%, for a running conversation), 'none' renders nothing.
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined
data-testidstring | undefined

ChatBody

PropTypeDefaultDescription
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined
data-testidstring | undefined

ChatFooter

PropTypeDefaultDescription
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined
data-testidstring | undefined

ChatGreeting

PropTypeDefaultDescription
title *ReactNodeHeading under the Wally mark, e.g. "How can I help you today?".
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined
data-testidstring | undefined

ChatHeader

PropTypeDefaultDescription
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined
data-testidstring | undefined

ChatHeaderActions

PropTypeDefaultDescription
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined
data-testidstring | undefined

ChatHeaderTitle

PropTypeDefaultDescription
labelReactNodeThe title shown when there are no children (e.g. a translation). Default: "Ask Wally".
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined
data-testidstring | undefined

ChatSuggestion

PropTypeDefaultDescription
disabledboolean | undefined
namestring | undefined
type"button" | "submit" | "reset" | undefined
valuestring | number | readonly string[] | undefined
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined
data-testidstring | undefined

ChatSuggestions

PropTypeDefaultDescription
placementChatSuggestionsPlacement | undefinedfooter'footer' (default, Figma 91:1167): right-aligned Medium pills above the input. 'greeting' (Figma 44:1706): centered Large pills under the greeting.
labelReactNodeVisible label (Figma "Suggestions"); also becomes the group's accessible name.
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
titlestring | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined
data-testidstring | undefined

ChatTrigger

PropTypeDefaultDescription
labelstring | undefinedAsk WallyTooltip text and accessible name.
titlestring | undefined
defaultCheckedboolean | undefined
defaultValuestring | number | readonly string[] | undefined
autoFocusboolean | undefined
idstring | undefined
tabIndexnumber | undefined
relstring | undefined
onChangeChangeEventHandler<T, Element> | undefined
type"button" | "submit" | "reset" | undefined
disabledboolean | undefined
namestring | undefined
valuestring | number | readonly string[] | undefined
data-testidstring | undefined

Explorer