ComponentsCode Block

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

    Run the following command

    npx shadcn@latest add https://localhostui.com/r/code-block.json
    

Props

PropTypeDefaultDescription
code*string—The raw source code to display and highlight.
fileNamestring"app/api/mcp/route.ts"File path or name shown in the header next to the language icon.
languagestring"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.
showLineNumbersbooleanfalseToggles a line-number gutter alongside the code.
lightThemestring"github-light"Shiki theme used in light mode.
darkThemestring"github-dark"Shiki theme used in dark mode. Both themes are rendered at once, so switching themes never flickers.
widthstring | number"100%"Width of the component. Numbers are pixels; strings are used as-is (e.g. "100%", "40rem"). Never overflows its parent.
heightstring | number"auto"Height of the component. Numbers are pixels; strings are used as-is (e.g. "auto", "60vh").