Code Block

A syntax-highlighted code block component with copy functionality and customizable layout

Preview

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

TypeScript
types/user.ts
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.

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class 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

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

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])

TypeScript
config/theme.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
export 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.

TypeScript
lib/api.ts
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)

JavaScript
utils/cart.js
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)

JavaScript
utils/cart.js
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

JavaScript
utils/helpers.js
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

TypeScript
types/user.ts
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

JavaScript
api/users.js
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)

JavaScript
api/users.js
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.

Prop

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.

Prop

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.

Prop

CodeBlockCode

The actual syntax-highlighted code element. Automatically consumes code and nodes (highlighted JSX) from CodeBlock context.

Prop