Skip to content
Redpanda UI
Esc
↑↓navigate↵open⌘Jpreview
On this page
Made by shadcn

useHighlightedCode

Highlights code with Shiki, one React node per line, for a Code Block.

Powered by

Installation

npx shadcn@latest add @redpanda/use-highlighted-code
pnpm dlx shadcn@latest add @redpanda/use-highlighted-code
yarn dlx shadcn@latest add @redpanda/use-highlighted-code
bunx shadcn@latest add @redpanda/use-highlighted-code
nubx shadcn@latest add @redpanda/use-highlighted-code
aube dlx shadcn@latest add @redpanda/use-highlighted-code

The install brings the highlighter library with it. Code Block installs both.

useHighlightedCode(code, language) returns one React node per line. Each one goes in a CodeBlockLine. CodeBlockLines calls it for you and keys the lines, so reach for the hook when you render the lines yourself. Every token carries both themes’ colours, and the theme’s code-token utility picks the one for the theme around it, so update @redpanda/theme along with the hook.

Usage

"use client"

import {
  CodeBlock,
  CodeBlockContent,
  CodeBlockLine,
} from "@/components/redpanda-ui/components/code-block"
import { useHighlightedCode } from "@/components/redpanda-ui/lib/use-highlighted-code"

export function Snippet({ code }: { code: string }) {
  const lines = useHighlightedCode(code, "yaml")

  return (
    <CodeBlock>
      <CodeBlockContent lineNumbers>
        {lines.map((line, index) => (
          <CodeBlockLine key={index}>{line}</CodeBlockLine>
        ))}
      </CodeBlockContent>
    </CodeBlock>
  )
}

Behavior

  • Plain lines come first. The hook returns the code split into lines until the language loads, so the block keeps its size when the colours arrive.
  • Each language loads on first use, as its own chunk. An unlisted language stays plain, and loads nothing.
  • A trailing newline is ignored, so it does not render as an empty last line.
  • Streaming only tokenizes new lines. When the code grows, the finished lines keep their nodes, and only the lines after them are tokenized, from the grammar state the last finished line left.
  • "ansi" renders terminal colours from ANSI escape codes, one line at a time.

Languages

The list lives in lib/highlighter: bash, css, diff, go, html, java, javascript, json, jsx, log, markdown, powershell, protobuf, python, rust, sql, toml, tsx, typescript, and yaml. Aliases include ts, js, sh, shell, zsh, yml, md, py, rs, proto, ps1, and golang, and a language-* class from a Markdown fence resolves too. Add a language with one line:

const languages = {
  // ...
  kotlin: () => import("shiki/langs/kotlin.mjs"),
}

On the server

highlightCode(code, language) from lib/highlighter is async, so a Server Component can highlight and keep Shiki out of the client bundle. It returns the same lines, or null for an unlisted language.

import { highlightCode } from "@/components/redpanda-ui/lib/highlighter"

const lines = (await highlightCode(code, "sql")) ?? code.split("\n")

API

PropType
codestring

The code to highlight. It may grow between renders as it streams.

Typestring
languagestring

A listed language or alias, a `language-*` class, or `"ansi"`. Anything else stays plain.

Typestring

Returns React.ReactNode[], one node per line.

Credits

Last updated on

Was this page helpful?