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

format-price.ts
typescript
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

use-debounce.ts
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

next.config.ts
Hover to see the full file
import type { NextConfig } from "next";
const nextConfig: NextConfig = { reactStrictMode: true, images: { remotePatterns: [{ hostname: "images.unsplash.com" }], }, experimental: { typedRoutes: true, },};
export default nextConfig;

Diff

lib/users.ts
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

avatar.tsx
ErrorWarningInfo
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

package.json
json
{  "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

login-page.tsx
<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-block

File tabs

typescript
export function slugify(text: string) {  return text.toLowerCase().trim().replace(/[^a-z0-9]+/g, "-");}

Streaming response

app/api/describe/route.ts
Generating

AI chat message

JD

How do I focus an input when a dialog opens?

AI

Patch review

lib/cart.ts
+2-1
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}
app/checkout/page.tsx
+1-1
export default function CheckoutPage() {  const total = getCartTotal(items)  return <Summary total={total} />  return <Summary total={total} freeShipping={total > 5000} />}

Code folding

send-weekly-digest.ts
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

average-rating.ts
Empty list crashes reduce
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

Terminal
> 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 B

Reference lines in chat

use-copy.ts
Press + on a line to reference it
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 };}
Ask about use-copy.ts...
No context yet

Theme token colors

use-theme.ts
Colors from theme tokens
export function useTheme() {  const [theme, setTheme] = useState<"light" | "dark">("light");  const toggle = () => setTheme((value) => (value === "light" ? "dark" : "light"));  return { theme, toggle };}
Unlock premium components
Get full control of shadcn/ui components, blocks and instances, including future additions.

Explore Shadcn Blocks

Ready-made page sections built with the same components.

View all blocks

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

PartDescription
CodeBlockThe root. Takes code and language, or prebuilt lines, plus options such as showLineNumbers, maxLines, streaming, foldable and selectable.
CodeBlockHeaderThe top bar for the file name, language label and actions. The copy button moves into it automatically.
CodeBlockTitle and CodeBlockLanguageThe file name and the detected language label shown in the header.
CodeBlockCopyButton and CodeBlockDownloadButtonCopy the code to the clipboard or save it as a file. Without a header they float over the top right corner.
CodeBlockWrapToggle and CodeBlockExpandButtonSwitch soft wrapping, and reveal a block collapsed with maxLines.
CodeBlockLineActionsA render prop that adds buttons to a line, at the end of the row or in the gutter.
CodeBlockContentThe 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-block1

The 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.

KeyAction
TabMoves focus to the code and its actions.
Arrow keysScroll the code, or move between lines when selectable.
Space / EnterSelects 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

Add the Code Block component and pass your code and language. It loads Shiki and the needed grammar on demand and renders themed tokens, so you do not have to set up a highlighter yourself.

Place CodeBlockCopyButton inside CodeBlock. Inside a CodeBlockHeader it sits in the header row; without a header it floats over the top right corner of the code.

Yes. Pass the partial code and set streaming while it grows. New lines animate in, the view follows the end, and markdownFences splits a raw assistant message into text and code parts while the fence is still open.

Pass a diff prop with added and removed line numbers, or parse a git patch with parseUnifiedDiff and pass each file's lines to the lines prop.

Yes. All code block variants on this page are free to copy or install with the shadcn CLI.

Looking for something else? Browse all shadcn/ui components or ready-made UI blocks built with them.