diff --git a/apps/website/content/docs/components.mdx b/apps/website/content/docs/components.mdx index 50ffee35..5eb0860b 100644 --- a/apps/website/content/docs/components.mdx +++ b/apps/website/content/docs/components.mdx @@ -59,19 +59,21 @@ You can override any of the following standard HTML components: Custom components receive all the props that the default components would receive, including: - `children` - The content to render -- `className` - CSS class names from the Markdown AST (if applicable) +- `className` - CSS class names from the Markdown AST (if applicable). This does not include Streamdown's built-in default styles. - `node` - The Markdown AST node (for advanced use cases) - Element-specific props (e.g., `href` for links, `src` for images) Custom components **fully replace** the default implementations, including their built-in Tailwind styles. The `className` prop only contains classes from the Markdown AST (e.g., `language-js` on code elements) — it does **not** include the default styles that Streamdown normally applies. - If you need to preserve the default appearance, you must re-apply the styles yourself. See the [Styling](/docs/styling) documentation for the default classes, or use [CSS selectors with `data-streamdown` attributes](/docs/styling#global-css-targeting) instead of component overrides when you only need visual changes. + If you need to preserve the default appearance and behavior, import `defaultComponents` and render the built-in component inside your override. This keeps the default styles in sync with Streamdown updates and preserves attributes like `data-streamdown`. -For example, the default `h2` component applies `mt-6 mb-2 font-semibold text-2xl`. When you override it, those styles are lost unless you include them: - ```tsx title="app/page.tsx" +import { Streamdown, defaultComponents } from "streamdown"; + +const DefaultH2 = defaultComponents.h2; + {children} ), // ✅ Preserves default styles alongside custom ones - h2: ({ children, className }) => ( -

- {children} -

+ h2: ({ className, ...restProps }) => ( + ), }} > diff --git a/packages/streamdown/index.tsx b/packages/streamdown/index.tsx index be32d9fd..873a3fc9 100644 --- a/packages/streamdown/index.tsx +++ b/packages/streamdown/index.tsx @@ -63,6 +63,7 @@ export { CodeBlockHeader } from "./lib/code-block/header"; export { CodeBlockSkeleton } from "./lib/code-block/skeleton"; export { detectTextDirection } from "./lib/detect-direction"; export type { IconMap } from "./lib/icon-context"; +export { defaultComponents }; export type { AllowElement, diff --git a/packages/streamdown/lib/components.tsx b/packages/streamdown/lib/components.tsx index 2449ca3a..e0ec4e49 100644 --- a/packages/streamdown/lib/components.tsx +++ b/packages/streamdown/lib/components.tsx @@ -1016,7 +1016,7 @@ const MemoParagraph = memo( ); MemoParagraph.displayName = "MarkdownParagraph"; -export const components: Options["components"] = { +export const components = { ol: MemoOl, li: MemoLi, ul: MemoUl, @@ -1048,4 +1048,4 @@ export const components: Options["components"] = { sub: MemoSub, p: MemoParagraph, section: MemoSection, -}; +} satisfies Options["components"];