Code Block
Display formatted code snippets with syntax highlighting and copy functionality.
Default
A standard code block with language label and copy button.
function greet(name) {
return `Hello, ${name}!`;
}
const message = greet("World");
console.log(message);
<div class="vt-rounded-lg vt-bg-surface-subtle vt-overflow-hidden">
<div class="vt-code-header">
<span class="vt-text-xs vt-text-foreground-muted">javascript</span>
<button class="copy-btn vt-p-1 vt-rounded vt-hover:bg-surface-subtle vt-transition-colors vt-text-foreground-muted vt-hover:text-foreground-primary" aria-label="Copy code">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-copy vt-w-4 vt-h-4">
<rect width="14" height="14" x="8" y="8" rx="2" ry="2"></rect><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"></path>
</svg>
</button>
</div>
<div class="vt-p-4">
<pre class="vt-font-mono vt-text-sm vt-text-foreground-primary"><code>function greet(name) {
return `Hello, ${name}!`;
}
const message = greet("World");
console.log(message);</code></pre>
</div>
</div>
With Line Numbers
Code block with line numbers for easier reference.
1 interface User { 2 id: string; 3 name: string; 4 email: string; 5 role: "admin" | "user"; 6 } 7 8 function getUser(id: string): User { 9 return fetchUser(id); 10 }
<div class="vt-rounded-lg vt-bg-surface-subtle vt-overflow-hidden">
<div class="vt-code-header">
<span class="vt-text-xs vt-text-foreground-muted">typescript</span>
<button class="copy-btn vt-p-1 vt-rounded vt-hover:bg-surface-subtle vt-transition-colors vt-text-foreground-muted vt-hover:text-foreground-primary" aria-label="Copy code">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-copy vt-w-4 vt-h-4">
<rect width="14" height="14" x="8" y="8" rx="2" ry="2"></rect><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"></path>
</svg>
</button>
</div>
<div class="vt-p-4">
<pre class="vt-font-mono vt-text-sm vt-text-foreground-primary"><code><table class="vt-border-collapse vt-w-full"><tbody><tr><td class="vt-text-foreground-muted vt-text-right vt-pr-4 vt-select-none vt-border-r vt-border-border-default vt-w-8 vt-align-top">1</td><td class="vt-pl-4">interface User {</td></tr><tr><td class="vt-text-foreground-muted vt-text-right vt-pr-4 vt-select-none vt-border-r vt-border-border-default vt-w-8 vt-align-top">2</td><td class="vt-pl-4"> id: string;</td></tr><tr><td class="vt-text-foreground-muted vt-text-right vt-pr-4 vt-select-none vt-border-r vt-border-border-default vt-w-8 vt-align-top">3</td><td class="vt-pl-4"> name: string;</td></tr><tr><td class="vt-text-foreground-muted vt-text-right vt-pr-4 vt-select-none vt-border-r vt-border-border-default vt-w-8 vt-align-top">4</td><td class="vt-pl-4"> email: string;</td></tr><tr><td class="vt-text-foreground-muted vt-text-right vt-pr-4 vt-select-none vt-border-r vt-border-border-default vt-w-8 vt-align-top">5</td><td class="vt-pl-4"> role: "admin" | "user";</td></tr><tr><td class="vt-text-foreground-muted vt-text-right vt-pr-4 vt-select-none vt-border-r vt-border-border-default vt-w-8 vt-align-top">6</td><td class="vt-pl-4">}</td></tr><tr><td class="vt-text-foreground-muted vt-text-right vt-pr-4 vt-select-none vt-border-r vt-border-border-default vt-w-8 vt-align-top">7</td><td class="vt-pl-4"></td></tr><tr><td class="vt-text-foreground-muted vt-text-right vt-pr-4 vt-select-none vt-border-r vt-border-border-default vt-w-8 vt-align-top">8</td><td class="vt-pl-4">function getUser(id: string): User {</td></tr><tr><td class="vt-text-foreground-muted vt-text-right vt-pr-4 vt-select-none vt-border-r vt-border-border-default vt-w-8 vt-align-top">9</td><td class="vt-pl-4"> return fetchUser(id);</td></tr><tr><td class="vt-text-foreground-muted vt-text-right vt-pr-4 vt-select-none vt-border-r vt-border-border-default vt-w-8 vt-align-top">10</td><td class="vt-pl-4">}</td></tr></tbody></table></code></pre>
</div>
</div>
With Highlighted Lines
Highlight specific lines to draw attention to important code.
<div class="vt-rounded-lg vt-bg-surface-subtle vt-overflow-hidden">
<div class="vt-code-header">
<span class="vt-text-xs vt-text-foreground-muted">javascript</span>
<button class="copy-btn vt-p-1 vt-rounded vt-hover:bg-surface-subtle vt-transition-colors vt-text-foreground-muted vt-hover:text-foreground-primary" aria-label="Copy code">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-copy vt-w-4 vt-h-4">
<rect width="14" height="14" x="8" y="8" rx="2" ry="2"></rect><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"></path>
</svg>
</button>
</div>
<div class="vt-font-mono vt-text-sm vt-text-foreground-primary"><div class="vt-px-4 vt-py-0.5">const app = express();</div><div class="vt-px-4 vt-py-0.5"></div><div class="vt-px-4 vt-py-0.5 vt-bg-info-fill/5 vt-border-l-2 vt-border-info-fill">app.get("/api/users", (req, res) => {</div><div class="vt-px-4 vt-py-0.5 vt-bg-info-fill/5 vt-border-l-2 vt-border-info-fill"> const users = db.getUsers();</div><div class="vt-px-4 vt-py-0.5 vt-bg-info-fill/5 vt-border-l-2 vt-border-info-fill"> res.json(users);</div><div class="vt-px-4 vt-py-0.5">});</div><div class="vt-px-4 vt-py-0.5"></div><div class="vt-px-4 vt-py-0.5">app.listen(3000);</div></div>
</div>
Inline Code
Use inline code for short code references within text.
Use const for variables that won't be reassigned, and
let for variables that will change.
Import components with import Button from './Button' to use them in your templates.
The function returns Promise<User[]> which resolves to an array of user objects.
You can handle errors using try...catch blocks or the
.catch() method.
Run npm install to install dependencies, then
npm run dev to start the development server on
localhost:3000.
<div class="vt-space-y-4 vt-text-sm vt-text-foreground-primary vt-leading-relaxed">
<p>
Use <code class="vt-code-inline">const</code> for variables that won't be reassigned, and
<code class="vt-code-inline">let</code> for variables that will change.
</p>
<p>
Import components with <code class="vt-code-inline">import Button from './Button'</code> to use them in your templates.
</p>
<p>
The function returns <code class="vt-code-inline">Promise<User[]></code> which resolves to an array of user objects.
You can handle errors using <code class="vt-code-inline">try...catch</code> blocks or the
<code class="vt-code-inline">.catch()</code> method.
</p>
<p>
Run <code class="vt-code-inline">npm install</code> to install dependencies, then
<code class="vt-code-inline">npm run dev</code> to start the development server on
<code class="vt-code-inline">localhost:3000</code>.
</p>
</div>
With Tabs
Switch between multiple languages or file variants.
function fibonacci(n) {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
console.log(fibonacci(10));
function fibonacci(n: number): number {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
console.log(fibonacci(10));
def fibonacci(n: int) -> int:
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
print(fibonacci(10))
<div class="vt-rounded-lg vt-bg-surface-subtle vt-overflow-hidden" id="code-tabs-block">
<div class="vt-flex vt-items-center vt-border-b vt-border-border-default">
<div class="vt-flex">
<button class="code-tab vt-px-4 vt-py-2 vt-text-xs vt-font-medium vt-bg-surface-card vt-text-foreground-primary vt-border-r vt-border-border-default" data-tab="js">JavaScript</button>
<button class="code-tab vt-px-4 vt-py-2 vt-text-xs vt-font-medium vt-text-foreground-muted vt-border-r vt-border-border-default vt-hover:text-foreground-primary vt-transition-colors" data-tab="ts">TypeScript</button>
<button class="code-tab vt-px-4 vt-py-2 vt-text-xs vt-font-medium vt-text-foreground-muted vt-border-r vt-border-border-default vt-hover:text-foreground-primary vt-transition-colors" data-tab="py">Python</button>
</div>
<div class="vt-ml-auto vt-pr-2">
<button class="copy-btn vt-p-1 vt-rounded vt-hover:bg-surface-subtle vt-transition-colors vt-text-foreground-muted vt-hover:text-foreground-primary" aria-label="Copy code">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-copy vt-w-4 vt-h-4">
<rect width="14" height="14" x="8" y="8" rx="2" ry="2"></rect><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"></path>
</svg>
</button>
</div>
</div>
<div class="vt-p-4">
<pre class="code-panel vt-font-mono vt-text-sm vt-text-foreground-primary" data-tab="js"><code>function fibonacci(n) {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
console.log(fibonacci(10));</code></pre>
<pre class="code-panel vt-font-mono vt-text-sm vt-text-foreground-primary vt-hidden" data-tab="ts"><code>function fibonacci(n: number): number {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
console.log(fibonacci(10));</code></pre>
<pre class="code-panel vt-font-mono vt-text-sm vt-text-foreground-primary vt-hidden" data-tab="py"><code>def fibonacci(n: int) -> int:
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
print(fibonacci(10))</code></pre>
</div>
</div>
Terminal
Terminal-style code block for CLI commands and output.
$ npm install
added 156 packages in 3.2s
$ npm run build
> my-app@1.0.0 build
> astro build
generating static routes
▶ src/pages/index.astro
▶ src/pages/about.astro
▶ src/pages/components/button.astro
✓ Completed in 1.24s
build complete!
<div class="vt-rounded-lg vt-bg-surface-subtle vt-overflow-hidden">
<div class="vt-code-header">
<div class="vt-flex vt-items-center vt-gap-2">
<div class="vt-flex vt-gap-1.5">
<span class="vt-w-3 vt-h-3 vt-rounded-full vt-bg-error-fill/50"></span>
<span class="vt-w-3 vt-h-3 vt-rounded-full vt-bg-warning-fill/50"></span>
<span class="vt-w-3 vt-h-3 vt-rounded-full vt-bg-info-fill/50"></span>
</div>
<span class="vt-text-xs vt-text-foreground-muted">terminal</span>
</div>
<button class="copy-btn vt-p-1 vt-rounded vt-hover:bg-surface-subtle vt-transition-colors vt-text-foreground-muted vt-hover:text-foreground-primary" aria-label="Copy code">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="lucide lucide-copy vt-w-4 vt-h-4">
<rect width="14" height="14" x="8" y="8" rx="2" ry="2"></rect><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"></path>
</svg>
</button>
</div>
<div class="vt-p-4">
<pre class="vt-font-mono vt-text-sm vt-text-foreground-primary"><code><span class="vt-text-info-fill">$ </span>npm install
<span class="vt-text-foreground-muted">added 156 packages in 3.2s</span>
<span class="vt-text-info-fill">$ </span>npm run build
<span class="vt-text-foreground-muted">> my-app@1.0.0 build
> astro build
generating static routes
▶ src/pages/index.astro
▶ src/pages/about.astro
▶ src/pages/components/button.astro
✓ Completed in 1.24s
build complete!</span></code></pre>
</div>
</div>
Guidelines
Present multi-line snippets in a block with a language label and copy action; keep short references inline.
function greet(name) {
return `Hello, ${name}!`;
}
const message = greet("World");
console.log(message);
Run const sum = a + b; const product = a * b; return sum + product; to compute the result.
Use const for values that never change, and let for ones that do.
const
API Reference
All CSS classes and data attributes.
| Class | Type | Description |
|---|---|---|
vt-code-header |
Base | Header bar above a code block — filename plus copy action |
vt-code-inline |
Base | Inline code fragment inside prose |
Accessibility
Keyboard and screen reader support.
| Feature | Details |
|---|---|
| Semantics | Code lives in pre + code elements so screen readers announce it as code |
| Copy action | The copy button carries an aria-label and announces success via its label swap |
| Scroll | Long code scrolls inside the block (overflow-x-auto) — the page never scrolls horizontally |