惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
WordPress大学
WordPress大学
Google DeepMind News
Google DeepMind News
T
The Exploit Database - CXSecurity.com
阮一峰的网络日志
阮一峰的网络日志
F
Fox-IT International blog
The GitHub Blog
The GitHub Blog
Engineering at Meta
Engineering at Meta
I
Intezer
P
Privacy & Cybersecurity Law Blog
B
Blog RSS Feed
Latest news
Latest news
小众软件
小众软件
A
Arctic Wolf
Attack and Defense Labs
Attack and Defense Labs
L
LINUX DO - 热门话题
博客园 - 聂微东
B
Blog
T
Troy Hunt's Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
Malwarebytes
Malwarebytes
爱范儿
爱范儿
Recorded Future
Recorded Future
Apple Machine Learning Research
Apple Machine Learning Research
人人都是产品经理
人人都是产品经理
D
Docker
T
Threat Research - Cisco Blogs
MyScale Blog
MyScale Blog
Martin Fowler
Martin Fowler
E
Exploit-DB.com RSS Feed
F
Fortinet All Blogs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
PCI Perspectives
PCI Perspectives
Scott Helme
Scott Helme
N
Netflix TechBlog - Medium
博客园 - 三生石上(FineUI控件)
T
True Tiger Recordings
C
Check Point Blog
Microsoft Azure Blog
Microsoft Azure Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
K
Kaspersky official blog
Security Latest
Security Latest
The Hacker News
The Hacker News
Microsoft Security Blog
Microsoft Security Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
Stack Overflow Blog
Stack Overflow Blog
S
Security @ Cisco Blogs
C
CXSECURITY Database RSS Feed - CXSecurity.com
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
M
Microsoft Research Blog - Microsoft Research

Streamdown Documentation

Migrate from react-markdown Custom renderers @streamdown/mermaid @streamdown/math Built-in Plugins @streamdown/code @streamdown/cjk Usage Typography Unterminated Block Parsing Styling Security Animation Memoization Link Safety Internationalization Interactivity Introduction GitHub Flavored Markdown Getting Started FAQ Configuration Components Code Blocks
Carets
Vercel · 2026-04-11 · via Streamdown Documentation

Visual cursor indicators for streaming content to show active generation.

Streamdown includes built-in caret (cursor) indicators that display at the end of streaming content. Carets provide a visual cue to users that content is actively being generated, similar to a blinking cursor in a text editor.

The caret prop adds a visual indicator at the end of your streaming markdown content. This feature enhances the user experience by making it clear when content is actively being generated versus when generation is complete.

Key features:

  • Two built-in styles - Choose between block () and circle () carets
  • Automatic positioning - Carets automatically appear at the end of the last rendered element
  • Streaming-aware - Only displays when isAnimating={true} and mode="streaming" (default)
  • CSS-based - Uses CSS custom properties and pseudo-elements for efficient rendering

To enable carets, pass the caret prop with either "block" or "circle":

import { Streamdown } from 'streamdown';

function StreamingChat() {
  const [isStreaming, setIsStreaming] = useState(true);
  const [content, setContent] = useState('');

  return (
    <Streamdown
      caret="block"
      isAnimating={isStreaming}
    >
      {content}
    </Streamdown>
  );
}

Streamdown provides two built-in caret styles:

Block Caret

The block caret displays a vertical bar () similar to a terminal cursor:

<Streamdown caret="block" isAnimating={true}>
  Streaming content...
</Streamdown>

Circle Caret

The circle caret displays a filled circle () for a subtler indicator:

<Streamdown caret="circle" isAnimating={true}>
  Streaming content...
</Streamdown>

The caret visibility is controlled by two conditions:

  1. caret prop is set - You must specify either "block" or "circle"
  2. isAnimating={true} - The caret only appears during active streaming

When streaming stops (when isAnimating becomes false), the caret automatically disappears, leaving only the completed content.

Streamdown doesn't know about roles or message ordering, so you should conditionally show carets for specific messages, such as only displaying them for the last message in a chat and only displaying them from assistant messages:

{messages.map((message, index) => (
  <Streamdown
    key={message.id}
    caret={
      message.role === 'assistant' &&
      index === messages.length - 1
        ? 'block'
        : undefined
    }
    isAnimating={isStreaming}
  >
    {message.content}
  </Streamdown>
))}

Carets are implemented using CSS custom properties and pseudo-elements:

  • The caret value is passed as a CSS custom property (--streamdown-caret)
  • A ::after pseudo-element is added to the last child element
  • The pseudo-element displays the caret character inline
  • When isAnimating becomes false or caret is undefined, the styles are removed

This approach ensures efficient rendering without additional DOM elements.