Usage
Pass thecaret prop with either "block" or "circle":
chat.tsx
- The
caretprop is set to"block"or"circle" isAnimatingistrue
isAnimating becomes false), the caret disappears automatically.
Caret styles
Selects the cursor character to display.
"block"— renders the vertical bar character▋, similar to a terminal block cursor"circle"— renders the filled circle character●, a subtler dot indicator
- Block
- Circle
Conditional display in chat UIs
Streamdown has no concept of message order or role. In a chat interface, you typically want the caret to appear only on the last assistant message while it is being streamed:chat.tsx
When the caret is hidden
Even when bothcaret and isAnimating={true} are set, Streamdown suppresses the caret in two situations:
- Inside an incomplete code fence — when the last block contains an open
```without a closing```, the caret is hidden to avoid rendering inside a highlighted code block - Inside a table — when the last block contains a table, the caret is hidden to avoid disrupting table layout
How it works
The caret is implemented with a CSS custom property and a pseudo-element:-
When
caretandisAnimatingare both set, Streamdown writes the caret character to the CSS variable--streamdown-careton the container element: -
A
::afterpseudo-element on the last child reads the variable and renders inline: -
When streaming ends or
caretisundefined, the CSS variable and the class that enables the pseudo-element are removed, so no extra DOM nodes are left behind.
The caret does not blink by default. If you want a blinking animation, you can target the
::after pseudo-element with a CSS animation using a [data-streamdown] selector or a scoped className.