# CodeBlock

> Multi-line source with an optional filename header, line numbers, highlighted, added and removed rows, copy and a caption.

- Status: beta
- Group: structure
- Page: https://www.digitaltableteur.com/design-system/components/code-block
- Contract: https://www.digitaltableteur.com/contracts/v1/CodeBlock.contract.json

## 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

- Code: Do not use for one identifier inside a sentence; use Code.
- Snippet: Do not use for a single command the reader pastes into a terminal; use Snippet.

## 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` (default `light`).

## 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/content` exports it too.
- Styles: import `@digitaltableteur/react/style.css` once 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): https://www.digitaltableteur.com/contracts/v1/CodeBlock.contract.json
- Markdown version of this page: https://www.digitaltableteur.com/design-system/components/code-block.md
- Component index as JSON: https://www.digitaltableteur.com/design-system/components.json
- All components: https://www.digitaltableteur.com/design-system/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.
