Elements

Syntax highlighter

Prism-based code highlighting for assistant markdown code blocks.

tsx
export function Assistant() {
  return <Thread />;
}
fig. 01

Installation

Install manually
npx shadcn@latest add "@assistant-ui/syntax-highlighter"
First time? Set up a runtime

Runtime components read their state from an assistant-ui runtime. Add one to an existing project:

npx assistant-ui@latest init

Then wrap your app in a runtime provider:

import { AssistantRuntimeProvider } from "@assistant-ui/react";
import { useChatRuntime, AssistantChatTransport } from "@assistant-ui/ai-sdk";

export default function App() {
  const runtime = useChatRuntime({
    transport: new AssistantChatTransport({ api: "/api/chat" }),
  });

  return (
    <AssistantRuntimeProvider runtime={runtime}>
      {/* your components */}
    </AssistantRuntimeProvider>
  );
}

The installation guide covers new projects, templates, and API routes.

SyntaxHighlighter tokenizes one fenced code block with Prism, through react-syntax-highlighter's async light build, and renders a light and a dark themed variant at once so a theme switch needs no re-render. With a runtime it replaces the plain code Markdown text renders by default; standalone you call it directly with the code, the language, and the tag components it mounts onto.

Getting started

Add it to MarkdownText's components

components/assistant-ui/elements/markdown-text.tsx
import { SyntaxHighlighter } from "./syntax-highlighter";

const defaultComponents = memoizeMarkdownComponents({
  SyntaxHighlighter,
  h1: /* ... */,
  // ...other elements...
});

Every fenced code block in an assistant message now highlights with the light and dark Coldark Prism token colors, drawn on the markdown code block's own themed background rather than Coldark's. Shiki highlighter is the newer, runtime-aware alternative: reach for this one if you are already on react-syntax-highlighter.

Anatomy

<>
  <Pre className="dark:hidden">{/* Coldark Cold tokens */}</Pre>
  <Pre className="hidden dark:block">{/* Coldark Dark tokens */}</Pre>
</>

Both the light and the dark highlighter mount on every render; Tailwind's dark: classes hide whichever one does not match the active theme, so switching themes toggles visibility instead of re-tokenizing.

Examples

Register another language

components/assistant-ui/elements/syntax-highlighter.tsx
import { PrismAsyncLight } from "react-syntax-highlighter";
import go from "react-syntax-highlighter/dist/esm/languages/prism/go";

PrismAsyncLight.registerLanguage("go", go);

Only js, jsx, ts, tsx (all mapped to the TSX grammar) and python are registered by default. A fenced block whose language is not registered still renders, unhighlighted.

Load every language instead

components/assistant-ui/elements/syntax-highlighter.tsx
import { makePrismAsyncSyntaxHighlighter } from "@assistant-ui/react-syntax-highlighter/full";

Swap the light-build import for the full build to skip per-language registration entirely, at the cost of a larger bundle.

Choose a different theme

components/assistant-ui/elements/syntax-highlighter.tsx
import { oneLight, oneDark } from "react-syntax-highlighter/dist/cjs/styles/prism";

const LightSyntaxHighlighter = makePrismAsyncLightSyntaxHighlighter({
  style: oneLight,
  customStyle: syntaxHighlighterCustomStyle,
  className: "dark:hidden",
});

Pass any react-syntax-highlighter Prism style in place of coldarkCold/coldarkDark; do the same for the dark variant.

API reference

MarkdownText's code-block pipeline supplies every prop below automatically, from the fenced block being rendered; you never call SyntaxHighlighter yourself once it is wired into components.

SyntaxHighlighter

PropTypeDefaultDescription
languagestringrequiredThe fence's language, for example "tsx". Selects the Prism grammar.
codestringrequiredThe code to highlight.
components{ Pre: ComponentType; Code: ComponentType }requiredTag components the highlighter renders into, as PreTag/CodeTag.