Get Started
Components
- Alert
- Avatar
- Badge
- Breadcrumb
- Button
- Button Group
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Checkbox Group
- ComboBox
- Command
- Data Table
- Date Field
- Date Picker
- Date Range Picker
- Dialog
- Disclosure
- Disclosure Group
- Drawer
- Empty
- Field
- File Trigger
- Form
- Grid List
- Hover Card
- Input
- Input Group
- Input OTP
- Item
- Kbd
- Label
- ListBox
- Menu
- Number Field
- Pagination
- Popover
- Progress Bar
- Radio Group
- Range Calendar
- Resizable
- Search Field
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Spinner
- Switch
- Table
- Tabs
- Tag Group
- Text Field
- Textarea
- Time Field
- Toast
- Toggle Button
- Toggle Button Group
- Tooltip
- Tree
- Typography
AI Elements
greet.ts
function greet(name: string) { return `Hello, ${name}!`;}const message = greet("World");console.log(message);"use client"
import {
CodeBlock,
CodeBlockBody,
CodeBlockContent,
CodeBlockCopyButton,
CodeBlockFilename,
CodeBlockHeader,
CodeBlockItem,
} from "@/components/ai-elements/code-block"
export function CodeBlockDemo() {
const codeData = [
{
language: "typescript",
filename: "greet.ts",
code: `function greet(name: string) {
return \`Hello, \${name}!\`;
}
const message = greet("World");
console.log(message);`,
},
]
return (
<CodeBlock data={codeData} defaultValue="typescript">
<CodeBlockHeader>
<CodeBlockFilename value="typescript">
{codeData[0].filename}
</CodeBlockFilename>
<CodeBlockCopyButton />
</CodeBlockHeader>
<CodeBlockBody>
{(item) => (
<CodeBlockItem key={item.language} value={item.language}>
<CodeBlockContent language={item.language as any}>
{item.code}
</CodeBlockContent>
</CodeBlockItem>
)}
</CodeBlockBody>
</CodeBlock>
)
}
Installation
CLI
Manual
pnpmnpmyarnbunpnpm dlx shadcn@latest add code-block
Usage
import {
CodeBlock,
CodeBlockBody,
CodeBlockContent,
CodeBlockCopyButton,
CodeBlockFilename,
CodeBlockHeader,
CodeBlockItem,
} from "@/ai-elements/code-block"const codeData = [
{
language: "typescript",
filename: "example.ts",
code: `function greet(name: string) {
return \`Hello, \${name}!\`;
}`,
},
]
<CodeBlock data={codeData} defaultValue="typescript">
<CodeBlockHeader>
<CodeBlockFilename value="typescript">
{codeData[0].filename}
</CodeBlockFilename>
<CodeBlockCopyButton />
</CodeBlockHeader>
<CodeBlockBody>
{(item) => (
<CodeBlockItem key={item.language} value={item.language}>
<CodeBlockContent language={item.language}>
{item.code}
</CodeBlockContent>
</CodeBlockItem>
)}
</CodeBlockBody>
</CodeBlock>Features
- Syntax highlighting powered by Shiki
- Line numbers
- Copy to clipboard functionality
- Support for filenames with auto-detected icons
- Highlighted lines and words
- Focused lines
- Diff annotations
- Language detection
- Theme support
- Customizable styles
Examples
No Header
function MyComponent(props) { return ( <div> <h1>Hello, {props.name}!</h1> <p>This is an example React component.</p> </div> );}"use client"
import {
CodeBlock,
CodeBlockBody,
CodeBlockContent,
CodeBlockItem,
} from "@/components/ai-elements/code-block"
export function CodeBlockNoHeaderDemo() {
const codeData = [
{
language: "jsx",
filename: "MyComponent.jsx",
code: `function MyComponent(props) {
return (
<div>
<h1>Hello, {props.name}!</h1>
<p>This is an example React component.</p>
</div>
);
}`,
},
]
return (
<CodeBlock data={codeData} defaultValue="jsx">
<CodeBlockBody>
{(item) => (
<CodeBlockItem key={item.language} value={item.language}>
<CodeBlockContent language={item.language as any}>
{item.code}
</CodeBlockContent>
</CodeBlockItem>
)}
</CodeBlockBody>
</CodeBlock>
)
}
<CodeBlock data={codeData} defaultValue="jsx">
<CodeBlockBody>
{(item) => (
<CodeBlockItem key={item.language} value={item.language}>
<CodeBlockContent language={item.language}>
{item.code}
</CodeBlockContent>
</CodeBlockItem>
)}
</CodeBlockBody>
</CodeBlock>Highlighted Lines
MyComponent.jsx
function MyComponent(props) { // [!code highlight] return ( <div> <h1>Hello, {props.name}!</h1> // [!code highlight] <p>This is an example React component.</p> </div> );}"use client"
import {
CodeBlock,
CodeBlockBody,
CodeBlockContent,
CodeBlockCopyButton,
CodeBlockFilename,
CodeBlockHeader,
CodeBlockItem,
} from "@/components/ai-elements/code-block"
export function CodeBlockHighlightDemo() {
const codeData = [
{
language: "jsx",
filename: "MyComponent.jsx",
code: `function MyComponent(props) { // [!code highlight]
return (
<div>
<h1>Hello, {props.name}!</h1> // [!code highlight]
<p>This is an example React component.</p>
</div>
);
}`,
},
]
return (
<CodeBlock data={codeData} defaultValue="jsx">
<CodeBlockHeader>
<CodeBlockFilename value="jsx">
{codeData[0].filename}
</CodeBlockFilename>
<CodeBlockCopyButton />
</CodeBlockHeader>
<CodeBlockBody>
{(item) => (
<CodeBlockItem key={item.language} value={item.language}>
<CodeBlockContent language={item.language as any}>
{item.code}
</CodeBlockContent>
</CodeBlockItem>
)}
</CodeBlockBody>
</CodeBlock>
)
}
Add // [!code highlight] at the end of lines you want to highlight.
const code = `function MyComponent(props) { // [!code highlight]
return (
<div>
<h1>Hello, {props.name}!</h1> // [!code highlight]
<p>This is an example React component.</p>
</div>
);
}`Highlighted Words
MyComponent.jsx
function MyComponent(props) { return ( <div> // [!code word:props.name] <h1>Hello, {props.name}!</h1> <p>This is an example React component.</p> </div> );}"use client"
import {
CodeBlock,
CodeBlockBody,
CodeBlockContent,
CodeBlockCopyButton,
CodeBlockFilename,
CodeBlockHeader,
CodeBlockItem,
} from "@/components/ai-elements/code-block"
export function CodeBlockHighlightWordDemo() {
const codeData = [
{
language: "jsx",
filename: "MyComponent.jsx",
code: `function MyComponent(props) {
return (
<div>
// [!code word:props.name]
<h1>Hello, {props.name}!</h1>
<p>This is an example React component.</p>
</div>
);
}`,
},
]
return (
<CodeBlock data={codeData} defaultValue="jsx">
<CodeBlockHeader>
<CodeBlockFilename value="jsx">
{codeData[0].filename}
</CodeBlockFilename>
<CodeBlockCopyButton />
</CodeBlockHeader>
<CodeBlockBody>
{(item) => (
<CodeBlockItem key={item.language} value={item.language}>
<CodeBlockContent language={item.language as any}>
{item.code}
</CodeBlockContent>
</CodeBlockItem>
)}
</CodeBlockBody>
</CodeBlock>
)
}
Add // [!code word:text] to highlight specific words in your code.
const code = `function MyComponent(props) {
return (
<div>
// [!code word:props.name]
<h1>Hello, {props.name}!</h1>
<p>This is an example React component.</p>
</div>
);
}`Diff
utils.js
function calculateTotal(items) { let total = 0; for (let i = 0; i < items.length; i++) { total += items[i].price * items[i].quantity; // [!code --] const itemTotal = items[i].price * items[i].quantity; // [!code ++] total += itemTotal; // [!code ++] } return total;}"use client"
import {
CodeBlock,
CodeBlockBody,
CodeBlockContent,
CodeBlockCopyButton,
CodeBlockFilename,
CodeBlockHeader,
CodeBlockItem,
} from "@/components/ai-elements/code-block"
export function CodeBlockDiffDemo() {
const codeData = [
{
language: "javascript",
filename: "utils.js",
code: `function calculateTotal(items) {
let total = 0;
for (let i = 0; i < items.length; i++) {
total += items[i].price * items[i].quantity; // [!code --]
const itemTotal = items[i].price * items[i].quantity; // [!code ++]
total += itemTotal; // [!code ++]
}
return total;
}`,
},
]
return (
<CodeBlock data={codeData} defaultValue="javascript">
<CodeBlockHeader>
<CodeBlockFilename value="javascript">
{codeData[0].filename}
</CodeBlockFilename>
<CodeBlockCopyButton />
</CodeBlockHeader>
<CodeBlockBody>
{(item) => (
<CodeBlockItem key={item.language} value={item.language}>
<CodeBlockContent language={item.language as any}>
{item.code}
</CodeBlockContent>
</CodeBlockItem>
)}
</CodeBlockBody>
</CodeBlock>
)
}
Use // [!code --] for deletions and // [!code ++] for additions.
const code = `function calculateTotal(items) {
let total = 0;
for (let i = 0; i < items.length; i++) {
total += items[i].price * items[i].quantity; // [!code --]
const itemTotal = items[i].price * items[i].quantity; // [!code ++]
total += itemTotal; // [!code ++]
}
return total;
}`Focus
utils.js
function calculateDiscount(price, percentage) { const discount = price * (percentage / 100); // [!code focus] return price - discount;}// Example usageconst finalPrice = calculateDiscount(100, 20);console.log(finalPrice); // 80"use client"
import {
CodeBlock,
CodeBlockBody,
CodeBlockContent,
CodeBlockCopyButton,
CodeBlockFilename,
CodeBlockHeader,
CodeBlockItem,
} from "@/components/ai-elements/code-block"
export function CodeBlockFocusDemo() {
const codeData = [
{
language: "javascript",
filename: "utils.js",
code: `function calculateDiscount(price, percentage) {
const discount = price * (percentage / 100); // [!code focus]
return price - discount;
}
// Example usage
const finalPrice = calculateDiscount(100, 20);
console.log(finalPrice); // 80`,
},
]
return (
<CodeBlock data={codeData} defaultValue="javascript">
<CodeBlockHeader>
<CodeBlockFilename value="javascript">
{codeData[0].filename}
</CodeBlockFilename>
<CodeBlockCopyButton />
</CodeBlockHeader>
<CodeBlockBody>
{(item) => (
<CodeBlockItem key={item.language} value={item.language}>
<CodeBlockContent language={item.language as any}>
{item.code}
</CodeBlockContent>
</CodeBlockItem>
)}
</CodeBlockBody>
</CodeBlock>
)
}
Use // [!code focus] to focus on specific lines while blurring the rest.
const code = `function calculateDiscount(price, percentage) {
const discount = price * (percentage / 100); // [!code focus]
return price - discount;
}
// Example usage
const finalPrice = calculateDiscount(100, 20);
console.log(finalPrice); // 80`Hidden Line Numbers
MyComponent.jsx
function MyComponent(props) { return ( <div> <h1>Hello, {props.name}!</h1> <p>This is an example React component.</p> </div> );}"use client"
import {
CodeBlock,
CodeBlockBody,
CodeBlockContent,
CodeBlockCopyButton,
CodeBlockFilename,
CodeBlockHeader,
CodeBlockItem,
} from "@/components/ai-elements/code-block"
export function CodeBlockNoLineNumbersDemo() {
const codeData = [
{
language: "jsx",
filename: "MyComponent.jsx",
code: `function MyComponent(props) {
return (
<div>
<h1>Hello, {props.name}!</h1>
<p>This is an example React component.</p>
</div>
);
}`,
},
]
return (
<CodeBlock data={codeData} defaultValue="jsx">
<CodeBlockHeader>
<CodeBlockFilename value="jsx">
{codeData[0].filename}
</CodeBlockFilename>
<CodeBlockCopyButton />
</CodeBlockHeader>
<CodeBlockBody>
{(item) => (
<CodeBlockItem
key={item.language}
value={item.language}
lineNumbers={false}
>
<CodeBlockContent language={item.language as any}>
{item.code}
</CodeBlockContent>
</CodeBlockItem>
)}
</CodeBlockBody>
</CodeBlock>
)
}
Set lineNumbers={false} on the CodeBlockItem component.
<CodeBlockItem key={item.language} value={item.language} lineNumbers={false}>
<CodeBlockContent language={item.language}>
{item.code}
</CodeBlockContent>
</CodeBlockItem>No Syntax Highlighting
MyComponent.jsx
function MyComponent(props) { return ( <div> <h1>Hello, {props.name}!</h1> <p>This is an example React component.</p> </div> );}"use client"
import {
CodeBlock,
CodeBlockBody,
CodeBlockContent,
CodeBlockCopyButton,
CodeBlockFilename,
CodeBlockHeader,
CodeBlockItem,
} from "@/components/ai-elements/code-block"
export function CodeBlockNoSyntaxDemo() {
const codeData = [
{
language: "jsx",
filename: "MyComponent.jsx",
code: `function MyComponent(props) {
return (
<div>
<h1>Hello, {props.name}!</h1>
<p>This is an example React component.</p>
</div>
);
}`,
},
]
return (
<CodeBlock data={codeData} defaultValue="jsx">
<CodeBlockHeader>
<CodeBlockFilename value="jsx">
{codeData[0].filename}
</CodeBlockFilename>
<CodeBlockCopyButton />
</CodeBlockHeader>
<CodeBlockBody>
{(item) => (
<CodeBlockItem key={item.language} value={item.language}>
<CodeBlockContent
language={item.language as any}
syntaxHighlighting={false}
>
{item.code}
</CodeBlockContent>
</CodeBlockItem>
)}
</CodeBlockBody>
</CodeBlock>
)
}
Set syntaxHighlighting={false} on the CodeBlockContent component.
<CodeBlockContent language={item.language} syntaxHighlighting={false}>
{item.code}
</CodeBlockContent>Custom Theme
MyComponent.jsx
function MyComponent(props) { return ( <div> <h1>Hello, {props.name}!</h1> <p>This is an example React component.</p> </div> );}"use client"
import {
CodeBlock,
CodeBlockBody,
CodeBlockContent,
CodeBlockCopyButton,
CodeBlockFilename,
CodeBlockHeader,
CodeBlockItem,
} from "@/components/ai-elements/code-block"
export function CodeBlockCustomThemeDemo() {
const codeData = [
{
language: "jsx",
filename: "MyComponent.jsx",
code: `function MyComponent(props) {
return (
<div>
<h1>Hello, {props.name}!</h1>
<p>This is an example React component.</p>
</div>
);
}`,
},
]
return (
<CodeBlock data={codeData} defaultValue="jsx">
<CodeBlockHeader>
<CodeBlockFilename value="jsx">
{codeData[0].filename}
</CodeBlockFilename>
<CodeBlockCopyButton />
</CodeBlockHeader>
<CodeBlockBody>
{(item) => (
<CodeBlockItem key={item.language} value={item.language}>
<CodeBlockContent
language={item.language as any}
themes={{
light: "vitesse-light",
dark: "vitesse-dark",
}}
>
{item.code}
</CodeBlockContent>
</CodeBlockItem>
)}
</CodeBlockBody>
</CodeBlock>
)
}
Pass custom themes to the CodeBlockContent component using the themes prop.
<CodeBlockContent
language={item.language}
themes={{
light: "vitesse-light",
dark: "vitesse-dark",
}}
>
{item.code}
</CodeBlockContent>Multiple Files
Button.tsx
import { type ReactNode } from "react"interface ButtonProps { children: ReactNode onClick?: () => void variant?: "primary" | "secondary"}export function Button({ children, onClick, variant = "primary" }: ButtonProps) { return ( <button onClick={onClick} className={`btn btn-${variant}`} > {children} </button> )}"use client"
import {
CodeBlock,
CodeBlockBody,
CodeBlockContent,
CodeBlockCopyButton,
CodeBlockFilename,
CodeBlockFiles,
CodeBlockHeader,
CodeBlockItem,
CodeBlockSelect,
CodeBlockSelectItem,
} from "@/components/ai-elements/code-block"
export function CodeBlockMultipleFilesDemo() {
const codeData = [
{
language: "typescript",
filename: "Button.tsx",
code: `import { type ReactNode } from "react"
interface ButtonProps {
children: ReactNode
onClick?: () => void
variant?: "primary" | "secondary"
}
export function Button({ children, onClick, variant = "primary" }: ButtonProps) {
return (
<button
onClick={onClick}
className={\`btn btn-\${variant}\`}
>
{children}
</button>
)
}`,
},
{
language: "typescript",
filename: "Input.tsx",
code: `import { type InputHTMLAttributes } from "react"
interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
label?: string
error?: string
}
export function Input({ label, error, ...props }: InputProps) {
return (
<div className="input-wrapper">
{label && <label>{label}</label>}
<input {...props} />
{error && <span className="error">{error}</span>}
</div>
)
}`,
},
{
language: "css",
filename: "styles.css",
code: `.btn {
padding: 0.5rem 1rem;
border-radius: 0.375rem;
font-weight: 500;
transition: all 0.2s;
}
.btn-primary {
background-color: #3b82f6;
color: white;
}
.btn-secondary {
background-color: #6b7280;
color: white;
}`,
},
]
return (
<CodeBlock data={codeData} defaultValue={codeData[0].filename}>
<CodeBlockHeader>
<CodeBlockFiles>
{(item) => (
<CodeBlockFilename key={item.filename} value={item.filename}>
{item.filename}
</CodeBlockFilename>
)}
</CodeBlockFiles>
<CodeBlockSelect>
{(item) => (
<CodeBlockSelectItem key={item.filename} id={item.filename}>
{item.filename}
</CodeBlockSelectItem>
)}
</CodeBlockSelect>
<CodeBlockCopyButton
onCopy={() => console.log("Copied code to clipboard")}
onError={() => console.error("Failed to copy code to clipboard")}
/>
</CodeBlockHeader>
<CodeBlockBody>
{(item) => (
<CodeBlockItem key={item.filename} value={item.filename}>
<CodeBlockContent language={item.language as any}>
{item.code}
</CodeBlockContent>
</CodeBlockItem>
)}
</CodeBlockBody>
</CodeBlock>
)
}
Use CodeBlockSelect to switch between multiple files.
const codeData = [
{
language: "typescript",
filename: "Button.tsx",
code: `...`,
},
{
language: "typescript",
filename: "Input.tsx",
code: `...`,
},
{
language: "css",
filename: "styles.css",
code: `...`,
},
]
<CodeBlock data={codeData} defaultValue="typescript">
<CodeBlockHeader>
<CodeBlockSelect>
{(item) => (
<CodeBlockSelectItem key={item.language} id={item.language}>
{item.filename}
</CodeBlockSelectItem>
)}
</CodeBlockSelect>
<CodeBlockCopyButton />
</CodeBlockHeader>
<CodeBlockBody>
{(item) => (
<CodeBlockItem key={item.language} value={item.language}>
<CodeBlockContent language={item.language}>
{item.code}
</CodeBlockContent>
</CodeBlockItem>
)}
</CodeBlockBody>
</CodeBlock>