Code block
Present code with legible hierarchy and copy access.
contentdeveloper
Preview
Code block preview
Live · keyboard ready
counter.tsxtsx
When to use
- Documentation snippets and install commands with a copy button.
- Long files that should collapse to a few lines with Show all, via maxLines.
When not to use
- Use copy-button alone for a one-line value such as an API key.
- Use text-stream for code arriving from an AI response in progress.
- Use a full highlighter library when you need many languages.
shadcn CLI
Also installs (2)
- manicat-foundation
- copy-button
Manual install(+)
registry.jsonjson
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "code-block",
"type": "registry:ui",
"title": "Code block",
"description": "Present code with legible hierarchy and copy access.",
"categories": [
"data"
],
"dependencies": [
"lucide-react",
"motion"
],
"registryDependencies": [
"https://manicat.viraza.net/r/manicat-foundation.json",
"https://manicat.viraza.net/r/copy-button.json"
],
"files": [
{
"path": "registry/components/code-block/code-block.tsx",
"type": "registry:component",
"target": "@components/manicat/code-block/code-block.tsx"
},
{
"path": "registry/components/code-block/code-block.module.css",
"type": "registry:component",
"target": "@components/manicat/code-block/code-block.module.css"
},
{
"path": "registry/components/copy-button/copy-button.tsx",
"type": "registry:component",
"target": "@components/manicat/copy-button/copy-button.tsx"
},
{
"path": "registry/components/copy-button/copy-button.module.css",
"type": "registry:component",
"target": "@components/manicat/copy-button/copy-button.module.css"
},
{
"path": "lib/use-copy-feedback.ts",
"type": "registry:lib",
"target": "@components/manicat/lib/use-copy-feedback.ts"
}
],
"docs": "Docs and live preview: https://uiarc.dev/components/code-block",
"meta": {
"tier": "free",
"kind": "component",
"docs": "https://manicat.viraza.net/components/code-block",
"markdown": "https://uiarc.dev/components/code-block/markdown",
"tags": [
"content",
"developer"
]
}
}Usage
Install the component, then copy this into your app. Change the content and the props to fit your screen.
example.tsxtsx
"use client";
import { CodeBlock } from "@/components/manicat/code-block/code-block";
export function CodeBlockExample() {
return (
<CodeBlock
code={`export function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You pressed {count} times.</p>
<button onClick={() => setCount(count + 1)}>
Press me
</button>
</div>
);
}`}
filename="counter.tsx"
language="tsx"
/>
);
}
Examples
Real screens rather than isolated props. Switch to Code to copy a whole example into your project.
Installation snippet A code card with a file name and syntax highlighting.
Installation snippet
A code card with a file name and syntax highlighting. preview
Live · keyboard ready
counter.tsxtsx
installation-snippet-a-code-card-with-a-file-name-and-syntax-highlighting-.tsxtsx
"use client";
import { CodeBlock } from "@/components/manicat/code-block/code-block";
export function CodeBlockSnippetExample() {
return (
<div className="w-full max-w-xl">
<CodeBlock
code={`export function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
You pressed {count} times
</button>
);
}`}
filename="counter.tsx"
language="tsx"
/>
</div>
);
}
Keyboard interactions
| Keys | Action |
|---|---|
| Tab | Focuses the copy button, the scrollable source, and the expand toggle. |
| Enter / Space | Copies the code or toggles the expanded state. |
Accessibility
- The block is a section labelled like "hello.ts source code"; the pre is focusable so keyboard users can scroll it.
- The expand toggle uses aria-expanded and aria-controls pointing at the source.
- Copy feedback comes from copy-button.
Motion
- Expanding or collapsing springs the source height; new code fades up in place.
- The toggle label rolls and its chevron rotates.
- Reduced motion snaps height and swaps text without movement.
Responsive behavior
- Long lines scroll horizontally inside the block, never the page.
- Below 420px the padding and font shrink and the copy button becomes icon-only.
Performance
- The built-in highlighter is a small regex pass with no language bundles.
- ResizeObservers measure the source for the height spring; many blocks on one page each run their own.
Notes for AI
- Use for documentation snippets and install commands. The highlighter is lightweight; use a full highlighter for many languages.
- Set maxLines for long files so pages stay scannable.