Conversation
Code Block
Code in an answer — filename, language, line numbers, wrap toggle, copy and collapse for long snippets.
2 variantsMIT
Preview
src/site/images.tsts
import { createCache } from "./cache";
// Resized images are keyed by content hash, so a changed file always misses.
export async function resize(src: string, width: number) {
const key = await hash(src, width);
const hit = await cache.get(key);
if (hit) return hit;
return cache.set(key, await sharp(src).resize(width).toBuffer());
}
Installation
Copies the component into components/ui and installs its dependencies and theme tokens.
pnpm dlx shadcn@latest add https://tuffui.com/r/code-block.jsonUsage
Pass your own data and wire the callbacks to your agent runtime.
import { CodeBlock } from "@/components/ui/code-block";
export function AnswerCode({ block }: { block: { code: string; lang: string; file?: string } }) {
return (
<CodeBlock
data={{ code: block.code, language: block.lang as "ts", filename: block.file }}
collapseAfter={16}
onCopy={() => analytics.track("code_copied")}
/>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
| data* | CodeBlockData | — | The code, its language, an optional filename and lines to highlight. |
| collapseAfter | number | 14 | Longer code collapses to this many lines behind a “Show all N lines” control. |
| showLineNumbers | boolean | true | Line numbers in a sticky gutter. |
| defaultWrap | boolean | false | Start with soft wrap on; the header toggle switches it. |
| onCopy | (code: string) => void | — | Called after the code is copied to the clipboard. |
| className | string | — | Extra classes for the shell. |
type CodeLanguage = "ts" | "tsx" | "js" | "json" | "bash" | "python" | "text";
type CodeBlockData = {
code: string;
language?: CodeLanguage; // drives the built-in tokenizer
filename?: string;
highlight?: number[]; // 1-based line numbers
};