# Code block

Package: @commenda/pathfinder@0.1.0
Page: /docs/components/code-block
Figma: https://www.figma.com/design/dn7BkGYEfIyP0o2zfesfVh/The-System?node-id=596-28365

```tsx
import { CodeBlock } from '@commenda/pathfinder/code-block';

<CodeBlock
  code="SELECT entity, filing FROM filings;"
  language="sql"
  filename="q3_filings.sql"
/>;
```


## Usage [#usage]

```tsx
import { CodeBlock } from '@commenda/pathfinder/code-block';
import '@commenda/pathfinder/styles.css';
import '@commenda/pathfinder/code-font.css';

<CodeBlock code={source} language="sql" filename="q3_filings.sql" />;
```

Load compiled CSS once in your application. The optional code-font stylesheet supplies Geist Mono; without it, the component uses the host's monospace fallback. No app-side Tailwind compilation or syntax stylesheet is needed.

## Examples [#examples]

### Tool request and response [#tool-request-and-response]

Pass the original payload string when exact formatting matters. The component does not parse, prettify, or execute it.


```tsx
<CodeBlock
  variant="payload"
  language="json"
  filename="list_filings"
  code={JSON.stringify({ request, response }, null, 2)}
/>;
```


### Diff [#diff]

Mark one-based **source line positions**. The original code remains unchanged, including when copied. Added and removed lines have both a background and a gutter marker.


```tsx
<CodeBlock
  variant="diff"
  language="json"
  filename="registration.json"
  code={source}
  diffConfig={{ removed: [3], added: [4] }}
/>;
```


### Plain text and unknown languages [#plain-text-and-unknown-languages]

Unsupported languages fall back to readable plain text. Line numbers can be hidden.


```tsx
<CodeBlock
  language="unknown-format"
  code={source}
  lineNumberConfig={{ visible: false }}
/>;
```


## API reference [#api-reference]

| Prop | Type | Requirement | Behavior |
| --- | --- | --- | --- |
| `code` | `string` | required | Required source; copying preserves whitespace and trailing newlines |
| `language` | `string` | optional | `text`; Highlight.js common languages and aliases |
| `filename` | `string` | optional | Optional header label; long names truncate with full native title |
| `variant` | `"code" \| "payload" \| "diff"` | optional | `code` |
| `lineNumberConfig` | `{ visible?: boolean; start?: number; }` | optional | Visible, starts at 1 |
| `showLineNumbers` | `boolean` | optional | Compatibility prop; explicit `lineNumberConfig.visible` wins |
| `diffConfig` | `{ added?: readonly number[]; removed?: readonly number[]; }` | optional | One-based source line positions, independent of displayed starting number |
| `copyConfig` | `CodeCopyConfig` | optional | Copy enabled by default |

### lineNumberConfig fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `visible` | `boolean` | No |  |
| `start` | `number` | No |  |

### diffConfig fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `added` | `readonly number[]` | No |  |
| `removed` | `readonly number[]` | No |  |

### copyConfig fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `enabled` | `boolean` | No |  |
| `label` | `string` | No |  |
| `copiedLabel` | `string` | No |  |
| `errorLabel` | `string` | No |  |
| `onCopy` | `(() => void)` | No |  |
| `onError` | `((error: Error) => void)` | No |  |

`CodeCopyConfig` supports `enabled`, `label`, `copiedLabel`, `errorLabel`, `onCopy`, and `onError(error)`. Clipboard failure is announced and remains retryable; the success indicator resets after two seconds. Callbacks run after the clipboard outcome.

## Design and accessibility rules [#design-and-accessibility-rules]

- **CODE-01:** White surface, pearl-300 hairline, radius 8, 32px header, 12px body inset, Geist Mono 10/16 without ligatures.
- **CODE-02:** Show line numbers by default. Long source scrolls horizontally; never truncate or collapse code silently.
- **CODE-03:** Copy excludes labels and the gutter. Diff meaning must not rely on color alone.
- **CODE-04:** Payloads remain inert source; unknown languages still render. Highlighting loads after mount and does not block initial content.
- The scroll region is keyboard-focusable. Clipboard outcomes use a polite status announcement.

## Migration notes [#migration-notes]

Existing `code`, `language`, and `showLineNumbers` values can be reused. Replace compound CodeBlock header/copy children with `filename` and `copyConfig`. This is a documented future migration path; no existing consumers are changed. The renderer uses Lowlight/Highlight.js, not Shiki. See the [AI content integration guide](/docs/guides/ai-content).
