Code Block
A syntax-highlighted code block component with copy functionality and customizable layout
Preview
function fibonacci(n) { if (n <= 1) return n; return fibonacci(n - 1) + fibonacci(n - 2); } console.log(fibonacci(10)); // Output: 55
Installation
npx shadcn@latest add @cubby-ui/code-block
Usage
import { CodeBlock, CodeBlockHeader, CodeBlockPre, CodeBlockCode, } from "@/components/ui/cubby-ui/code-block";
<CodeBlock> <CodeBlockHeader /> <CodeBlockPre> <CodeBlockCode /> </CodeBlockPre> </CodeBlock>
Examples
Floating Copy Button
Display code without a header using a floating copy button that appears on hover.
function greet(name) { return `Hello, ${name}!`; } console.log(greet("World"));
With Filename
Display a filename in the header to provide context for the code snippet.
export interface User { id: string; name: string; email: string; role: "admin" | "user"; } export function createUser(data: Omit<User, "id">): User { return { ...data, id: crypto.randomUUID(), }; }
With Tabs
Show multiple code variants using tabs, commonly used for different package managers or language implementations.
Switch between package managers using the tabs in the header.
npm install react-query
With Line Numbers
Add line numbers to help users reference specific lines of code.
12345678910111213141516171819202122232425262728293031class BinarySearchTree { constructor() { this.root = null; } insert(value) { const newNode = { value, left: null, right: null }; if (!this.root) { this.root = newNode; return; } let current = this.root; while (true) { if (value < current.value) { if (!current.left) { current.left = newNode; return; } current = current.left; } else { if (!current.right) { current.right = newNode; return; } current = current.right; } } } }
Multiple Languages
The component automatically detects and highlights syntax for different programming languages.
TypeScript
interface ApiResponse<T> { data: T; status: number; message: string; } async function fetchUser(id: string): Promise<ApiResponse<User>> { const response = await fetch(`/api/users/${id}`); return response.json(); }
Python
def quicksort(arr): if len(arr) <= 1: return arr pivot = arr[len(arr) // 2] left = [x for x in arr if x < pivot] middle = [x for x in arr if x == pivot] right = [x for x in arr if x > pivot] return quicksort(left) + middle + quicksort(right) print(quicksort([3, 6, 8, 10, 1, 2, 1])) # [1, 1, 2, 3, 6, 8, 10]
Bash
#!/bin/bash # Deploy script echo "Starting deployment..." npm run build npm run test if [ $? -eq 0 ]; then echo "Tests passed! Deploying..." npm run deploy else echo "Tests failed. Deployment cancelled." exit 1 fi
Custom Icon
Override the default language icon with a custom icon of your choice.
function greet(name) { return `Hello, ${name}! ✨`; } console.log(greet("World"));
Custom Height
Control the maximum height and scrolling behavior with custom classes.
Custom max height with scrolling (max-h-[200px])
12345678910111213141516171819202122232425262728293031323334353637383940414243444546export const theme = { colors: { primary: "#3b82f6", secondary: "#8b5cf6", success: "#10b981", warning: "#f59e0b", danger: "#ef4444", info: "#06b6d4", }, spacing: { xs: "0.25rem", sm: "0.5rem", md: "1rem", lg: "1.5rem", xl: "2rem", "2xl": "3rem", }, typography: { fontFamily: { sans: "Inter, system-ui, sans-serif", mono: "Fira Code, monospace", }, fontSize: { xs: "0.75rem", sm: "0.875rem", base: "1rem", lg: "1.125rem", xl: "1.25rem", "2xl": "1.5rem", "3xl": "1.875rem", "4xl": "2.25rem", }, fontWeight: { normal: 400, medium: 500, semibold: 600, bold: 700, }, }, borderRadius: { sm: "0.25rem", md: "0.5rem", lg: "1rem", full: "9999px", }, };
Server-Side Highlighting
Pre-highlight code on the server using the highlight function for instant rendering with zero client-side delay.
export async function fetchUserData(userId: string) { const response = await fetch(`/api/users/${userId}`); if (!response.ok) { throw new Error('Failed to fetch user data'); } return response.json(); }
Highlighted Lines
Emphasize specific lines with background highlighting and a left border accent.
Highlight specific lines (lines 2, 5)
function calculateTotal(items) { let total = 0; for (const item of items) { total += item.price * item.quantity; } return total; }
Highlight range using string syntax (lines 1-3, 7)
function calculateTotal(items) { let total = 0; for (const item of items) { total += item.price * item.quantity; } return total; }
Diffs
Show code changes with added, removed, and modified line indicators. Diff markers are automatically stripped from the displayed code.
Diff view with added (+), removed (-), and modified (!) lines
function greet(name) { console.log("Hello " + name); console.log(`Hello, ${name}!`); } function calculatePrice(item) { return item.price; return item.price * (1 - item.discount); // Apply discount }
Using comment-style markers for TypeScript/JSX compatibility
export interface User { id: string; name: string; email: string; emailAddress: string; emailVerified: boolean; }
Focus Mode
Blur non-focused lines to draw attention to specific parts of the code.
Focus on specific lines (lines 4-5) - other lines are dimmed
async function fetchUser(userId) { const response = await fetch(`/api/users/${userId}`); if (!response.ok) { throw new Error('Failed to fetch user'); } const data = await response.json(); return data; }
Focus on a range using string syntax (lines 1-2, 8)
async function fetchUser(userId) { const response = await fetch(`/api/users/${userId}`); if (!response.ok) { throw new Error('Failed to fetch user'); } const data = await response.json(); return data; }
API Reference
The CodeBlock component is a custom implementation built with Shiki for syntax highlighting. It does not extend Base UI.
Props
CodeBlock
The main component that manages state and provides context to sub-components automatically via React Context. Sub-components can access code, language, nodes, and lines without explicit prop passing.
CodeBlockHeader
Smart header component that auto-arranges language icons, filenames, tabs, and copy button based on props. Automatically consumes language and code from CodeBlock context.
CodeBlockPre
The pre-formatted text container that wraps the code content. Automatically consumes lines from CodeBlock context for line numbers. Includes group and relative classes for floating button support.
CodeBlockCode
The actual syntax-highlighted code element. Automatically consumes code and nodes (highlighted JSX) from CodeBlock context.