Code Block
A syntax-highlighted code block with file header, copy button, optional line numbers and light/dark Shiki themes.
Preview
app/api/mcp/route.ts
import { z } from 'zod';
import { createMcpHandler } from 'mcp-handler';
const handler = createMcpHandler(
(server) => {
server.tool(
'roll_dice',
'Rolls an N-sided die',
{ sides: z.number().int().min(2) },
async ({ sides }) => {
const value = 1 + Math.floor(Math.random() * sides);
return {
content: [{ type: 'text', text: `🎲 You rolled a 10!` }],
};
},
);
},
{},
{ basePath: '/api' },
);
pages/index.tsx
import { useChat } from '@ai-sdk/react';
import { useState } from 'react';
export default function Chat() {
const [input, setInput] = useState('');
const { messages, sendMessage } = useChat();
return (
<div className="flex flex-col w-full max-w-md py-24 mx-auto stretch">
{messages.map(message => (
<div key={message.id} className="whitespace-pre-wrap">
{message.role === 'user' ? 'User: ' : 'AI: '}
{message.parts.map((part, i) => {
switch (part.type) {
case 'text':
return <div>{part.text}</div>;
}
})}
</div>
))}
<form
onSubmit={e => {
e.preventDefault();
sendMessage({ text: input });
setInput('');
}}
>
<input
className="fixed dark:bg-zinc-900 bottom-0 w-full max-w-md p-2 mb-8 border border-zinc-300 dark:border-zinc-800 rounded shadow-xl"
value={input}
placeholder="Say something..."
onChange={e => setInput(e.currentTarget.value)}
/>
</form>
</div>
);
}
Installation
- 1
Run the following command
npx shadcn@latest add https://localhostui.com/r/code-block.json
Props
| Prop | Type | Default | Description |
|---|---|---|---|
code* | string | — | The raw source code to display and highlight. |
fileName | string | "app/api/mcp/route.ts" | File path or name shown in the header next to the language icon. |
language | string | "tsx" | Shiki language id used for highlighting (e.g. "ts", "tsx", "bash", "json"). Also picks the header icon. Unknown languages fall back to plain text. |
showLineNumbers | boolean | false | Toggles a line-number gutter alongside the code. |
lightTheme | string | "github-light" | Shiki theme used in light mode. |
darkTheme | string | "github-dark" | Shiki theme used in dark mode. Both themes are rendered at once, so switching themes never flickers. |
width | string | number | "100%" | Width of the component. Numbers are pixels; strings are used as-is (e.g. "100%", "40rem"). Never overflows its parent. |
height | string | number | "auto" | Height of the component. Numbers are pixels; strings are used as-is (e.g. "auto", "60vh"). |