Code Block

A high-performance syntax-highlighted code surface powered by Shiki with zero-DOM CSS line numbers, dual themes, line highlighting, collapsible blocks, diff mode, code folding, diagnostic levels, and copy actions.

$ pnpm dlx shadcn@latest add @byphongphan/code-block
Requires @byphongphan in components.json
data-display
Loading preview...

Installation

$ pnpm dlx shadcn@latest add @byphongphan/code-block
Requires @byphongphan in components.json

Anatomy

CodeBlock├── CodeBlockHeader│   ├── CodeBlockTitle│   ├── CodeBlockLanguage│   ├── CodeBlockWrapToggle│   ├── CodeBlockDownloadButton│   └── CodeBlockCopyButton├── CodeBlockSurface (Built-in or via CodeBlockContent)│   ├── Line Numbers (CSS counter, zero-DOM)│   ├── Fold Toggles & Diff Indicators (+ / -)│   ├── Code Tokens & Words│   └── CodeBlockLineActions (Hover action bar)└── CodeBlockExpandButton

Usage

import {  CodeBlock,  CodeBlockCopyButton,  CodeBlockHeader,  CodeBlockLanguage,  CodeBlockTitle,} from "@/components/ui/code-block"
<CodeBlock code={code} language="typescript" showLineNumbers>  <CodeBlockHeader>    <CodeBlockTitle>example.ts</CodeBlockTitle>    <CodeBlockLanguage />    <CodeBlockCopyButton className="ml-auto" />  </CodeBlockHeader></CodeBlock>

Examples

Git Diff & Patch Review

Display additions and removals with dedicated line gutters and background tints for reviewing pull requests and patch differences.

src/auth/session.ts
typescript
import { cookies } from "next/headers"
export async function getSession() { // Legacy session extraction via raw cookie header const rawCookie = headers().get("cookie") // Secure token-based session resolution const cookieStore = await cookies() const token = cookieStore.get("session_token")?.value
if (!token) return null return verifySessionToken(token)}

Diagnostic Severity Levels

Surface inline compiler and linter diagnostics with error, warning, and info visual indicators.

src/utils/greeting.ts
typescript
interface UserProfile {  id: string  name: string  email: string  role?: "admin" | "editor" | "viewer"}
export function formatGreeting(user: UserProfile): string { // TS2345: Argument of type 'undefined' is not assignable to parameter of type 'string' const normalizedEmail = user.email.toLowerCase()
// ESLint: prefer-optional-chain if (user && user.role && user.role === "admin") { return `Welcome, Administrator ${user.name} (${normalizedEmail})` }
return `Welcome back, ${user.name}!`}

Collapsible with Max Lines

Clamp lengthy code snippets to a clean maximum height with a smooth bottom gradient fade and floating expand button.

src/hooks/use-projects.ts
typescript
import { useQuery } from "@tanstack/react-query"import { z } from "zod"
const projectSchema = z.object({ id: z.string().uuid(), name: z.string().min(1), status: z.enum(["active", "archived", "draft"]), stars: z.number().int().nonnegative(), updatedAt: z.string().datetime(),})
type Project = z.infer<typeof projectSchema>
async function fetchProjects(): Promise<Project[]> { const response = await fetch("/api/projects") if (!response.ok) { throw new Error(`Failed to fetch projects: ${response.statusText}`) } const data = await response.json() return z.array(projectSchema).parse(data)}
export function useProjects() { return useQuery({ queryKey: ["projects"], queryFn: fetchProjects, staleTime: 1000 * 60 * 5, gcTime: 1000 * 60 * 30, retry: 2, })}

Action Toolbar with Wrap & Download

A complete header bar equipped with soft line-wrapping toggles, one-click file download, and clipboard copy affordances.

src/lib/query-client.ts
typescript
import { QueryClient } from "@tanstack/react-query"
export const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: 1000 * 60 * 5, gcTime: 1000 * 60 * 60 * 24, refetchOnWindowFocus: false, retry: (failureCount, error) => { if (error instanceof Response && error.status === 404) return false return failureCount < 3 }, }, mutations: { onError: (err) => { console.error("Mutation failed with error:", err) }, }, },})

API Reference

CodeBlock

The root container managing syntax highlighting, Shiki streaming, CSS counter state, and context providers.

PropTypeDefaultDescription
codestring""Raw source code string to highlight.
language?stringundefinedProgramming language identifier (e.g. "typescript", "json", "bash").
lines?CodeBlockLine[]undefinedPre-tokenized server-side lines to skip client-side Shiki highlighter.
showLineNumbers?booleanfalseWhether to display numeric gutter indicators.
startLine?number11-based initial counter seed for line numbering.
highlightedLines?CodeBlockLineSpecundefinedComma-separated lines or inclusive ranges to highlight (e.g. "2,4-6").
highlightedWords?CodeBlockWordSpec[]undefinedExact token substrings to highlight with visual pills.
focusedLines?CodeBlockLineSpecundefinedLines to keep focused while dimming other lines.
diff?CodeBlockDiffSpecundefinedAddition and removal line specs (e.g. { added: "2-4", removed: "6" }).
lineLevels?CodeBlockLevelSpecundefinedDiagnostic levels per line (e.g. { error: "3", warning: "7" }).
maxLines?numberundefinedMaximum visible lines before clamping with a collapsible fade.
expanded?booleanundefinedControlled collapsed/expanded state when maxLines is set.
defaultExpanded?booleanfalseInitial uncontrolled expanded state.
onExpandedChange?(expanded: boolean) => voidundefinedCallback fired when the expanded state changes.
foldable?booleanfalseEnables indentation-based code folding with chevron toggles.
folded?number[]undefinedControlled array of folded region start lines.
defaultFolded?number[]undefinedInitial uncontrolled folded region start lines.
onFoldedChange?(folded: number[]) => voidundefinedCallback fired when folded regions change.
wrap?booleanundefinedControlled soft text wrapping toggle.
defaultWrap?booleanfalseInitial soft text wrapping state.
onWrapChange?(wrap: boolean) => voidundefinedCallback fired when wrap state changes.
selectable?booleanfalseAllows clicking and Shift-clicking lines for selection.
selectedLines?number[]undefinedControlled array of selected line numbers.
defaultSelectedLines?number[][]Initial uncontrolled selected line numbers.
onSelectedLinesChange?(lines: number[]) => voidundefinedCallback fired when line selections change.
streaming?booleanfalseEnables AI token streaming optimizations with animated caret.
variant?"default" | "ghost""default"Visual surface variant. "ghost" renders a transparent backdrop.
className?stringundefinedAdditional classes merged onto the root element.

CodeBlockContent

Composable surface that renders the code block inside an external scroll wrapper (e.g. ScrollArea).

PropTypeDefaultDescription
className?stringundefinedAdditional classes for the surface element.

CodeBlockHeader

Top toolbar header housing filename title, language tag, and action buttons.

PropTypeDefaultDescription
className?stringundefinedAdditional classes for the header container.
childrenReact.ReactNodeundefinedHeader content elements.

CodeBlockTitle

Displays the file name or snippet label with standard typography.

PropTypeDefaultDescription
children?React.ReactNodeundefinedTitle label text. Defaults to active file name.
className?stringundefinedAdditional classes for the title element.

CodeBlockLanguage

Displays the detected or specified syntax language badge.

PropTypeDefaultDescription
className?stringundefinedAdditional classes for the language label.

CodeBlockCopyButton

Interactive clipboard button with animated copied state feedback.

PropTypeDefaultDescription
value?stringundefinedExplicit text to copy. Defaults to the current code snippet.
position?"default" | "pinned""default"Placement strategy. "pinned" places the button in the top-right corner.
alwaysVisible?booleanfalseWhen pinned, keeps the button visible instead of fading in on hover.
className?stringundefinedAdditional classes for the copy button.

CodeBlockDownloadButton

Downloads the current code block content as a local file.

PropTypeDefaultDescription
filename?stringundefinedTarget download filename (e.g. "snippet.tsx").
label?string"Download code"Accessible ARIA label.
className?stringundefinedAdditional classes for the download button.

CodeBlockWrapToggle

Toggles soft line-wrapping on and off.

PropTypeDefaultDescription
className?stringundefinedAdditional classes for the toggle button.

CodeBlockExpandButton

Floating expand/collapse control rendered when maxLines clamps code block height.

PropTypeDefaultDescription
expandText?string"Expand"Label displayed when collapsed.
collapseText?string"Collapse"Label displayed when expanded.
className?stringundefinedAdditional classes for the button.

CodeBlockLineActions

Render prop registering custom action controls on hovered/active code lines.

PropTypeDefaultDescription
side?"end" | "gutter""end"Placement of the action control on the line row.
children(data: { line: number, text: string }) => ReactNode—Render prop receiving active line metadata.

References

Command Palette

Quick search and commands navigation