Skip to main content
Streamdown is configured entirely through props on the <Streamdown> component. This page documents every available prop, its type, default value, and what it controls.

Core props

children
string
The Markdown string to render. In mode="streaming" this value is expected to grow on each render as new tokens arrive.
mode
"streaming" | "static"
default:"\"streaming\""
Controls how Streamdown renders content.
  • "streaming" — parses the content into independent blocks and memoizes each one so only the last block re-renders as new tokens arrive. All streaming features (incomplete-markdown handling, carets, animation) are active.
  • "static" — renders the entire string as a single pass. Use this when the content is already complete (e.g. cached AI responses, documentation pages). Callbacks like onAnimationStart and onAnimationEnd are suppressed in this mode.
<Streamdown mode="static">{completedMarkdown}</Streamdown>
isAnimating
boolean
default:"false"
Signals that content is actively being streamed. When true:
  • The caret indicator is visible (if caret is set)
  • Copy/download buttons on code blocks and tables are disabled
  • The character-by-character animate plugin is active (if animated is set)
  • onAnimationStart fires on the transition from falsetrue
Set this to match the streaming state of your data source.
<Streamdown isAnimating={isStreaming}>{markdown}</Streamdown>
parseIncompleteMarkdown
boolean
default:"true"
When true (the default), Streamdown runs the remend preprocessor on the raw markdown string before parsing. Remend closes open formatting spans (bold, italic, inline code, links, etc.) and handles other incomplete constructs that a mid-stream token boundary can produce.Disable this only if you are streaming pre-validated complete markdown or if you are providing your own preprocessing.
<Streamdown parseIncompleteMarkdown={false}>{markdown}</Streamdown>
normalizeHtmlIndentation
boolean
default:"false"
Removes leading indentation (4+ spaces) from lines that begin with an HTML tag. This prevents the Markdown parser from treating indented HTML blocks as fenced code blocks.Useful when rendering AI-generated responses that include well-indented HTML with deeply nested tags.
<Streamdown normalizeHtmlIndentation>{markdown}</Streamdown>
dir
"auto" | "ltr" | "rtl"
Text direction applied to rendered blocks.
  • "ltr" / "rtl" — forces a fixed direction for all blocks.
  • "auto" — detects the direction of each individual block using the Unicode first strong character algorithm. This is the right choice for multilingual chat applications where different messages may be in different languages.
<Streamdown dir="auto">{markdown}</Streamdown>
className
string
Additional CSS class names added to the outermost <div> container. Useful for scoping styles or integrating with utility-class frameworks.If a prefix is also set, the class names you provide here are prefixed the same as Streamdown’s internal classes.
<Streamdown className="prose prose-lg dark:prose-invert max-w-none">
  {markdown}
</Streamdown>

Streaming & incomplete markdown

remend
RemendOptions
Fine-grained control over which incomplete-markdown completions the remend preprocessor applies. All options default to true. Pass false to disable a specific completion.
KeyDefaultDescription
linkstrueComplete incomplete links
imagestrueComplete incomplete images
boldtrueClose open ** bold spans
italictrueClose open * / _ italic spans
boldItalictrueClose open *** bold-italic spans
inlineCodetrueClose open ` inline code
strikethroughtrueClose open ~~ strikethrough spans
katextrueClose open $$ math blocks
setextHeadingstrueHandle incomplete setext headings
comparisonOperatorstrueEscape > in list items that look like blockquotes
htmlTagstrueStrip incomplete HTML tags at end of text
linkMode"protocol""protocol" uses a placeholder URL; "text-only" renders plain text
handlersArray of custom RemendHandler functions
<Streamdown
  remend={{
    links: false,  // disable link completion
    katex: false,  // disable KaTeX completion
  }}
>
  {markdown}
</Streamdown>

Styling props

shikiTheme
[ThemeInput, ThemeInput]
default:"[\"github-light\", \"github-dark\"]"
A [lightTheme, darkTheme] tuple passed to Shiki for syntax highlighting code blocks. Accepts any bundled theme name (BundledTheme) or a custom theme registration object (ThemeRegistrationAny).
import type { BundledTheme } from 'streamdown';

<Streamdown shikiTheme={['catppuccin-latte', 'catppuccin-mocha']}>
  {markdown}
</Streamdown>
components
Components
An object mapping HTML element names to custom React components. When you supply a component, it fully replaces the default renderer — including its built-in Tailwind classes.See the Components page for a full guide and the list of overridable elements. The special key inlineCode overrides only inline code without replacing the block code renderer.
<Streamdown
  components={{
    h1: ({ children }) => <h1 className="text-blue-600">{children}</h1>,
  }}
>
  {markdown}
</Streamdown>
prefix
string
A Tailwind CSS class prefix prepended to every utility class Streamdown generates internally. Set this to match the value passed to Tailwind v4’s prefix() function.User-supplied className values are also prefixed, so you must not prefix them yourself.
// tailwind.config: prefix("tw")
<Streamdown prefix="tw">{markdown}</Streamdown>
// Produces tw:flex, tw:items-center, etc.
The prefix also applies to the className prop. Pass unprefixed class names — Streamdown adds the prefix for you.

Custom HTML tags

allowedTags
Record<string, string[]>
A map of custom HTML tag names to their allowed attribute names. Tags not listed here are stripped by the sanitizer (content is preserved, the tag element is removed).This prop only takes effect when you are using the default rehype plugins.
<Streamdown
  allowedTags={{
    mention: ['user_id'],
    source: ['id'],
  }}
  components={{
    mention: ({ user_id, children }) => (
      <span className="text-blue-600">@{children}</span>
    ),
  }}
>
  {markdown}
</Streamdown>
literalTagContent
string[]
Tag names whose child content should be treated as plain text instead of parsed as Markdown. This prevents underscores, asterisks, and other Markdown metacharacters inside tag content from being formatted.Every tag listed here must also appear in allowedTags.
// <mention>some_user_name</mention> — underscore would normally italicize
<Streamdown
  allowedTags={{ mention: ['user_id'] }}
  literalTagContent={['mention']}
>
  {markdown}
</Streamdown>

Feature props

caret
"block" | "circle"
Displays a cursor character at the end of the last rendered element while isAnimating is true. See the Carets page for full details.
<Streamdown caret="block" isAnimating={isStreaming}>{markdown}</Streamdown>
animated
boolean | AnimateOptions
Enables character-by-character reveal animation for newly arrived tokens during streaming. Pass true for default settings or an AnimateOptions object to customize the animation.See the Animation page for full configuration.
controls
ControlsConfig
default:"true"
Controls visibility of the interactive buttons rendered on code blocks, tables, and Mermaid diagrams. Accepts true (show all), false (hide all), or a granular config object:
<Streamdown
  controls={{
    code: {
      copy: true,
      download: true,
    },
    table: {
      copy: true,
      download: true,
      fullscreen: true,
    },
    mermaid: {
      download: true,
      copy: true,
      fullscreen: true,
      panZoom: true,
    },
  }}
>
  {markdown}
</Streamdown>
lineNumbers
boolean
default:"true"
Show line numbers in fenced code blocks. Can be overridden per block by adding noLineNumbers to the code fence meta string:
```js noLineNumbers
const x = 1;
```
Configure the link-safety modal that appears before navigating to external URLs. See the Link Safety page for details.
<Streamdown
  linkSafety={{
    enabled: true,
    onLinkCheck: async (url) => isTrustedDomain(url),
  }}
>
  {markdown}
</Streamdown>
mermaid
MermaidOptions
Options for Mermaid diagram rendering.
mermaid.config
MermaidConfig
A Mermaid configuration object passed directly to the Mermaid renderer.
mermaid.errorComponent
React.ComponentType<MermaidErrorComponentProps>
A custom component rendered when a Mermaid diagram fails to parse or render. Receives { chart, error, retry } props.
plugins
PluginConfig
Plugin bundles for optional heavy features: math rendering, CJK text support, and custom code highlighters. See the Plugins section for setup guides.

Internationalization & icons

translations
Partial<StreamdownTranslations>
Override any of the built-in English UI labels used in copy buttons, download menus, and link modals. Any key you omit falls back to the English default. See the Internationalization page for all keys.
<Streamdown translations={{ copyCode: 'Copiar código', close: 'Cerrar' }}>
  {markdown}
</Streamdown>
icons
Partial<IconMap>
Override the SVG icon components used in controls. Any key you omit keeps the default icon. See the Internationalization page for the full IconMap interface.
import { CopyIcon } from 'my-icon-library';

<Streamdown icons={{ CopyIcon }}>{markdown}</Streamdown>

Lifecycle callbacks

onAnimationStart
() => void
Called when isAnimating transitions from false to true. Suppressed in mode="static". Wrap in useCallback to prevent unnecessary re-renders.
<Streamdown
  isAnimating={isStreaming}
  onAnimationStart={useCallback(() => console.log('started'), [])}
>
  {markdown}
</Streamdown>
onAnimationEnd
() => void
Called when isAnimating transitions from true to false. Suppressed in mode="static". Wrap in useCallback to prevent unnecessary re-renders.

Advanced props

BlockComponent
React.ComponentType<BlockProps>
default:"Block"
Replaces the internal component used to render each individual block. A block is one top-level Markdown section as returned by parseMarkdownIntoBlocksFn.Use this to wrap blocks with additional context providers or measurement logic without affecting the Markdown rendering pipeline.
parseMarkdownIntoBlocksFn
(markdown: string) => string[]
default:"parseMarkdownIntoBlocks"
Replaces the function that splits the full Markdown string into independent blocks before memoized rendering. The default implementation splits on blank lines between top-level elements.Providing a custom function lets you control block granularity (e.g. splitting on headings, or treating the whole string as a single block).
rehypePlugins
Pluggable[]
default:"Object.values(defaultRehypePlugins)"
The rehype plugin pipeline applied to each block’s HAST. The default pipeline includes rehype-raw, rehype-sanitize, and rehype-harden.Replace the entire array to use a fully custom pipeline. If you replace the default plugins, allowedTags will no longer work automatically — you must configure your sanitizer manually.
remarkPlugins
Pluggable[]
default:"Object.values(defaultRemarkPlugins)"
The remark plugin pipeline applied to Markdown before it is converted to HAST. The default pipeline includes remark-gfm and an internal remarkCodeMeta plugin.

Element filtering

These props match the react-markdown API, making Streamdown a drop-in replacement.
allowedElements
string[]
An allowlist of HTML tag names. All other elements are removed from the output. Cannot be combined with disallowedElements.
disallowedElements
string[]
default:"[]"
A blocklist of HTML tag names to remove from the output. Cannot be combined with allowedElements.
allowElement
(element: Element, index: number, parent: Parent | undefined) => boolean
A custom filter function called for each element in the tree. Return false to remove the element. Applied after allowedElements / disallowedElements.
unwrapDisallowed
boolean
default:"false"
When true, disallowed elements are replaced by their children instead of being removed entirely. Useful for stripping wrapper tags while keeping their content.
skipHtml
boolean
default:"false"
Ignore raw HTML in the Markdown source entirely.
urlTransform
(url: string, key: string, node: Element) => string | null | undefined
default:"defaultUrlTransform"
Transform every URL that appears in the Markdown (links, images, etc.). Return an empty string to remove the URL. URL security is handled separately by rehype-sanitize and rehype-harden.
import { Streamdown, defaultUrlTransform } from 'streamdown';

<Streamdown
  urlTransform={(url, key) => {
    if (key === 'src') {
      return `https://cdn.example.com/proxy?url=${encodeURIComponent(url)}`;
    }
    return defaultUrlTransform(url, key);
  }}
>
  {markdown}
</Streamdown>

Build docs developers (and LLMs) love