CodeBlock
Multi-line source with an optional filename header, line numbers, highlighted, added and removed rows, copy and a caption.
Status: beta. Group: structure. Markdown version: /design-system/components/code-block.md
When to use
CodeBlock shows source the reader will scan or paste. Pass code as a string (highlighted at runtime) or a Shiki tree from the MDX pipeline. Give a filename when the code has a paste destination, highlight only the lines under discussion and mark diffs as added and removed rows instead of comments, so copy-paste still yields working code.
When not to use
- Do not use for a single command the reader pastes into a terminal; use Snippet.
- Do not use for one identifier inside a sentence; use Code.
Look-alikes
Props
| Prop | Type | Default | Description | Required |
|---|---|---|---|---|
code | string | none | Source to show. Highlighted at runtime for the common languages; with language="diff" the leading +/- of each line become added and removed rows. Pass either code or a pre-highlighted Shiki tree as children. | No |
children | React.ReactNode | none | A Shiki <pre><code> tree (rehype-pretty-code output). Callouts come from the MDX meta string: a line range highlights, and a range with the id "added" or "removed" marks a diff. | No |
language | string | none | Language of the code; shown in the header and drives highlighting. | No |
filename | string | none | File name shown in the header. Giving one turns the header on. | No |
header | boolean | true when `filename` is set | Show the header bar. | No |
lineNumbers | boolean | the Shiki tree's showLineNumbers, else false | Number the lines. | No |
highlightLines | CodeLineSpec | none | Lines to highlight: [2, 3] or "2-3,7". 1-based. | No |
addedLines | CodeLineSpec | none | Lines to mark as added. | No |
removedLines | CodeLineSpec | none | Lines to mark as removed. Copy leaves them out. | No |
caption | React.ReactNode | none | Caption under the card. | No |
theme | "light" | "terminal" | light | terminal renders the block in the dark theme on any page. In the high-contrast themes it follows the page so contrast stays at the high-contrast level. | No |
wrap | boolean | false | Wrap long lines instead of scrolling sideways. | No |
maxHeight | string | number | none | Cap the body height (any CSS length, or pixels) and scroll inside it. | No |
copyable | boolean | true | Show the copy button. | No |
copyLabel | string | "Copy code" (translated) | Accessible name for the copy button. | No |
onCopy | (text: string) => void | none | Called with the copied text. | No |
Variants
- Available themes:
light,terminal(defaultlight).
Invalid combinations
The contract records no invalid combinations.
Keyboard
| Key | Behaviour |
|---|---|
| Tab | Reaches the copy button, then the code body when it scrolls. |
| arrow keys | Scroll the focused body. |
Rules
Every item under When not to use is a MUST NOT. MUST and SHOULD follow RFC 2119.
| Level | Rule | How it is checked |
|---|---|---|
| MUST | ARIA: The body becomes a named, focusable region only when it overflows, so a short block adds no tab stop. | Not yet verified: no evidence record. WCAG 4.1.2. |
| MUST | ARIA: Added and removed rows carry a sign with translated alternative text (Added line, Removed line); state never rests on colour alone. | Not yet verified: no evidence record. WCAG 4.1.2. |
| MUST | ARIA: Line numbers are generated content with empty alternative text, so screen readers read the code only. | Not yet verified: no evidence record. WCAG 4.1.2. |
| MUST | ARIA: With a caption the block is a figure and the caption its figcaption. | Not yet verified: no evidence record. WCAG 4.1.2. |
| MUST | Required stories produce no axe violations at the configured severity. | Automated by npm run test:stories:matrix:ci. WCAG 2.5.8. |
| MUST | The accessibility tree (role, name, state) matches the committed snapshot for every required story. | Automated by npm run test:stories:matrix:ci. WCAG 1.3.1, 4.1.2. |
| MUST | The component remains legible and operable under a real browser forced-colors: active pass. | Automated by npm run test:stories:hc. |
| MUST | Every documented keyboard interaction works as specified. | Not yet verified: no evidence record. WCAG 2.1.1, 2.1.2. |
| MUST | A human completed an end-to-end accessibility review of this component. | Manual review, last on 2026-10-25. |
| SHOULD | Always set language; highlighting is the reason to choose CodeBlock over a plain pre. | Not stated in the contract. |
| SHOULD | Show a filename when the snippet belongs in a specific file; leave it out for throwaway examples. | Not stated in the contract. |
| SHOULD | Mark changes with addedLines and removedLines or language="diff"; copy leaves removed lines out. | Not stated in the contract. |
| SHOULD NOT | Do not highlight most of the block; a block where every line is highlighted reads like no highlight. | Not stated in the contract. |
| SHOULD NOT | Do not turn on line numbers for blocks under five lines. | Not stated in the contract. |
| SHOULD NOT | Do not nest it in another scroll container; use maxHeight. | Not stated in the contract. |
Install and import
- Install:
npm install @digitaltableteur/react(version 0.9.1, restricted access on npm). - Import:
import { CodeBlock } from "@digitaltableteur/react"; - Entry point:
@digitaltableteur/react/contentexports it too. - Styles: import
@digitaltableteur/react/style.cssonce at the app boundary. - Also available as the custom element
<dt-code-block>; see the custom elements manifest.
Links
- Machine-readable contract (Design System Contract 1.0)
- Markdown version of this page
- Component index as JSON
- All components
- Source: The implementation lives in a private repository. This page, its Markdown twin and the contract are generated from it at build time and are the public source of truth.