Frontend Lab
← 回到所有模式
PD08📊 Data Display · 資料展示程式碼

Code Block

程式碼區塊

難度 ★★★★★標籤 code · highlight · 複製3 min read

模式簡述

Code Block:程式碼展示。語法 highlight + 複製按鈕。docs 站必備。

page.tsx
export default function Page() {
  return <h1>Hello</h1>
}
單檔|一段程式碼 + 複製

Claude Code Prompt

💬 Claude Code Prompt
參考:PD08 codeblock
組件:Codeblock.tsx

Code Block:程式碼展示。語法 highlight + 複製按鈕。docs 站必備。

限制:
- 沒複製按鈕
- copy 後沒反饋
- 語法 highlight 顏色太花

完整程式碼

Codeblock.tsx
"use client";
import { useEffect, useState } from "react";
import { Copy, Check } from "lucide-react";
import { cn } from "@/lib/utils";

type State = "single" | "tabs" | "diff";

const FILES = [
{ name: "page.tsx", code: `export default function Page() {
  return <h1>Hello</h1>
}` },
{ name: "layout.tsx", code: `export default function Layout({ children }) {
  return <div>{children}</div>
}` },
];

const DIFF = [
{ type: "ctx", line: `export default function Page() {` },
{ type: "del", line: `  return <h1>Hello</h1>` },
{ type: "add", line: `  return <h1>Hello, Lab</h1>` },
{ type: "add", line: `  // version 2` },
{ type: "ctx", line: `}` },
];

export function Codeblock({ state = "single" }: { state?: State }) {
const [active, setActive] = useState(0);
const [copied, setCopied] = useState(false);
useEffect(() => setActive(0), [state]);

return (
  <div className="w-full max-w-md overflow-hidden rounded-lg border border-border bg-[#0a0a0a] font-mono text-xs">
    <div className="flex items-center justify-between border-b border-border/60 bg-background/30 px-3 py-1.5">
      {state === "tabs" ? (
        <div className="flex gap-1">
          {FILES.map((f, i) => (
            <button
              key={f.name}
              onClick={() => setActive(i)}
              className={cn(
                "rounded-t px-2.5 py-1 text-[11px]",
                i === active
                  ? "bg-background text-foreground"
                  : "text-muted-foreground hover:text-foreground",
              )}
            >
              {f.name}
            </button>
          ))}
        </div>
      ) : (
        <span className="text-[11px] text-muted-foreground">
          {state === "diff" ? "page.tsx (diff)" : "page.tsx"}
        </span>
      )}
      <button
        onClick={() => {
          setCopied(true);
          setTimeout(() => setCopied(false), 1200);
        }}
        className="text-muted-foreground hover:text-foreground"
      >
        {copied ? <Check className="h-3 w-3 text-emerald-500" /> : <Copy className="h-3 w-3" />}
      </button>
    </div>
    <pre className="overflow-x-auto p-3 leading-relaxed">
      {state === "diff" ? (
        DIFF.map((l, i) => (
          <div
            key={i}
            className={cn(
              "px-1",
              l.type === "add" && "bg-emerald-500/10 text-emerald-400",
              l.type === "del" && "bg-red-500/10 text-red-400",
              l.type === "ctx" && "text-muted-foreground",
            )}
          >
            <span className="select-none opacity-60">
              {l.type === "add" ? "+ " : l.type === "del" ? "- " : "  "}
            </span>
            {l.line}
          </div>
        ))
      ) : (
        <code>{FILES[active].code}</code>
      )}
    </pre>
  </div>
);
}

何時用

  • ✅ 技術文件、blog
  • ✅ 教學步驟中的範例
  • ✅ API 回應、設定檔展示

何時別用

  • ❌ 極短的單行命令(用內聯 code 即可)
  • ❌ 需要編輯的 code(用 codemirror/monaco)
  • ❌ 需要執行的 code(接 sandbox)

我踩過的坑

  1. 沒複製按鈕:使用者要圈選文字超痛苦。右上角放 copy icon。

  2. copy 後沒反饋:點完不知道有沒有成功。秀「Copied!」2 秒。

  3. 語法 highlight 顏色太花:colorful 主題在 docs 太雜。用單色主題或 GitHub 系列。

相關模式

  • PA01

搜尋

按 ⌘K 隨時開啟