Message Typing
Three pulsing dots that fill the gap between sending a message and the reply arriving. Place it where the reply will appear, so the answer replaces the indicator in the same spot.
Usage
Render it as a normal transcript row while you are waiting, and drop the row once the reply lands.
import { MessageTyping } from "@e-infra/design-system"
{status === "streaming" && (
<MessageScrollerItem messageId="typing">
<Message align="start">
<MessageAvatar>
<Avatar>
<AvatarFallback>AI</AvatarFallback>
</Avatar>
</MessageAvatar>
<MessageContent>
<Bubble variant="muted">
<BubbleContent>
<MessageTyping />
</BubbleContent>
</Bubble>
</MessageContent>
</Message>
</MessageScrollerItem>
)}Because it is a normal row, it inherits the transcript's entrance animation and the autoscroll follows it — the same as any message.
Colour
The dots are painted with currentColor, so they take the colour of whatever bubble they sit in without configuration.
Labelling
The dots are decorative and hidden from assistive technology. A visually hidden label carries the meaning instead, so pick one that describes what is actually happening.
<MessageTyping label="Searching the knowledge base" />Pair it with busy on MessageScrollerContent, which sets aria-busy on the transcript so the log is announced as still being written.
<MessageScrollerContent busy={status === "streaming"}>Props
| Prop | Type | Default | Description |
|---|---|---|---|
| label | string | Generating response | Visually hidden description of the wait |
| className | string | - | Additional CSS classes |
| ...props | React.HTMLAttributes | - | Native span props |
Reduced motion
The pulse is suppressed under prefers-reduced-motion, leaving three static dots that still communicate the waiting state.
Related
Message Input drives the streaming status, and Message Scroller hosts the row.