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}Anatomy
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
| Prop | Type | Default | Description |
|---|---|---|---|
code | string | required | The source code to display |
language | string | — | Language label, surfaced as data-language and on the context |
diff | Record<number, 'add' | 'remove'> | — | Diff markers keyed by 1-based line number |
highlightLines | number[] | — | 1-based line numbers to mark as highlighted |
startLine | number | 1 | Number the first line starts at |
copyResetAfter | number | 2000 | ms before the copied state resets |
Lines props
| Prop | Type | Description |
|---|---|---|
children | (props: { line: CodeBlockLine }) => ReactNode | Render function for a single line |
Each line has number (1-based), content (raw text), diff ('add' / 'remove' / undefined) and highlighted (boolean).
CopyButton props
| Prop | Type | Description |
|---|---|---|
children | ReactNode | ((props: { copied: boolean }) => ReactNode) | Static content or a render function receiving the copied state |
Data attributes
| Attribute | Element | Values |
|---|---|---|
data-language | Root, Code, <code> | The language prop when set |
data-line | Line wrapper | Present on every line |
data-line-number | Line wrapper | The 1-based line number |
data-diff | Line wrapper | "add" / "remove" when set |
data-highlighted | Line wrapper | Present when the line is highlighted |
data-copied | CopyButton | Present while the copied state is active |
Accessibility
- CopyButton renders as a
<button type="button">witharia-labeltoggling between"Copy code"and"Copied".
Last updated on