- Components
- Data Display
- Code Block
Shadcn Code Block Components
A syntax highlighted code block with copy and download actions, line numbers, diffs, diagnostics, folding and streaming support for docs and AI chat interfaces. Browse our collection of 18 Shadcn Code Block variants.
Basic
export function formatPrice(amount: number, currency = "USD") { return new Intl.NumberFormat("en-US", { style: "currency", currency, }).format(amount / 100);}Pinned copy button
export async function getProjectWithOwnerAndRecentActivity(projectId: string) { const project = await db.project.findUnique({ where: { id: projectId }, include: { owner: true } }); if (!project) throw new NotFoundError(`Project ${projectId} was not found`); return project;}
export function isProjectArchived(project: Project) { return project.archivedAt !== null;}
export function getProjectUrl(project: Project) { return `/projects/${project.slug}`;}
export function sortProjectsByActivity(projects: Project[]) { return [...projects].sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());}Highlighted lines and words
export function useDebounce<T>(value: T, delay = 300) { const [debounced, setDebounced] = useState(value);
useEffect(() => { const timer = setTimeout(() => setDebounced(value), delay); return () => clearTimeout(timer); }, [value, delay]);
return debounced;}Focused lines
import type { NextConfig } from "next";
const nextConfig: NextConfig = { reactStrictMode: true, images: { remotePatterns: [{ hostname: "images.unsplash.com" }], }, experimental: { typedRoutes: true, },};
export default nextConfig;Diff
export async function getUser(id: string) { const response = await fetch(`/api/users/${id}`); return response.json(); if (!response.ok) { throw new Error("Failed to load user"); } return (await response.json()) as User;}Diagnostics
export function Avatar({ user }: { user: User }) { const initials = user.name.split(" ").map((part) => part[0]);
return ( <div className="avatar"> <img src={user.image} /> <span>{initials}</span> </div> );}Collapsible
{ "name": "acme-dashboard", "version": "1.4.0", "private": true, "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "eslint ." }, "dependencies": { "next": "16.0.0", "react": "19.2.0", "react-dom": "19.2.0", "lucide-react": "0.540.0", "tailwind-merge": "3.3.1" }, "devDependencies": { "typescript": "5.9.2", "tailwindcss": "4.1.13" }}Word wrap
<div className="flex min-h-svh flex-col items-center justify-center gap-6 bg-muted p-6 md:p-10"> <LoginForm className="w-full max-w-sm rounded-xl border bg-background p-6 shadow-sm" /></div>Install command
pnpm dlx shadcn@latest add code-blockFile tabs
export function slugify(text: string) { return text.toLowerCase().trim().replace(/[^a-z0-9]+/g, "-");}Streaming response
AI chat message
How do I focus an input when a dialog opens?
Patch review
export function getCartTotal(items: CartItem[]) { const subtotal = items.reduce((sum, item) => sum + item.price * item.quantity, 0) const shipping = 500 const shipping = subtotal > 5000 ? 0 : 500 const discount = getDiscount(subtotal) return subtotal + shipping}export default function CheckoutPage() { const total = getCartTotal(items) return <Summary total={total} /> return <Summary total={total} freeShipping={total > 5000} />}Code folding
export async function sendWeeklyDigest(teamId: string) { const team = await db.team.findUnique({ where: { id: teamId } });
if (!team) { throw new TeamNotFoundError(teamId); }
const members = await db.member.findMany({ where: { teamId } });
for (const member of members) { if (member.digestEnabled) { } }
return { sent: members.length };}Fix with AI
export function averageRating(reviews: Review[]) { const scores = reviews.map((review) => review.rating); const total = scores.reduce((sum, score) => sum + score); return total / scores.length;}Terminal output
> acme-dashboard@1.4.0 build> next build
✓ Compiled successfully in 4.2s✓ Linting and checking validity of types⚠Image on /pricing is missing a width✓ Generating static pages (24/24)
Route (app) Size First Load JS┌ ○ / 5.2 kB 112 kB├ ○ /pricing 3.8 kB 109 kB└ ƒ /api/checkout 0 B 0 BReference lines in chat
export function useCopy(timeout = 2000) { const [copied, setCopied] = useState(false);
const copy = async (text: string) => { await navigator.clipboard.writeText(text); setCopied(true); setTimeout(() => setCopied(false), timeout); };
return { copied, copy };}Theme token colors
Unlock premium components
Explore Shadcn Blocks
Ready-made page sections built with the same components.
Shadcn Code Block Component
The Shadcn Code Block is a React component for showing source code with syntax highlighting. It covers what documentation sites, developer dashboards and AI chat apps need: copy and download buttons, line numbers, highlighted lines, diffs, diagnostics, folding and code that streams in token by token.
Highlighting runs on Shiki with the JavaScript regex engine, so it needs no WebAssembly, and each language grammar loads only when a block uses it. The chrome is built with shadcn/ui and Tailwind CSS, and every color comes from your theme.
What is the Shadcn Code Block Component?
A code block renders a snippet as a scrollable, selectable surface. CodeBlock takes the code and language and draws the highlighted lines itself, so its children are only chrome: a CodeBlockHeader with a title, the language and actions, or a copy button pinned over the code.
Line states are props, not markup. Pass line numbers to highlightedLines, focusedLines, diff or lineLevels and the block tints them. For inline code inside a sentence use a plain code element, and for an editable field use a Textarea.
Anatomy of the Shadcn Code Block
| Part | Description |
|---|---|
| CodeBlock | The root. Takes code and language, or prebuilt lines, plus options such as showLineNumbers, maxLines, streaming, foldable and selectable. |
| CodeBlockHeader | The top bar for the file name, language label and actions. The copy button moves into it automatically. |
| CodeBlockTitle and CodeBlockLanguage | The file name and the detected language label shown in the header. |
| CodeBlockCopyButton and CodeBlockDownloadButton | Copy the code to the clipboard or save it as a file. Without a header they float over the top right corner. |
| CodeBlockWrapToggle and CodeBlockExpandButton | Switch soft wrapping, and reveal a block collapsed with maxLines. |
| CodeBlockLineActions | A render prop that adds buttons to a line, at the end of the row or in the gutter. |
| CodeBlockContent | The code surface, placed explicitly when you wrap it in your own Scroll Area. |
18 Shadcn Code Block Variants
Each code block variant listed here is previewed live at the top of this page, together with its source code and install command.
- Basic: A file header with title, language and copy button over a numbered snippet.
- Pinned copy button: No header; the copy button floats over a long file inside a height limited Scroll Area.
- Highlighted lines and words: Marks the important lines and every use of two functions.
- Focused lines: Dims everything except the relevant part of a config file until you hover it.
- Diff: Added and removed lines with tints and +/- markers.
- Diagnostics: Error, warning and info lines with a small legend in the header.
- Collapsible: A long file cut at eight lines with a Show more button.
- Word wrap: A long JSX line with a toggle for soft wrapping.
- Install command: pnpm, npm, yarn and bun commands switched with Tabs.
- File tabs: The same function in TypeScript, Python and Go, one tab per file.
- Streaming response: Code that types itself in like an AI response, with a status badge and replay.
- AI chat message: An assistant reply split into prose and fenced code while it streams.
- Patch review: A git diff parsed into one block per file with change counts and a download button.
- Code folding: Collapsible regions with Fold all and Unfold all actions.
- Fix with AI: A failing line with an inline action that applies a patch and can be undone.
- Terminal output: Colored build output rendered from ANSI escape codes.
- Reference lines in chat: Select lines and add them as references to a chat composer.
- Theme token colors: Syntax colors taken from your theme variables instead of a fixed theme.
How to Install the Shadcn Code Block Component
Set up shadcn/ui in your project if you have not already, then add the Shadcn UI Kit registry to your components.json once:
{
"registries": {
"@shadcnuikit": "https://shadcnuikit.com/r/{name}.json"
}
}Then install a code block variant by its name:
npx shadcn@latest add @shadcnuikit/code-block1The same command works with pnpm dlx, yarn dlx and bunx --bun. Each variant has a copy button for every package manager, and the code is added to your project as plain React and Tailwind CSS that you can edit freely.
How to Use the Shadcn Code Block Component
Import the parts from components/ui/code-block. Pass the code as a string and add a header for the file name and actions.
import {
CodeBlock,
CodeBlockCopyButton,
CodeBlockHeader,
CodeBlockTitle,
} from "@/components/ui/code-block"
const code = `export function greet(name: string) {
return \`Hello \${name}\`
}`
export function Example() {
return (
<CodeBlock code={code} language="typescript" showLineNumbers>
<CodeBlockHeader>
<CodeBlockTitle>greet.ts</CodeBlockTitle>
<CodeBlockCopyButton className="ml-auto" />
</CodeBlockHeader>
</CodeBlock>
)
}Why Use the Shadcn Code Block Component
- Accurate highlighting: Shiki uses the same grammars as VS Code, with light and dark themes switched by CSS.
- Built for AI chat: Streaming mode, markdown fence parsing and line actions cover assistant replies and code review.
- Lightweight loading: The highlighter and each language load on demand, and no WebAssembly is required.
- Clean copy: Line numbers and diff markers are drawn with CSS, so copied text is exactly the source.
- Theme aware: Surfaces, tints and even token colors can follow your CSS variables in light and dark mode.
Common Code Block Use Cases
- Documentation: Install commands, API examples and config files.
- AI assistants: Streaming code answers with copy and apply actions.
- Code review: Patches with added and removed lines per file.
- Developer dashboards: API keys, webhooks and terminal logs.
- Tutorials: Focused and highlighted lines that guide the reader.
Customizing the Shadcn Code Block
Every part accepts a className, merged with cn(). Sizes and tints are CSS variables on the root, such as --code-block-font-size and --code-block-highlight-bg, so one class changes them. Diff and diagnostic tints use the success, warning, info and destructive theme colors, and a palette from the free Theme Generator restyles them.
For syntax colors from your own tokens, use the css-variables theme and set the token variables:
<CodeBlock
code={code}
language="tsx"
themes={{ light: "css-variables", dark: "css-variables" }}
className="[--code-token-keyword:var(--primary)] [--code-token-string:var(--success)]"
/>Code Block Accessibility and Keyboard Support
The code surface is a focusable region named by the label prop, so keyboard users can scroll long lines. Copy and download buttons have accessible names, the copy label changes to Copied after a click, and a polite status region announces when a stream finishes instead of reading every streamed token.
With selectable, lines become a list box: arrow keys move between lines and Space selects them. Folding toggles are real buttons with aria-expanded.
| Key | Action |
|---|---|
| Tab | Moves focus to the code and its actions. |
| Arrow keys | Scroll the code, or move between lines when selectable. |
| Space / Enter | Selects a line, or activates a focused button. |
Code Block Best Practices
- Show a file name in the header so readers know where the code belongs.
- Keep snippets short; collapse long files with maxLines.
- Highlight or focus only the lines that matter for the explanation.
- Wrap prose lines, but keep code unwrapped unless the line is very long.
- Group commands for different package managers with Tabs instead of stacking blocks.
Components Related to Code Block
Shadcn Code Block FAQ
Looking for something else? Browse all shadcn/ui components or ready-made UI blocks built with them.















