Code block

Code in a reply, with the file name, line numbers, marked lines and a copy button.

Loading preview…

Install

  1. 1

    Run this command in your Tailwind CSS project. It adds components/ai/code-block-default.tsx and installs its dependencies.

    $ npx shadcn@latest add https://gradientdeck.com/ai-components/r/code-block-default.json

Usage & API

Example

code-block-default.tsx
import { CopyButton } from "@/components/ai/code-block-default"

<CopyButton
  text="…"
/>

Props CopyButton

PropType & descriptionRequired
textstringRequired

Dependencies

  • React
  • Tailwind CSS
  • motion
  • lucide-react
Implementation notes

Single file is a figure. The caption has a file icon, the filename in a mono face, an uppercase language badge, and Copy, which becomes Copied with a check for about a second and a half. The sample file is app/api/signup/route.ts, language ts. The body is a POST handler that reads x-forwarded-for, checks a limiter, returns 429 with Too many requests when the check fails, then reads an email, creates a user and returns 201. Lines 6 through 9 are marked, which is the limiter check, the if, the 429 return and the closing brace. Line numbers stay on. Copy writes that whole string, including the unmarked lines and the comment about the welcome email.

Choosing a layout

Use the single file when the answer contains one snippet and the filename is part of the meaning, such as a route handler the person asked for. Pass highlight for the lines the reply is actually talking about, so the eye lands there without you describing line numbers in the prose. Turn line numbers off only when the snippet is a fragment with no stable numbering. Use the tabs when the answer is several files that belong together, a worker, the module it imports, and the env keys it expects. Keeping them in one card means copy always matches the file on screen.

A diff is the better fit when the code is a change against a file the person already has and each hunk should be accepted or rejected. A file tree is the better fit when the point is which paths were added, modified or deleted, not the source itself. Test results are the better fit when the thing to show is a run, with pass and fail counts and an error for what failed. An artifact panel is the better fit when the same artifact should also have a visual preview and a version list. The code block does not try to be those.

Does Copy include only the marked lines?

No. The button writes the whole code string for that file. Highlight only changes the border, the background and the gutter colour. In the tabbed block, Copy writes the active file and ignores the others. Switching tabs resets the button so it does not keep saying Copied for a file you are no longer looking at.

Will the colours be right for every language?

No. The highlighter is a set of regular expressions for comments, strings, a few keywords, numbers, function calls and capitalised words. It is enough for the TypeScript samples and for a short env file. It is not a grammar. If you need faithful highlighting for a language those patterns miss, pass the text through your own pass before render, or accept that unknown tokens stay in the body colour.