> 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.

# 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 `Button`s and vertical `Separator`s, 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](https://github.com/wallarm/design-system/tree/main/packages/design-system/src/components/Chat) · [Storybook](https://wallarm.github.io/design-system/storybook/?path=/docs/ai-chat--overview)

```tsx
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';

export const HeaderDefault = () => (
  <div className='h-200 w-480'>
    <Chat data-testid='chat' background='none'>
      <ChatHeader>
        <ChatHeaderTitle />
        <ChatHeaderActions>
          <Button variant='ghost' color='neutral' size='small' aria-label='Chat history'>
            <History />
          </Button>
          <DropdownMenu positioning={{ placement: 'bottom-end' }}>
            <DropdownMenuTrigger asChild>
              <Button variant='ghost' color='neutral' size='small' aria-label='More actions'>
                <Ellipsis />
              </Button>
            </DropdownMenuTrigger>
            <DropdownMenuContent>
              <DropdownMenuItem>Rename chat</DropdownMenuItem>
              <DropdownMenuItem>Delete chat</DropdownMenuItem>
            </DropdownMenuContent>
          </DropdownMenu>
          <Separator orientation='vertical' />
          <Button variant='ghost' color='neutral' size='small' aria-label='Close chat'>
            <X />
          </Button>
        </ChatHeaderActions>
      </ChatHeader>
      <ChatBody />
    </Chat>
  </div>
);
```

## Usage

```tsx
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.

```tsx
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, Plus, X } from '@wallarm-org/design-system/icons';
import { Select, SelectButton, SelectContent, SelectOption, SelectOptionIndicator, SelectOptionText, SelectPositioner } from '@wallarm-org/design-system/Select';
import { Separator } from '@wallarm-org/design-system/Separator';

export const HeaderWithThreadSelect = () => (
  <div className='h-200 w-480'>
    <Chat data-testid='chat' background='none'>
      <ChatHeader>
        <ChatHeaderTitle>
          <Select collection={threads} defaultValue={['blocked']}>
            <SelectButton variant='ghost' size='small' placeholder='New chat' />
            <SelectPositioner>
              <SelectContent>
                {threads.items.map(item => (
                  <SelectOption key={item.value} item={item}>
                    <SelectOptionText>{item.label}</SelectOptionText>
                    <SelectOptionIndicator />
                  </SelectOption>
                ))}
              </SelectContent>
            </SelectPositioner>
          </Select>
        </ChatHeaderTitle>
        <ChatHeaderActions>
          <Button variant='ghost' color='neutral' size='small' aria-label='New chat'>
            <Plus />
          </Button>
          <Separator orientation='vertical' />
          <Button variant='ghost' color='neutral' size='small' aria-label='Chat history'>
            <History />
          </Button>
          <DropdownMenu positioning={{ placement: 'bottom-end' }}>
            <DropdownMenuTrigger asChild>
              <Button variant='ghost' color='neutral' size='small' aria-label='More actions'>
                <Ellipsis />
              </Button>
            </DropdownMenuTrigger>
            <DropdownMenuContent>
              <DropdownMenuItem>Rename chat</DropdownMenuItem>
              <DropdownMenuItem>Delete chat</DropdownMenuItem>
            </DropdownMenuContent>
          </DropdownMenu>
          <Separator orientation='vertical' />
          <Button variant='ghost' color='neutral' size='small' aria-label='Close chat'>
            <X />
          </Button>
        </ChatHeaderActions>
      </ChatHeader>
      <ChatBody />
    </Chat>
  </div>
);
```

### Greeting

The empty state (Figma 44:1464): the circle mark and a heading, with Large suggestion pills
centered under it, over the `strong` background.

```tsx
import { type MouseEvent, useState } from 'react';
import { Button } from '@wallarm-org/design-system/Button';
import { Chat, ChatBody, ChatGreeting, ChatHeader, ChatHeaderActions, ChatHeaderTitle, ChatSuggestion, ChatSuggestions } 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';

export const Greeting = () => {
  const [picked, setPicked] = useState<string>();
  const handleSuggestionClick = (event: MouseEvent<HTMLButtonElement>) =>
    setPicked(event.currentTarget.value);

  return (
    <div className='h-640 w-480'>
      <Chat data-testid='chat' background='strong'>
        <ChatHeader>
          <ChatHeaderTitle />
          <ChatHeaderActions>
            <Button variant='ghost' color='neutral' size='small' aria-label='Chat history'>
              <History />
            </Button>
            <DropdownMenu positioning={{ placement: 'bottom-end' }}>
              <DropdownMenuTrigger asChild>
                <Button variant='ghost' color='neutral' size='small' aria-label='More actions'>
                  <Ellipsis />
                </Button>
              </DropdownMenuTrigger>
              <DropdownMenuContent>
                <DropdownMenuItem>Rename chat</DropdownMenuItem>
                <DropdownMenuItem>Delete chat</DropdownMenuItem>
              </DropdownMenuContent>
            </DropdownMenu>
            <Separator orientation='vertical' />
            <Button variant='ghost' color='neutral' size='small' aria-label='Close chat'>
              <X />
            </Button>
          </ChatHeaderActions>
        </ChatHeader>
        <ChatBody>
          <ChatGreeting title='How can I help you today?'>
            <ChatSuggestions placement='greeting' label='Suggestions'>
              {SUGGESTIONS.map((text, index) => (
                <ChatSuggestion
                  key={text}
                  data-testid={`chat--suggestion-${index}`}
                  value={text}
                  onClick={handleSuggestionClick}
                >
                  {text}
                </ChatSuggestion>
              ))}
            </ChatSuggestions>
          </ChatGreeting>
          {picked && (
            <p data-testid='chat--picked' className='sr-only'>
              Picked: {picked}
            </p>
          )}
        </ChatBody>
      </Chat>
    </div>
  );
};
```

### 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.

```tsx
import { Button } from '@wallarm-org/design-system/Button';
import { Chat, ChatBody, ChatFooter, ChatGreeting, ChatHeader, ChatHeaderActions, ChatHeaderTitle, ChatSuggestion, ChatSuggestions } 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';
import { HStack } from '@wallarm-org/design-system/Stack';

export const Suggestions = () => (
  <HStack gap={24} align='start'>
    <div className='h-640 w-480'>
      <Chat data-testid='chat-footer-suggestions'>
        <ChatHeader>
          <ChatHeaderTitle />
          <ChatHeaderActions>
            <Button variant='ghost' color='neutral' size='small' aria-label='Chat history'>
              <History />
            </Button>
            <DropdownMenu positioning={{ placement: 'bottom-end' }}>
              <DropdownMenuTrigger asChild>
                <Button variant='ghost' color='neutral' size='small' aria-label='More actions'>
                  <Ellipsis />
                </Button>
              </DropdownMenuTrigger>
              <DropdownMenuContent>
                <DropdownMenuItem>Rename chat</DropdownMenuItem>
                <DropdownMenuItem>Delete chat</DropdownMenuItem>
              </DropdownMenuContent>
            </DropdownMenu>
            <Separator orientation='vertical' />
            <Button variant='ghost' color='neutral' size='small' aria-label='Close chat'>
              <X />
            </Button>
          </ChatHeaderActions>
        </ChatHeader>
        <ChatBody />
        <ChatFooter>
          <ChatSuggestions label='Suggestions'>
            {SUGGESTIONS.map((text, index) => (
              <ChatSuggestion
                key={text}
                data-testid={`chat-footer-suggestions--suggestion-${index}`}
              >
                {text}
              </ChatSuggestion>
            ))}
          </ChatSuggestions>
        </ChatFooter>
      </Chat>
    </div>
    <div className='h-640 w-480'>
      <Chat data-testid='chat-greeting-suggestions' background='strong'>
        <ChatHeader>
          <ChatHeaderTitle />
          <ChatHeaderActions>
            <Button variant='ghost' color='neutral' size='small' aria-label='Chat history'>
              <History />
            </Button>
            <DropdownMenu positioning={{ placement: 'bottom-end' }}>
              <DropdownMenuTrigger asChild>
                <Button variant='ghost' color='neutral' size='small' aria-label='More actions'>
                  <Ellipsis />
                </Button>
              </DropdownMenuTrigger>
              <DropdownMenuContent>
                <DropdownMenuItem>Rename chat</DropdownMenuItem>
                <DropdownMenuItem>Delete chat</DropdownMenuItem>
              </DropdownMenuContent>
            </DropdownMenu>
            <Separator orientation='vertical' />
            <Button variant='ghost' color='neutral' size='small' aria-label='Close chat'>
              <X />
            </Button>
          </ChatHeaderActions>
        </ChatHeader>
        <ChatBody>
          <ChatGreeting title='How can I help you today?'>
            <ChatSuggestions placement='greeting'>
              {SUGGESTIONS.map((text, index) => (
                <ChatSuggestion
                  key={text}
                  data-testid={`chat-greeting-suggestions--suggestion-${index}`}
                >
                  {text}
                </ChatSuggestion>
              ))}
            </ChatSuggestions>
          </ChatGreeting>
        </ChatBody>
      </Chat>
    </div>
  </HStack>
);
```

### 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.

```tsx
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';
import { HStack } from '@wallarm-org/design-system/Stack';

export const Backgrounds = () => (
  <HStack gap={24} align='start'>
    {BACKGROUNDS.map(background => (
      <div key={background} className='h-640 w-360'>
        <Chat data-testid={`chat-${background}`} background={background}>
          <ChatHeader>
            <ChatHeaderTitle />
            <ChatHeaderActions>
              <Button variant='ghost' color='neutral' size='small' aria-label='Chat history'>
                <History />
              </Button>
              <DropdownMenu positioning={{ placement: 'bottom-end' }}>
                <DropdownMenuTrigger asChild>
                  <Button variant='ghost' color='neutral' size='small' aria-label='More actions'>
                    <Ellipsis />
                  </Button>
                </DropdownMenuTrigger>
                <DropdownMenuContent>
                  <DropdownMenuItem>Rename chat</DropdownMenuItem>
                  <DropdownMenuItem>Delete chat</DropdownMenuItem>
                </DropdownMenuContent>
              </DropdownMenu>
              <Separator orientation='vertical' />
              <Button variant='ghost' color='neutral' size='small' aria-label='Close chat'>
                <X />
              </Button>
            </ChatHeaderActions>
          </ChatHeader>
          <ChatBody />
        </Chat>
      </div>
    ))}
  </HStack>
);
```

### Analytics

Analytics attributes go on the interactive parts only: `data-analytics-id` on a `ChatSuggestion`
lands on its `<button>`; header actions are plain DS `Button`s and carry their own. Keep them off
the `Chat` root — a click anywhere inside would resolve to it.

```tsx
import { Button } from '@wallarm-org/design-system/Button';
import { Chat, ChatBody, ChatFooter, ChatHeader, ChatHeaderActions, ChatHeaderTitle, ChatSuggestion, ChatSuggestions } from '@wallarm-org/design-system/Chat';
import { X } from '@wallarm-org/design-system/icons';

export const Analytics = () => (
  <div className='h-640 w-480'>
    <Chat data-testid='chat'>
      <ChatHeader>
        <ChatHeaderTitle />
        <ChatHeaderActions>
          <Button
            variant='ghost'
            color='neutral'
            size='small'
            aria-label='Close chat'
            data-analytics-id='AI_CHAT_CLOSE'
          >
            <X />
          </Button>
        </ChatHeaderActions>
      </ChatHeader>
      <ChatBody />
      <ChatFooter>
        <ChatSuggestions label='Suggestions'>
          {SUGGESTIONS.map((text, index) => (
            <ChatSuggestion
              key={text}
              data-testid={`chat--suggestion-${index}`}
              data-analytics-id='AI_CHAT_SUGGESTION'
              data-analytics-props={JSON.stringify({ index })}
            >
              {text}
            </ChatSuggestion>
          ))}
        </ChatSuggestions>
      </ChatFooter>
    </Chat>
  </div>
);
```

### 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`).

```tsx
import { ChatTrigger } from '@wallarm-org/design-system/Chat';

export const Trigger = () => <ChatTrigger data-testid='chat-trigger' />;
```

### 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.

```tsx
import { Button } from '@wallarm-org/design-system/Button';
import { Chat, ChatBody, ChatHeader, ChatHeaderActions, ChatHeaderTitle, ChatTrigger } from '@wallarm-org/design-system/Chat';
import { Drawer, DrawerContent, DrawerTrigger } from '@wallarm-org/design-system/Drawer';
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';

export const TriggerWithDrawer = () => (
  <Drawer width={480}>
    <DrawerTrigger asChild>
      <ChatTrigger data-testid='chat-trigger' data-analytics-id='AI_CHAT_OPEN' />
    </DrawerTrigger>
    <DrawerContent>
      <Chat data-testid='chat'>
        <ChatHeader>
          <ChatHeaderTitle />
          <ChatHeaderActions>
            <Button variant='ghost' color='neutral' size='small' aria-label='Chat history'>
              <History />
            </Button>
            <DropdownMenu positioning={{ placement: 'bottom-end' }}>
              <DropdownMenuTrigger asChild>
                <Button variant='ghost' color='neutral' size='small' aria-label='More actions'>
                  <Ellipsis />
                </Button>
              </DropdownMenuTrigger>
              <DropdownMenuContent>
                <DropdownMenuItem>Rename chat</DropdownMenuItem>
                <DropdownMenuItem>Delete chat</DropdownMenuItem>
              </DropdownMenuContent>
            </DropdownMenu>
            <Separator orientation='vertical' />
            <Button variant='ghost' color='neutral' size='small' aria-label='Close chat'>
              <X />
            </Button>
          </ChatHeaderActions>
        </ChatHeader>
        <ChatBody />
      </Chat>
    </DrawerContent>
  </Drawer>
);
```

### 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.

```tsx
import { useState } from 'react';
import { Button } from '@wallarm-org/design-system/Button';
import { Chat, ChatBody, ChatFooter, ChatGreeting, ChatHeader, ChatHeaderActions, ChatHeaderTitle, ChatSuggestion, ChatSuggestions } from '@wallarm-org/design-system/Chat';
import { ChatInput, ChatInputSubmit, ChatInputTextarea } from '@wallarm-org/design-system/ChatInput';
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';

export const EmptyPanel = () => {
  const [value, setValue] = useState('');
  const handleSubmit = () => setValue('');

  return (
    <div className='h-640 w-480'>
      <Chat data-testid='chat' background='strong'>
        <ChatHeader>
          <ChatHeaderTitle />
          <ChatHeaderActions>
            <Button variant='ghost' color='neutral' size='small' aria-label='Chat history'>
              <History />
            </Button>
            <DropdownMenu positioning={{ placement: 'bottom-end' }}>
              <DropdownMenuTrigger asChild>
                <Button variant='ghost' color='neutral' size='small' aria-label='More actions'>
                  <Ellipsis />
                </Button>
              </DropdownMenuTrigger>
              <DropdownMenuContent>
                <DropdownMenuItem>Rename chat</DropdownMenuItem>
                <DropdownMenuItem>Delete chat</DropdownMenuItem>
              </DropdownMenuContent>
            </DropdownMenu>
            <Separator orientation='vertical' />
            <Button variant='ghost' color='neutral' size='small' aria-label='Close chat'>
              <X />
            </Button>
          </ChatHeaderActions>
        </ChatHeader>
        <ChatBody>
          <ChatGreeting title='How can I help you today?'>
            <ChatSuggestions placement='greeting' label='Suggestions'>
              {SUGGESTIONS.map((text, index) => (
                <ChatSuggestion key={text} data-testid={`chat--suggestion-${index}`}>
                  {text}
                </ChatSuggestion>
              ))}
            </ChatSuggestions>
          </ChatGreeting>
        </ChatBody>
        <ChatFooter>
          <ChatInput value={value} onValueChange={setValue} onSubmit={handleSubmit}>
            <ChatInputTextarea />
            <ChatInputSubmit />
          </ChatInput>
        </ChatFooter>
      </Chat>
    </div>
  );
};
```

### 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.

```tsx
import { useState } from 'react';
import { AssistantMessage, AssistantMessageContent } from '@wallarm-org/design-system/AssistantMessage';
import { Button } from '@wallarm-org/design-system/Button';
import { ChainOfThought, ChainOfThoughtStep } from '@wallarm-org/design-system/ChainOfThought';
import { Chat, ChatBody, ChatFooter, ChatHeader, ChatHeaderActions, ChatHeaderTitle, ChatSuggestion, ChatSuggestions } from '@wallarm-org/design-system/Chat';
import { ChatInput, ChatInputSubmit, ChatInputTextarea } from '@wallarm-org/design-system/ChatInput';
import { InlineCodeSnippet } from '@wallarm-org/design-system/CodeSnippet';
import { Copyable, CopyableIcon } from '@wallarm-org/design-system/Copyable';
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@wallarm-org/design-system/DropdownMenu';
import { Brain, Database, Ellipsis, History, Search, ThumbsDown, ThumbsUp, X } from '@wallarm-org/design-system/icons';
import { MessageAction, MessageActions, MessageTimestamp } from '@wallarm-org/design-system/MessageActions';
import { Separator } from '@wallarm-org/design-system/Separator';
import { UserMessage, UserMessageBubble } from '@wallarm-org/design-system/UserMessage';

export const Conversation = () => {
  const [value, setValue] = useState('');
  const handleSubmit = () => setValue('');

  return (
    <div className='h-640 w-480'>
      <Chat data-testid='chat'>
        <ChatHeader>
          <ChatHeaderTitle />
          <ChatHeaderActions>
            <Button variant='ghost' color='neutral' size='small' aria-label='Chat history'>
              <History />
            </Button>
            <DropdownMenu positioning={{ placement: 'bottom-end' }}>
              <DropdownMenuTrigger asChild>
                <Button variant='ghost' color='neutral' size='small' aria-label='More actions'>
                  <Ellipsis />
                </Button>
              </DropdownMenuTrigger>
              <DropdownMenuContent>
                <DropdownMenuItem>Rename chat</DropdownMenuItem>
                <DropdownMenuItem>Delete chat</DropdownMenuItem>
              </DropdownMenuContent>
            </DropdownMenu>
            <Separator orientation='vertical' />
            <Button variant='ghost' color='neutral' size='small' aria-label='Close chat'>
              <X />
            </Button>
          </ChatHeaderActions>
        </ChatHeader>
        <ChatBody>
          <UserMessage data-testid='chat--user-message-0'>
            <UserMessageBubble>{QUESTION}</UserMessageBubble>
            <MessageActions>
              <MessageTimestamp dateTime='2026-10-21T09:41:00Z'>2m ago</MessageTimestamp>
              <Copyable text={QUESTION}>
                <MessageAction aria-label='Copy'>
                  <CopyableIcon />
                </MessageAction>
              </Copyable>
            </MessageActions>
          </UserMessage>
          <AssistantMessage data-testid='chat--assistant-message-0'>
            <ChainOfThought>
              <ChainOfThoughtStep icon={<Brain />} label='Thought for 5s'>
                <p>
                  Look up blocked requests to /api/login for last night, then group them by source.
                </p>
              </ChainOfThoughtStep>
              <ChainOfThoughtStep icon={<Search />} label='Searched for blocked requests' />
              <ChainOfThoughtStep
                icon={<Database />}
                label='Queried attack events'
                metric='1,204'
              />
            </ChainOfThought>
            <AssistantMessageContent>
              <h3>SQL injection on the login endpoint</h3>
              <p>
                Wallarm blocked 1,204 SQL injection attempts, almost all against{' '}
                <InlineCodeSnippet code='/api/login' size='sm' />.
              </p>
              <ul>
                <li>
                  Most came from <InlineCodeSnippet code='203.0.113.0/24' size='sm' />.
                </li>
                <li>The peak was at 03:00 UTC.</li>
                <li>No request reached the application.</li>
              </ul>
            </AssistantMessageContent>
            <MessageActions visible>
              <Copyable text={ANSWER_TEXT}>
                <MessageAction aria-label='Copy' data-testid='chat--answer-copy'>
                  <CopyableIcon />
                </MessageAction>
              </Copyable>
              <MessageAction aria-label='Good response'>
                <ThumbsUp />
              </MessageAction>
              <MessageAction aria-label='Bad response'>
                <ThumbsDown />
              </MessageAction>
              <MessageTimestamp dateTime='2026-10-21T09:42:00Z'>1m ago</MessageTimestamp>
            </MessageActions>
          </AssistantMessage>
        </ChatBody>
        <ChatFooter>
          <ChatSuggestions label='Suggestions'>
            {FOLLOW_UPS.map((text, index) => (
              <ChatSuggestion key={text} data-testid={`chat--suggestion-${index}`}>
                {text}
              </ChatSuggestion>
            ))}
          </ChatSuggestions>
          <ChatInput value={value} onValueChange={setValue} onSubmit={handleSubmit}>
            <ChatInputTextarea />
            <ChatInputSubmit />
          </ChatInput>
        </ChatFooter>
      </Chat>
    </div>
  );
};
```

### 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.

```tsx
import { useState } from 'react';
import { AssistantMessage, AssistantMessageContent } from '@wallarm-org/design-system/AssistantMessage';
import { Button } from '@wallarm-org/design-system/Button';
import { ChainOfThought, ChainOfThoughtStep } from '@wallarm-org/design-system/ChainOfThought';
import { Chat, ChatBody, ChatFooter, ChatHeader, ChatHeaderActions, ChatHeaderTitle } from '@wallarm-org/design-system/Chat';
import { ChatInput, ChatInputSubmit, ChatInputTextarea } from '@wallarm-org/design-system/ChatInput';
import { Copyable, CopyableIcon } from '@wallarm-org/design-system/Copyable';
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@wallarm-org/design-system/DropdownMenu';
import { Database, Ellipsis, History, Search, X } from '@wallarm-org/design-system/icons';
import { MessageAction, MessageActions, MessageTimestamp } from '@wallarm-org/design-system/MessageActions';
import { Separator } from '@wallarm-org/design-system/Separator';
import { UserMessage, UserMessageBubble } from '@wallarm-org/design-system/UserMessage';

export const Streaming = () => {
  const [value, setValue] = useState('');
  const [isRunning, setIsRunning] = useState(true);
  const handleSubmit = () => setValue('');
  const handleStop = () => setIsRunning(false);

  return (
    <div className='h-640 w-480'>
      <Chat data-testid='chat'>
        <ChatHeader>
          <ChatHeaderTitle />
          <ChatHeaderActions>
            <Button variant='ghost' color='neutral' size='small' aria-label='Chat history'>
              <History />
            </Button>
            <DropdownMenu positioning={{ placement: 'bottom-end' }}>
              <DropdownMenuTrigger asChild>
                <Button variant='ghost' color='neutral' size='small' aria-label='More actions'>
                  <Ellipsis />
                </Button>
              </DropdownMenuTrigger>
              <DropdownMenuContent>
                <DropdownMenuItem>Rename chat</DropdownMenuItem>
                <DropdownMenuItem>Delete chat</DropdownMenuItem>
              </DropdownMenuContent>
            </DropdownMenu>
            <Separator orientation='vertical' />
            <Button variant='ghost' color='neutral' size='small' aria-label='Close chat'>
              <X />
            </Button>
          </ChatHeaderActions>
        </ChatHeader>
        <ChatBody aria-busy={isRunning}>
          <UserMessage data-testid='chat--user-message-0'>
            <UserMessageBubble>{QUESTION}</UserMessageBubble>
            <MessageActions>
              <MessageTimestamp dateTime='2026-10-21T09:41:00Z'>2m ago</MessageTimestamp>
              <Copyable text={QUESTION}>
                <MessageAction aria-label='Copy'>
                  <CopyableIcon />
                </MessageAction>
              </Copyable>
            </MessageActions>
          </UserMessage>
          <AssistantMessage data-testid='chat--assistant-message-0' aria-busy={isRunning}>
            <ChainOfThought>
              <ChainOfThoughtStep icon={<Search />} label='Searched for blocked requests' />
              <ChainOfThoughtStep
                icon={<Database />}
                label={isRunning ? 'Querying attack events...' : 'Stopped'}
                status={isRunning ? 'running' : 'done'}
              />
            </ChainOfThought>
            <AssistantMessageContent>
              <p>Wallarm blocked 1,204 SQL injection attempts, almost all against</p>
            </AssistantMessageContent>
          </AssistantMessage>
        </ChatBody>
        <ChatFooter>
          <ChatInput
            value={value}
            onValueChange={setValue}
            onSubmit={handleSubmit}
            isRunning={isRunning}
            onStop={handleStop}
          >
            <ChatInputTextarea />
            <ChatInputSubmit />
          </ChatInput>
        </ChatFooter>
      </Chat>
    </div>
  );
};
```

### 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.

```tsx
import { useState } from 'react';
import { ApprovalCard, ApprovalCardActions, ApprovalCardContent, type ApprovalCardStatus } from '@wallarm-org/design-system/ApprovalCard';
import { AssistantMessage, AssistantMessageContent } from '@wallarm-org/design-system/AssistantMessage';
import { Button } from '@wallarm-org/design-system/Button';
import { ChainOfThought, ChainOfThoughtStep } from '@wallarm-org/design-system/ChainOfThought';
import { Chat, ChatBody, ChatFooter, ChatHeader, ChatHeaderActions, ChatHeaderTitle } from '@wallarm-org/design-system/Chat';
import { ChatInput, ChatInputSubmit, ChatInputTextarea } from '@wallarm-org/design-system/ChatInput';
import { InlineCodeSnippet } from '@wallarm-org/design-system/CodeSnippet';
import { Copyable, CopyableIcon } from '@wallarm-org/design-system/Copyable';
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@wallarm-org/design-system/DropdownMenu';
import { Ellipsis, History, Search, ShieldBan, X } from '@wallarm-org/design-system/icons';
import { MessageAction, MessageActions, MessageTimestamp } from '@wallarm-org/design-system/MessageActions';
import { Separator } from '@wallarm-org/design-system/Separator';
import { UserMessage, UserMessageBubble } from '@wallarm-org/design-system/UserMessage';

export const ApprovalDocked = () => {
  const [value, setValue] = useState('');
  const [status, setStatus] = useState<ApprovalCardStatus>('pending');
  const pending = status === 'pending';
  const handleSubmit = () => setValue('');
  const handleApprove = () => setStatus('approved');
  const handleReject = () => setStatus('rejected');

  return (
    <div className='h-640 w-480'>
      <Chat data-testid='chat'>
        <ChatHeader>
          <ChatHeaderTitle />
          <ChatHeaderActions>
            <Button variant='ghost' color='neutral' size='small' aria-label='Chat history'>
              <History />
            </Button>
            <DropdownMenu positioning={{ placement: 'bottom-end' }}>
              <DropdownMenuTrigger asChild>
                <Button variant='ghost' color='neutral' size='small' aria-label='More actions'>
                  <Ellipsis />
                </Button>
              </DropdownMenuTrigger>
              <DropdownMenuContent>
                <DropdownMenuItem>Rename chat</DropdownMenuItem>
                <DropdownMenuItem>Delete chat</DropdownMenuItem>
              </DropdownMenuContent>
            </DropdownMenu>
            <Separator orientation='vertical' />
            <Button variant='ghost' color='neutral' size='small' aria-label='Close chat'>
              <X />
            </Button>
          </ChatHeaderActions>
        </ChatHeader>
        <ChatBody aria-busy={pending}>
          <UserMessage data-testid='chat--user-message-0'>
            <UserMessageBubble>{QUESTION}</UserMessageBubble>
            <MessageActions>
              <MessageTimestamp dateTime='2026-10-21T09:41:00Z'>2m ago</MessageTimestamp>
              <Copyable text={QUESTION}>
                <MessageAction aria-label='Copy'>
                  <CopyableIcon />
                </MessageAction>
              </Copyable>
            </MessageActions>
          </UserMessage>
          <AssistantMessage data-testid='chat--assistant-message-0'>
            <ChainOfThought>
              <ChainOfThoughtStep icon={<Search />} label='Searched for blocked requests' />
              <ChainOfThoughtStep
                icon={<ShieldBan />}
                label='Proposed a denylist entry'
                status={pending ? 'running' : 'done'}
              />
            </ChainOfThought>
            {!pending && (
              <AssistantMessageContent>
                <p>
                  {status === 'approved'
                    ? 'Done. 203.0.113.0/24 is now denied on all applications.'
                    : 'Okay, I left the denylist unchanged.'}
                </p>
              </AssistantMessageContent>
            )}
          </AssistantMessage>
        </ChatBody>
        <ChatFooter>
          <ApprovalCard status={status}>
            <ApprovalCardContent>
              <p>
                Add <InlineCodeSnippet code='203.0.113.0/24' size='sm' /> to the denylist on all
                applications
              </p>
            </ApprovalCardContent>
            <ApprovalCardActions>
              <Button data-testid='chat--approve' onClick={handleApprove}>
                Allow
              </Button>
              <Button
                variant='secondary'
                color='neutral'
                data-testid='chat--reject'
                onClick={handleReject}
              >
                Reject
              </Button>
            </ApprovalCardActions>
          </ApprovalCard>
          <ChatInput
            value={value}
            onValueChange={setValue}
            onSubmit={handleSubmit}
            isRunning={pending}
          >
            <ChatInputTextarea />
            <ChatInputSubmit />
          </ChatInput>
        </ChatFooter>
      </Chat>
    </div>
  );
};
```

### Approval resolved

After the decision the docked card collapses to a one-line status and the answer completes.

```tsx
import { useState } from 'react';
import { ApprovalCard } from '@wallarm-org/design-system/ApprovalCard';
import { AssistantMessage, AssistantMessageContent } from '@wallarm-org/design-system/AssistantMessage';
import { Button } from '@wallarm-org/design-system/Button';
import { ChainOfThought, ChainOfThoughtStep } from '@wallarm-org/design-system/ChainOfThought';
import { Chat, ChatBody, ChatFooter, ChatHeader, ChatHeaderActions, ChatHeaderTitle } from '@wallarm-org/design-system/Chat';
import { ChatInput, ChatInputSubmit, ChatInputTextarea } from '@wallarm-org/design-system/ChatInput';
import { Copyable, CopyableIcon } from '@wallarm-org/design-system/Copyable';
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@wallarm-org/design-system/DropdownMenu';
import { Ellipsis, History, Search, ShieldBan, X } from '@wallarm-org/design-system/icons';
import { MessageAction, MessageActions, MessageTimestamp } from '@wallarm-org/design-system/MessageActions';
import { Separator } from '@wallarm-org/design-system/Separator';
import { UserMessage, UserMessageBubble } from '@wallarm-org/design-system/UserMessage';

export const ApprovalResolved = () => {
  const [value, setValue] = useState('');
  const handleSubmit = () => setValue('');

  return (
    <div className='h-640 w-480'>
      <Chat data-testid='chat'>
        <ChatHeader>
          <ChatHeaderTitle />
          <ChatHeaderActions>
            <Button variant='ghost' color='neutral' size='small' aria-label='Chat history'>
              <History />
            </Button>
            <DropdownMenu positioning={{ placement: 'bottom-end' }}>
              <DropdownMenuTrigger asChild>
                <Button variant='ghost' color='neutral' size='small' aria-label='More actions'>
                  <Ellipsis />
                </Button>
              </DropdownMenuTrigger>
              <DropdownMenuContent>
                <DropdownMenuItem>Rename chat</DropdownMenuItem>
                <DropdownMenuItem>Delete chat</DropdownMenuItem>
              </DropdownMenuContent>
            </DropdownMenu>
            <Separator orientation='vertical' />
            <Button variant='ghost' color='neutral' size='small' aria-label='Close chat'>
              <X />
            </Button>
          </ChatHeaderActions>
        </ChatHeader>
        <ChatBody>
          <UserMessage data-testid='chat--user-message-0'>
            <UserMessageBubble>{QUESTION}</UserMessageBubble>
            <MessageActions>
              <MessageTimestamp dateTime='2026-10-21T09:41:00Z'>2m ago</MessageTimestamp>
              <Copyable text={QUESTION}>
                <MessageAction aria-label='Copy'>
                  <CopyableIcon />
                </MessageAction>
              </Copyable>
            </MessageActions>
          </UserMessage>
          <AssistantMessage data-testid='chat--assistant-message-0'>
            <ChainOfThought>
              <ChainOfThoughtStep icon={<Search />} label='Searched for blocked requests' />
              <ChainOfThoughtStep icon={<ShieldBan />} label='Proposed a denylist entry' />
            </ChainOfThought>
            <AssistantMessageContent>
              <p>Done. 203.0.113.0/24 is now denied on all applications.</p>
            </AssistantMessageContent>
          </AssistantMessage>
        </ChatBody>
        <ChatFooter>
          {/* Content and actions render only while pending; a resolved card shows just its status row. */}
          <ApprovalCard status='approved' />
          <ChatInput value={value} onValueChange={setValue} onSubmit={handleSubmit}>
            <ChatInputTextarea />
            <ChatInputSubmit />
          </ChatInput>
        </ChatFooter>
      </Chat>
    </div>
  );
};
```

### Permissions

The per-conversation tool permissions sit inside the composer, between textarea and submit.

```tsx
import { useState } from 'react';
import { Button } from '@wallarm-org/design-system/Button';
import { Chat, ChatBody, ChatFooter, ChatGreeting, ChatHeader, ChatHeaderActions, ChatHeaderTitle } from '@wallarm-org/design-system/Chat';
import { ChatInput, ChatInputSubmit, ChatInputTextarea } from '@wallarm-org/design-system/ChatInput';
import { ChatPermissions, ChatPermissionsContent, ChatPermissionsItem, type ChatPermissionsItemCheckedChangeDetails, ChatPermissionsTrigger } from '@wallarm-org/design-system/ChatPermissions';
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';

export const Permissions = () => {
  const [value, setValue] = useState('');
  const [allowed, setAllowed] = useState<Record<string, boolean>>({
    search_attacks: true,
    get_api_inventory: true,
    propose_add_to_denylist: false,
  });
  const handleSubmit = () => setValue('');
  const handlePermissionChange = ({ checked, name }: ChatPermissionsItemCheckedChangeDetails) =>
    setAllowed(prev => ({ ...prev, [name]: checked }));

  return (
    <div className='h-640 w-480'>
      <Chat data-testid='chat' background='strong'>
        <ChatHeader>
          <ChatHeaderTitle />
          <ChatHeaderActions>
            <Button variant='ghost' color='neutral' size='small' aria-label='Chat history'>
              <History />
            </Button>
            <DropdownMenu positioning={{ placement: 'bottom-end' }}>
              <DropdownMenuTrigger asChild>
                <Button variant='ghost' color='neutral' size='small' aria-label='More actions'>
                  <Ellipsis />
                </Button>
              </DropdownMenuTrigger>
              <DropdownMenuContent>
                <DropdownMenuItem>Rename chat</DropdownMenuItem>
                <DropdownMenuItem>Delete chat</DropdownMenuItem>
              </DropdownMenuContent>
            </DropdownMenu>
            <Separator orientation='vertical' />
            <Button variant='ghost' color='neutral' size='small' aria-label='Close chat'>
              <X />
            </Button>
          </ChatHeaderActions>
        </ChatHeader>
        <ChatBody>
          <ChatGreeting title='How can I help you today?' />
        </ChatBody>
        <ChatFooter>
          <ChatInput value={value} onValueChange={setValue} onSubmit={handleSubmit}>
            <ChatInputTextarea />
            <ChatPermissions>
              <ChatPermissionsTrigger />
              <ChatPermissionsContent>
                {TOOLS.map(tool => (
                  <ChatPermissionsItem
                    key={tool.name}
                    name={tool.name}
                    data-testid={`chat--permission-${tool.name}`}
                    title={tool.name}
                    description={tool.description}
                    checked={allowed[tool.name]}
                    onCheckedChange={handlePermissionChange}
                  />
                ))}
              </ChatPermissionsContent>
            </ChatPermissions>
            <ChatInputSubmit />
          </ChatInput>
        </ChatFooter>
      </Chat>
    </div>
  );
};
```

### 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`.

```tsx
import { useState } from 'react';
import { AssistantMessage, AssistantMessageContent } from '@wallarm-org/design-system/AssistantMessage';
import { Button } from '@wallarm-org/design-system/Button';
import { ChainOfThought, ChainOfThoughtStep } from '@wallarm-org/design-system/ChainOfThought';
import { Chat, ChatBody, ChatFooter, ChatHeader, ChatHeaderActions, ChatHeaderTitle, ChatTrigger } from '@wallarm-org/design-system/Chat';
import { ChatInput, ChatInputSubmit, ChatInputTextarea } from '@wallarm-org/design-system/ChatInput';
import { InlineCodeSnippet } from '@wallarm-org/design-system/CodeSnippet';
import { Copyable, CopyableIcon } from '@wallarm-org/design-system/Copyable';
import { Drawer, DrawerClose, DrawerContent, DrawerTrigger } from '@wallarm-org/design-system/Drawer';
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@wallarm-org/design-system/DropdownMenu';
import { Brain, Database, Ellipsis, History, Search, ThumbsDown, ThumbsUp, X } from '@wallarm-org/design-system/icons';
import { MessageAction, MessageActions, MessageTimestamp } from '@wallarm-org/design-system/MessageActions';
import { Separator } from '@wallarm-org/design-system/Separator';
import { UserMessage, UserMessageBubble } from '@wallarm-org/design-system/UserMessage';

export const InDrawer = () => {
  const [value, setValue] = useState('');
  const [isRunning, setIsRunning] = useState(true);
  const handleSubmit = () => setValue('');
  const handleStop = () => setIsRunning(false);

  return (
    <Drawer width={480}>
      <DrawerTrigger asChild>
        <ChatTrigger data-testid='chat-trigger' />
      </DrawerTrigger>
      <DrawerContent>
        <Chat data-testid='chat'>
          <ChatHeader>
            <ChatHeaderTitle />
            <ChatHeaderActions>
              <Button variant='ghost' color='neutral' size='small' aria-label='Chat history'>
                <History />
              </Button>
              <DropdownMenu positioning={{ placement: 'bottom-end' }}>
                <DropdownMenuTrigger asChild>
                  <Button variant='ghost' color='neutral' size='small' aria-label='More actions'>
                    <Ellipsis />
                  </Button>
                </DropdownMenuTrigger>
                <DropdownMenuContent>
                  <DropdownMenuItem>Rename chat</DropdownMenuItem>
                  <DropdownMenuItem>Delete chat</DropdownMenuItem>
                </DropdownMenuContent>
              </DropdownMenu>
              <Separator orientation='vertical' />
              <DrawerClose asChild>
                <Button variant='ghost' color='neutral' size='small' aria-label='Close chat'>
                  <X />
                </Button>
              </DrawerClose>
            </ChatHeaderActions>
          </ChatHeader>
          <ChatBody aria-busy={isRunning}>
            <UserMessage data-testid='chat--user-message-0'>
              <UserMessageBubble>{QUESTION}</UserMessageBubble>
              <MessageActions>
                <MessageTimestamp dateTime='2026-10-21T09:41:00Z'>2m ago</MessageTimestamp>
                <Copyable text={QUESTION}>
                  <MessageAction aria-label='Copy'>
                    <CopyableIcon />
                  </MessageAction>
                </Copyable>
              </MessageActions>
            </UserMessage>
            <AssistantMessage data-testid='chat--assistant-message-0' aria-busy={isRunning}>
              <ChainOfThought>
                <ChainOfThoughtStep icon={<Brain />} label='Thought for 5s'>
                  <p>
                    Look up blocked requests to /api/login for last night, then group them by
                    source.
                  </p>
                </ChainOfThoughtStep>
                <ChainOfThoughtStep icon={<Search />} label='Searched for blocked requests' />
                <ChainOfThoughtStep
                  icon={<Database />}
                  label='Queried attack events'
                  metric='1,204'
                />
              </ChainOfThought>
              <AssistantMessageContent>
                <h3>SQL injection on the login endpoint</h3>
                <p>
                  Wallarm blocked 1,204 SQL injection attempts, almost all against{' '}
                  <InlineCodeSnippet code='/api/login' size='sm' />.
                </p>
                <ul>
                  <li>
                    Most came from <InlineCodeSnippet code='203.0.113.0/24' size='sm' />.
                  </li>
                  <li>The peak was at 03:00 UTC.</li>
                  <li>No request reached the application.</li>
                </ul>
              </AssistantMessageContent>
              {!isRunning && (
                <MessageActions visible>
                  <Copyable text={ANSWER_TEXT}>
                    <MessageAction aria-label='Copy' data-testid='chat--answer-copy'>
                      <CopyableIcon />
                    </MessageAction>
                  </Copyable>
                  <MessageAction aria-label='Good response'>
                    <ThumbsUp />
                  </MessageAction>
                  <MessageAction aria-label='Bad response'>
                    <ThumbsDown />
                  </MessageAction>
                  <MessageTimestamp dateTime='2026-10-21T09:42:00Z'>1m ago</MessageTimestamp>
                </MessageActions>
              )}
            </AssistantMessage>
          </ChatBody>
          <ChatFooter>
            <ChatInput
              value={value}
              onValueChange={setValue}
              onSubmit={handleSubmit}
              isRunning={isRunning}
              onStop={handleStop}
            >
              <ChatInputTextarea />
              <ChatInputSubmit />
            </ChatInput>
          </ChatFooter>
        </Chat>
      </DrawerContent>
    </Drawer>
  );
};
```

## Props

| Prop           | Type                                                 | Default  | Description                                                                                                                                                                           |
| -------------- | ---------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| background     | `ChatBackground \| undefined`                        | `subtle` | Decorative 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. |
| defaultChecked | `boolean \| undefined`                               |          |                                                                                                                                                                                       |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |          |                                                                                                                                                                                       |
| autoFocus      | `boolean \| undefined`                               |          |                                                                                                                                                                                       |
| id             | `string \| undefined`                                |          |                                                                                                                                                                                       |
| tabIndex       | `number \| undefined`                                |          |                                                                                                                                                                                       |
| title          | `string \| undefined`                                |          |                                                                                                                                                                                       |
| rel            | `string \| undefined`                                |          |                                                                                                                                                                                       |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |          |                                                                                                                                                                                       |
| data-testid    | `string \| undefined`                                |          |                                                                                                                                                                                       |

### ChatBody

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |
| data-testid    | `string \| undefined`                                |         |             |

### ChatFooter

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |
| data-testid    | `string \| undefined`                                |         |             |

### ChatGreeting

| Prop           | Type                                                 | Default | Description                                                     |
| -------------- | ---------------------------------------------------- | ------- | --------------------------------------------------------------- |
| title \*       | `ReactNode`                                          |         | Heading under the Wally mark, e.g. "How can I help you today?". |
| defaultChecked | `boolean \| undefined`                               |         |                                                                 |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |                                                                 |
| autoFocus      | `boolean \| undefined`                               |         |                                                                 |
| id             | `string \| undefined`                                |         |                                                                 |
| tabIndex       | `number \| undefined`                                |         |                                                                 |
| rel            | `string \| undefined`                                |         |                                                                 |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |                                                                 |
| data-testid    | `string \| undefined`                                |         |                                                                 |

### ChatHeader

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |
| data-testid    | `string \| undefined`                                |         |             |

### ChatHeaderActions

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |
| data-testid    | `string \| undefined`                                |         |             |

### ChatHeaderTitle

| Prop           | Type                                                 | Default | Description                                                                            |
| -------------- | ---------------------------------------------------- | ------- | -------------------------------------------------------------------------------------- |
| label          | `ReactNode`                                          |         | The title shown when there are no children (e.g. a translation). Default: "Ask Wally". |
| defaultChecked | `boolean \| undefined`                               |         |                                                                                        |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |                                                                                        |
| autoFocus      | `boolean \| undefined`                               |         |                                                                                        |
| id             | `string \| undefined`                                |         |                                                                                        |
| tabIndex       | `number \| undefined`                                |         |                                                                                        |
| title          | `string \| undefined`                                |         |                                                                                        |
| rel            | `string \| undefined`                                |         |                                                                                        |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |                                                                                        |
| data-testid    | `string \| undefined`                                |         |                                                                                        |

### ChatSuggestion

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| disabled       | `boolean \| undefined`                               |         |             |
| name           | `string \| undefined`                                |         |             |
| type           | `"button" \| "submit" \| "reset" \| undefined`       |         |             |
| value          | `string \| number \| readonly string[] \| undefined` |         |             |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |
| data-testid    | `string \| undefined`                                |         |             |

### ChatSuggestions

| Prop           | Type                                                 | Default  | Description                                                                                                                                             |
| -------------- | ---------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| placement      | `ChatSuggestionsPlacement \| undefined`              | `footer` | `'footer'` (default, Figma 91:1167): right-aligned Medium pills above the input. `'greeting'` (Figma 44:1706): centered Large pills under the greeting. |
| label          | `ReactNode`                                          |          | Visible label (Figma "Suggestions"); also becomes the group's accessible name.                                                                          |
| defaultChecked | `boolean \| undefined`                               |          |                                                                                                                                                         |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |          |                                                                                                                                                         |
| autoFocus      | `boolean \| undefined`                               |          |                                                                                                                                                         |
| id             | `string \| undefined`                                |          |                                                                                                                                                         |
| tabIndex       | `number \| undefined`                                |          |                                                                                                                                                         |
| title          | `string \| undefined`                                |          |                                                                                                                                                         |
| rel            | `string \| undefined`                                |          |                                                                                                                                                         |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |          |                                                                                                                                                         |
| data-testid    | `string \| undefined`                                |          |                                                                                                                                                         |

### ChatTrigger

| Prop           | Type                                                 | Default     | Description                       |
| -------------- | ---------------------------------------------------- | ----------- | --------------------------------- |
| label          | `string \| undefined`                                | `Ask Wally` | Tooltip text and accessible name. |
| title          | `string \| undefined`                                |             |                                   |
| defaultChecked | `boolean \| undefined`                               |             |                                   |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |             |                                   |
| autoFocus      | `boolean \| undefined`                               |             |                                   |
| id             | `string \| undefined`                                |             |                                   |
| tabIndex       | `number \| undefined`                                |             |                                   |
| rel            | `string \| undefined`                                |             |                                   |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |             |                                   |
| type           | `"button" \| "submit" \| "reset" \| undefined`       |             |                                   |
| disabled       | `boolean \| undefined`                               |             |                                   |
| name           | `string \| undefined`                                |             |                                   |
| value          | `string \| number \| readonly string[] \| undefined` |             |                                   |
| data-testid    | `string \| undefined`                                |             |                                   |

## Explorer

