Skip to Content
⭐️ Leave a star →
ComponentsCodeBlock

CodeBlock

Code display with a copy button, line numbers and diff regions. Syntax highlighting is bring-your-own — render line.content through Shiki, Prism or any highlighter inside CodeBlock.Lines.

Features

Per-line render prop with line number, content, diff marker and highlighted flag.
Built-in copy button with a copied render state and data-copied attribute.
Diff regions via a line-number → 'add' / 'remove' map.
Highlight specific lines and offset numbering with startLine.
Headless — bring your own syntax highlighting and styles.

Example

1function greet(name) {2  const message = "Hello, " + name;3  return message;4}
import { CodeBlock } from '@wire-ui/react' <CodeBlock.Root code={source} language="js"> <CodeBlock.CopyButton> {({ copied }) => (copied ? 'Copied!' : 'Copy')} </CodeBlock.CopyButton> <CodeBlock.Code> <CodeBlock.Lines> {({ line }) => ( <> <span>{line.number}</span> {line.content} </> )} </CodeBlock.Lines> </CodeBlock.Code> </CodeBlock.Root>

Styling

CodeBlock ships zero styles. Each line rendered by CodeBlock.Lines is wrapped in a <span> carrying data-line, data-line-number, data-diff and data-highlighted — style against those, or read line.diff / line.highlighted inside the render prop. The copy button exposes data-copied.

<CodeBlock.CopyButton className=" text-black data-[copied]:text-green-600 "> {({ copied }) => (copied ? 'Copied!' : 'Copy')} </CodeBlock.CopyButton>

Using data attributes

The line wrapper and copy button set data attributes you can target from CSS.

/* Highlighted line */ [data-highlighted] { background: #f5f5f5; } /* Diff regions */ [data-diff="add"] { background: rgba(16, 185, 129, 0.15); } [data-diff="remove"] { background: rgba(239, 68, 68, 0.15); } /* Copy button after copying */ [data-copied] { color: #16a34a; }

Root props

PropTypeDefaultDescription
codestringrequiredThe source code to display
languagestringLanguage label, surfaced as data-language and on the context
diffRecord<number, 'add' | 'remove'>Diff markers keyed by 1-based line number
highlightLinesnumber[]1-based line numbers to mark as highlighted
startLinenumber1Number the first line starts at
copyResetAfternumber2000ms before the copied state resets

Lines props

PropTypeDescription
children(props: { line: CodeBlockLine }) => ReactNodeRender function for a single line

Each line has number (1-based), content (raw text), diff ('add' / 'remove' / undefined) and highlighted (boolean).

CopyButton props

PropTypeDescription
childrenReactNode | ((props: { copied: boolean }) => ReactNode)Static content or a render function receiving the copied state

Data attributes

AttributeElementValues
data-languageRoot, Code, <code>The language prop when set
data-lineLine wrapperPresent on every line
data-line-numberLine wrapperThe 1-based line number
data-diffLine wrapper"add" / "remove" when set
data-highlightedLine wrapperPresent when the line is highlighted
data-copiedCopyButtonPresent while the copied state is active

Accessibility

  • CopyButton renders as a <button type="button"> with aria-label toggling between "Copy code" and "Copied".
Last updated on

MIT License © 2026 wire-ui

CodeBlock – Wire UI