CodeBlock
A syntax-highlighted code block component with copy functionality and tab support for displaying code examples.
Usage
Basic Code Block
```tsx
const greeting = "Hello, World!";
console.log(greeting);
```With Title and Icon
```tsx title="config.js"
export function main() {
console.log("Starting application...");
}
```Live Example:
export function main() {'{'}
console.log("Starting application...");Code Block with Tabs
Use tabs to show code examples in different languages or contexts:
```ts tab="Typescript" title="example.ts"
const greeting: string = "Hello, World with ts!";
console.log(greeting);
```
```ts tab="Javascript" title="example.js"
const greeting = "Hello, World with js!";
console.log(greeting);
```const greeting: string = "Hello, World with ts!";
console.log(greeting);With Line Numbers
import { CodeBlock, Pre } from "@prisma-docs/eclipse";
export function LineNumbersCodeBlock() {
return (
<CodeBlock
title="counter.ts"
data-line-numbers
data-line-numbers-start={1}
>
<Pre>
<code>
let count = 0;
function increment() {'{'}
count++;
console.log(count);
{'}'}
increment();
</code>
</Pre>
</CodeBlock>
);
}let count = 0;
function increment() {
count++;
console.log(count);
}
increment();Keep Original Background
When using syntax highlighters like Shiki, preserve the theme colors:
import { CodeBlock, Pre } from "@prisma-docs/eclipse";
export function ThemedCodeBlock() {
return (
<CodeBlock
title="themed.tsx"
keepBackground={true}
>
<Pre>
<code className="language-tsx">
// Syntax highlighted code here
</code>
</Pre>
</CodeBlock>
);
}API Reference
CodeBlock
The main code block container with optional title bar and copy button.
Props:
title- Title displayed in the header (string, optional)icon- Icon shown next to the title (ReactNode | string, optional)allowCopy- Enable copy to clipboard button (boolean, default: true)keepBackground- Preserve syntax highlighter background (boolean, default: false)data-line-numbers- Show line numbers (boolean, optional)data-line-numbers-start- Starting line number (number, default: 1)viewportProps- Props passed to the scrollable viewport (HTMLAttributes, optional)Actions- Custom actions component (component, optional)className- Additional CSS classes (optional)- All standard HTML
<figure>attributes
Pre
Pre-formatted text wrapper for code content.
Props:
- All standard HTML
<pre>attributes className- Additional CSS classes (optional)
CodeBlockTabs
Container for tabbed code blocks.
Props:
defaultValue- Default active tab (string, optional)value- Controlled active tab (string, optional)onValueChange- Tab change callback ((value: string) => void, optional)className- Additional CSS classes (optional)- All Radix Tabs Root props
CodeBlockTabsList
Container for tab triggers.
Props:
className- Additional CSS classes (optional)- All standard HTML attributes
CodeBlockTabsTrigger
Individual tab trigger button.
Props:
value- Tab identifier (string, required)children- Tab label content (ReactNode, required)className- Additional CSS classes (optional)- All Radix Tabs Trigger props
CodeBlockTab
Content panel for a code block tab.
Props:
value- Tab identifier matching trigger (string, required)className- Additional CSS classes (optional)- All Radix Tabs Content props
Features
- ✅ Syntax highlighting support (via Shiki/Rehype)
- ✅ Copy to clipboard functionality
- ✅ Optional title bar with icons
- ✅ Line numbers support
- ✅ Tab interface for multiple code examples
- ✅ Scrollable viewport with max height
- ✅ Keyboard accessible
- ✅ Eclipse design system styling
- ✅ Built on Fumadocs UI patterns
- ✅ Custom actions support
Best Practices
- Use descriptive titles that indicate the file or context
- Include file extensions in titles for clarity (e.g., "index.ts", "App.jsx")
- Use tabs when showing the same functionality in different languages
- Enable line numbers for longer code examples or when referencing specific lines
- Set
allowCopy={false}only when copying doesn't make sense (e.g., example output) - Use
keepBackgroundwhen you want to preserve syntax theme colors - Keep code examples concise and focused on the concept being explained
- Add comments in code to explain complex logic
- Test that the copy button works correctly with your code content
Common Use Cases
API Examples
<CodeBlockTabs defaultValue="curl">
<CodeBlockTabsList>
<CodeBlockTabsTrigger value="curl">cURL</CodeBlockTabsTrigger>
<CodeBlockTabsTrigger value="javascript">JavaScript</CodeBlockTabsTrigger>
</CodeBlockTabsList>
<CodeBlockTab value="curl">
<CodeBlock title="request.sh">
<Pre><code>curl -X POST https://api.example.com/data</code></Pre>
</CodeBlock>
</CodeBlockTab>
<CodeBlockTab value="javascript">
<CodeBlock title="request.js">
<Pre><code>fetch('https://api.example.com/data', {'{'} method: 'POST' {'}'})</code></Pre>
</CodeBlock>
</CodeBlockTab>
</CodeBlockTabs>Configuration Files
<CodeBlock title="package.json" icon="📦">
<Pre>
<code>
{'{'}
"name": "my-project",
"version": "1.0.0"
{'}'}
</code>
</Pre>
</CodeBlock>Tutorial Steps
<CodeBlock
title="step-1.ts"
data-line-numbers
data-line-numbers-start={1}
>
<Pre>
<code>
// Step 1: Initialize the client
const client = new Client();
</code>
</Pre>
</CodeBlock>Terminal Output
<CodeBlock title="Terminal" allowCopy={false}>
<Pre>
<code>
$ npm install prisma
✓ Installed successfully
</code>
</Pre>
</CodeBlock>Styling with Syntax Highlighters
The CodeBlock component works seamlessly with syntax highlighters:
With Shiki (Recommended)
import { codeToHtml } from 'shiki';
const html = await codeToHtml(code, {
lang: 'typescript',
theme: 'github-dark'
});
<CodeBlock title="example.ts" keepBackground>
<div dangerouslySetInnerHTML={{ __html: html }} />
</CodeBlock>With Rehype Code
```tsx title="example.ts"
const greeting = "Hello, World!";
console.log(greeting);
\```Accessibility
- Copy buttons have proper
aria-labelattributes - Keyboard navigation supported (Tab to focus, Enter/Space to activate)
- Code blocks are focusable and scrollable via keyboard
- Screen readers announce copy success/failure
- Semantic HTML structure with
<figure>,<figcaption>,<pre>, and<code> - Tab interface follows ARIA tabs pattern
Integration with Fumadocs
CodeBlock is designed to work seamlessly with Fumadocs MDX:
---
title: My Documentation Page
---
Here's a code example:
```typescript title="example.ts"
const greeting = "Hello, World!";
console.log(greeting);
\```
Or with tabs:
```typescript tab="TypeScript" title="example.ts"
const greeting: string = "Hello, World!";
\```
```javascript tab="JavaScript" title="example.js"
const greeting = "Hello, World!";
\```Custom Actions
You can customize the actions area in the code block header:
import { CodeBlock, Pre } from "@prisma-docs/eclipse";
import { Download } from "lucide-react";
export function CustomActionsCodeBlock() {
return (
<CodeBlock
title="config.json"
Actions={({ className, children }) => (
<div className={className}>
{children}
<button aria-label="Download">
<Download className="size-4" />
</button>
</div>
)}
>
<Pre>
<code>{'{ "config": "value" }'}</code>
</Pre>
</CodeBlock>
);
}