Components / Code block
Code block
Showing a copyable snippet — install steps, API examples, generated prompts. One block, one snippet.
import { CodeBlock } from '@layers/ui/code-block'Rendered stock
House rules
- maxHeight caps the snippet and scrolls it inside itself. Reach for it when the snippet is something the reader COPIES rather than reads — a generated agent prompt, a long config dump — and its length would otherwise push the action that acts on it off the surface. Leave it off in docs and anywhere the code is the thing being read: a nested scroller nobody asked for is worse than a tall block.
- copyOnClick makes the whole snippet the copy target: a click anywhere in it copies all of it, and "Copied" shows beside the corner button for two seconds. Use it for text the reader pastes somewhere else (an agent prompt, a terminal command, an ID, a secret), shown open by default. Never hide that text behind a show/hide toggle or put a large primary copy button beside it: people trust what they can read before they paste it. A click that ends a text selection keeps the selection, so part of it can still be copied.
- wrap breaks long lines inside the block, and a long URL breaks anywhere, so prose never scrolls sideways. Use it for prose in a monospace block (a generated agent prompt, a fix prompt). Code keeps the default: a wrapped line of code reads as two lines.
- If the clipboard is unavailable the block selects the snippet instead, so the reader copies it with their own shortcut. Callers add no fallback of their own.
- The copy button is built in. Never wrap the block in your own copy affordance or hand-roll a <pre>.
- CodeBlock is atomic — one snippet. To switch languages or files, make CodeBlocks the children of a Tabs; to frame a group of steps, wrap them in a Card. Do not add a switcher to the block itself.
- A header row appears when you pass a `filename` or a `language`; otherwise the copy button overlays the top-right.
- Line numbers appear automatically for any multi-line snippet (the convention); single lines have none. Override with `lineNumbers={false}` (force off) or `lineNumbers` (force on).
- The block sits on --background with a 1px border — intentionally unlike the borderless Card, so a snippet reads as a distinct inset panel.
- Syntax highlighting (sugar-high) is on by default, tuned for JS/TS/JSX. Pass `highlight={false}` for prose or non-code text that would mis-tokenize (e.g. a generated agent prompt). The token palette lives in packages/ui css/code-block.css — tune it there, never per call.
- Long lines scroll horizontally inside the block; the surrounding layout never scrolls sideways.