Code Viewer

Syntax-highlighted code with folding, line highlights, copying, and streaming feedback.

Loading example…

Installation

bunx --bun shadcn@latest add @sui/code-viewer

Install with the shadcn CLI or use the shared @workspace/ui package. Follow the installation guide to configure the registry, load styles, and choose import aliases.

Usage

import { CodeViewer } from "@workspace/ui/components/code-viewer";

<CodeViewer code={'const theme = "bamboo";'} lang="typescript" title="theme.ts" />;

Lines, folding, and layout

Line numbers are shown by default. highlightLines uses one-based line numbers. Indented blocks following {, [, or ( can be folded with the gutter controls; changing code resets folding. This is an indentation-based view, not a syntax-aware code editor.

Set wrap for long lines or change maxHeight to limit the scrolling viewport. Use showLineNumbers={false} for compact snippets. The viewport is reachable with Tab and supports keyboard scrolling with a visible theme-colored focus ring.

Streaming content

Pass status="streaming" while appending code, then switch to "complete". The viewer displays status feedback and follows content near the bottom. Scrolling more than 32px away pauses following; returning to the bottom resumes it. Starting a new streaming session restores following by default. The example replays a local sequence and cleans up its timer on unmount.

Loading example…

Copy and theme behavior

Copy writes the original complete code, including folded lines, and provides success or failure feedback. Set copyable={false} to remove the action. Highlighting loads asynchronously with a bounded skeleton; streaming updates keep incoming text visible while tokens are prepared. If loading is pending, the complete source remains available to copy and to assistive technology; if highlighting fails, readable plain code remains available. An empty string displays the empty-state label.

The viewer follows the surrounding light or dark theme unless theme is supplied. Translate labels for copy, loading, empty, folding, writing, ready, copied, and copy failure.

Plain style and highlighting configuration

variant="plain" removes the outer frame and title bar while retaining the code and copy action. Override --code-highlight-bg to customize highlighted-line backgrounds.

An optional ShikiProvider shares highlighting configuration across its viewers and editors. themes provides light and dark themes, and languages preloads requested languages. Highlighting works without a provider; recognized languages and aliases load on demand, while unknown languages fall back to plain text.

Loading example…
import { CodeViewer, ShikiProvider } from "@workspace/ui/components/code-viewer";

<ShikiProvider
  themes={{ light: "github-light", dark: "github-dark" }}
  languages={["python", "sql"]}
>
  <CodeViewer
    code={code}
    lang="python"
    variant="plain"
    highlightLines={[2]}
    className="[--code-highlight-bg:var(--accent)]"
  />
</ShikiProvider>;

API reference

PropTypeDefault / behavior
variant"default" | "plain""default".
codestringRequired source text.
langstring"typescript".
theme"light" | "dark"Follows surrounding theme.
titleReactNodeOptional header title.
status"streaming" | "complete""complete".
showLineNumbersbooleantrue.
highlightLinesnumber[][]; one-based.
maxHeightnumber280 pixels.
wrapbooleanfalse.
copyablebooleantrue.
labelsPartial<CodeViewerLabels>English labels.
glassbooleanfalse.

The module exports CodeViewerProps and CodeViewerLabels. Highlighting uses Shiki. To edit instead of view, use Editor.

ShikiProviderProps is also exported from this module; theme names use Shiki bundled themes.

ShikiProvider

PropTypeDefault / behavior
themes{ light: BundledTheme; dark: BundledTheme }one-light and one-dark-pro.
languagesreadonly string[]Optional languages to preload.
onError(error: unknown) => voidReports preload failure without changing the plain-text fallback.

Keep static themes and languages outside the component to avoid restarting preloads.