Syntax Highlighting
Syntax highlighting for code blocks in markdown.
assistant-ui provides two options for syntax highlighting:
- react-shiki (recommended for performance & dynamic language support)
- react-syntax-highlighter (legacy - Prism or Highlight.js based)
react-shiki
Add shiki-highlighter
npx shadcn@latest add @assistant-ui/shiki-highlighterMain Component
npm install react-shikiyarn add react-shikipnpm add react-shikibun add react-shikixpm add react-shiki"use client";import { FC } from "react";import ShikiHighlighter, { type ShikiHighlighterProps } from "react-shiki";import type { SyntaxHighlighterProps as AUIProps } from "@assistant-ui/react-markdown";import { cn } from "@/lib/utils";/** * Props for the SyntaxHighlighter component */export type HighlighterProps = Omit< ShikiHighlighterProps, "children" | "theme"> & { theme?: ShikiHighlighterProps["theme"];} & Pick<AUIProps, "node" | "components" | "language" | "code">;/** * SyntaxHighlighter component, using react-shiki * Use it by passing to `defaultComponents` in `markdown-text.tsx` * * @example * const defaultComponents = memoizeMarkdownComponents({ * SyntaxHighlighter, * h1: //... * //...other elements... * }); */export const SyntaxHighlighter: FC<HighlighterProps> = ({ code, language, theme = { dark: "kanagawa-wave", light: "kanagawa-lotus" }, className, addDefaultStyles = false, // assistant-ui requires custom base styles showLanguage = false, // assistant-ui/react-markdown handles language labels node: _node, components: _components, ...props}) => { return ( <ShikiHighlighter {...props} language={language} theme={theme} addDefaultStyles={addDefaultStyles} showLanguage={showLanguage} defaultColor="light-dark()" className={cn( "aui-shiki-base [&_pre]:overflow-x-auto [&_pre]:rounded-b-lg [&_pre]:bg-muted/75! [&_pre]:p-4", className, )} > {code.trim()} </ShikiHighlighter> );};SyntaxHighlighter.displayName = "SyntaxHighlighter";This adds a /components/assistant-ui/shiki-highlighter.tsx file to your project and
installs the react-shiki dependency. The highlighter can be customized by editing
the config in the shiki-highlighter.tsx file.
Add it to defaultComponents in markdown-text.tsx
import { SyntaxHighlighter } from "./shiki-highlighter";
export const defaultComponents = memoizeMarkdownComponents({
SyntaxHighlighter: SyntaxHighlighter,
h1: /* ... */,
// ...other elements...
});Options
Prop
Type
Bundle Optimization
By default, react-shiki includes the full Shiki bundle, which contains all supported languages and themes.
To reduce bundle size, you can use the web bundle by changing the import to react-shiki/web, to include a smaller bundle of web related languages:
import ShikiHighlighter, { type ShikiHighlighterProps } from "react-shiki/web";Custom Bundles
For strict bundle size control, react-shiki also supports custom bundles created using createHighlighterCore from react-shiki/core (re-exported from Shiki):
import { createHighlighterCore, createOnigurumaEngine } from "react-shiki/core";
// Create the highlighter
// Use dynamic imports to load languages and themes on client on demand
const customHighlighter = await createHighlighterCore({
themes: [import("@shikijs/themes/nord")],
langs: [
import("@shikijs/langs/javascript"),
import("@shikijs/langs/typescript"),
],
engine: createOnigurumaEngine(import("shiki/wasm")),
});
// Then pass it to the highlighter prop
<SyntaxHighlighter
{...props}
language={language}
theme={theme}
highlighter={customHighlighter}
/>;For more information, see react-shiki - bundle options.
Dual/multi theme support
To use multiple theme modes, pass an object with your multi-theme configuration to the theme prop in the ShikiHighlighter component:
<ShikiHighlighter
/* ... */
theme={{
light: "github-light",
dark: "github-dark",
}}
/* ... */
>To make themes responsive to your site's theme mode, add one of the following CSS snippets to your project:
/* for class based dark mode */
html.dark .shiki,
html.dark .shiki span {
color: var(--shiki-dark) !important;
background-color: var(--shiki-dark-bg) !important;
/* Optional, if you also want font styles */
font-style: var(--shiki-dark-font-style) !important;
font-weight: var(--shiki-dark-font-weight) !important;
text-decoration: var(--shiki-dark-text-decoration) !important;
}
/* for query based dark mode */
@media (prefers-color-scheme: dark) {
.shiki,
.shiki span {
color: var(--shiki-dark) !important;
background-color: var(--shiki-dark-bg) !important;
/* Optional, if you also want font styles */
font-style: var(--shiki-dark-font-style) !important;
font-weight: var(--shiki-dark-font-weight) !important;
text-decoration: var(--shiki-dark-text-decoration) !important;
}
}For more information, see Shiki's documentation on dual and multi themes.
react-syntax-highlighter
This option may be removed in a future release. Consider using react-shiki instead.
Add syntax-highlighter
npx shadcn@latest add @assistant-ui/syntax-highlighterMain Component
npm install @assistant-ui/react-syntax-highlighter @types/react-syntax-highlighter react-syntax-highlighteryarn add @assistant-ui/react-syntax-highlighter @types/react-syntax-highlighter react-syntax-highlighterpnpm add @assistant-ui/react-syntax-highlighter @types/react-syntax-highlighter react-syntax-highlighterbun add @assistant-ui/react-syntax-highlighter @types/react-syntax-highlighter react-syntax-highlighterxpm add @assistant-ui/react-syntax-highlighter @types/react-syntax-highlighter react-syntax-highlighterimport { PrismAsyncLight } from "react-syntax-highlighter";import { makePrismAsyncLightSyntaxHighlighter } from "@assistant-ui/react-syntax-highlighter";import tsx from "react-syntax-highlighter/dist/esm/languages/prism/tsx";import python from "react-syntax-highlighter/dist/esm/languages/prism/python";import { coldarkDark } from "react-syntax-highlighter/dist/cjs/styles/prism";// register languages you want to supportPrismAsyncLight.registerLanguage("js", tsx);PrismAsyncLight.registerLanguage("jsx", tsx);PrismAsyncLight.registerLanguage("ts", tsx);PrismAsyncLight.registerLanguage("tsx", tsx);PrismAsyncLight.registerLanguage("python", python);export const SyntaxHighlighter = makePrismAsyncLightSyntaxHighlighter({ style: coldarkDark, customStyle: { margin: 0, width: "100%", background: "black", padding: "1.5rem 1rem", },});Adds a /components/assistant-ui/syntax-highlighter.tsx file to your project and installs the react-syntax-highlighter dependency.
Add it to defaultComponents in markdown-text.tsx
import { SyntaxHighlighter } from "./syntax-highlighter";
export const defaultComponents = memoizeMarkdownComponents({
SyntaxHighlighter: SyntaxHighlighter,
h1: /* ... */,
// ...other elements...
});Options
Supports all options from react-syntax-highlighter.
Bundle Optimization
By default, the syntax highlighter uses a light build that only includes languages you register. To include all languages:
import { makePrismAsyncSyntaxHighlighter } from "@assistant-ui/react-syntax-highlighter/full";