Code Block
Code blocks display, copy, and edit source code in common programming languages.
import { useState } from "react"
import { Check, Copy } from "lucide-react"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
const code = `const journeys = await atlas.search({
region: "western-ghats",
season: "monsoon",
difficulty: "moderate",
})
return journeys.filter((journey) => journey.isOpen)`
export default function ReadOnlyCodeBlock() {
const [copied, setCopied] = useState(false)
const copyCode = async () => {
await navigator.clipboard.writeText(code)
setCopied(true)
window.setTimeout(() => setCopied(false), 1600)
}
return (
<section className="mx-auto max-w-3xl overflow-hidden rounded-lg border bg-card shadow-sm">
<header className="flex items-center justify-between gap-4 border-b px-4 py-2.5">
<div className="flex items-center gap-2">
<span className="text-sm font-medium">search.ts</span>
<Badge variant="secondary">TypeScript</Badge>
</div>
<Button variant="ghost" size="icon-sm" onClick={copyCode} aria-label="Copy code">
{copied ? <Check /> : <Copy />}
</Button>
</header>
<pre className="overflow-x-auto p-5 text-sm leading-6" aria-label="TypeScript code example">
<code>{code}</code>
</pre>
</section>
)
}
import { useState } from "react"
import { Field, FieldLabel } from "@/components/ui/field"
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
import { Textarea } from "@/components/ui/textarea"
const examples = {
javascript: `const greeting = "Hello, world!"\nconsole.log(greeting)`,
python: `greeting = "Hello, world!"\nprint(greeting)`,
java: `class Main {\n public static void main(String[] args) {\n System.out.println("Hello, world!");\n }\n}`,
cpp: `#include <iostream>\n\nint main() {\n std::cout << "Hello, world!";\n return 0;\n}`,
plaintext: `Hello, world!`,
}
type Language = keyof typeof examples
export default function EditableCodeBlock() {
const [language, setLanguage] = useState<Language>("javascript")
const [value, setValue] = useState(examples.javascript)
const changeLanguage = (nextLanguage: Language) => {
setLanguage(nextLanguage)
setValue(examples[nextLanguage])
}
return (
<section className="mx-auto max-w-3xl overflow-hidden rounded-lg border bg-card shadow-sm">
<header className="flex flex-wrap items-center justify-between gap-3 border-b px-4 py-3">
<Select value={language} onValueChange={(value) => changeLanguage(value as Language)}>
<SelectTrigger className="w-40" aria-label="Programming language">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectItem value="javascript">JavaScript</SelectItem>
<SelectItem value="python">Python</SelectItem>
<SelectItem value="java">Java</SelectItem>
<SelectItem value="cpp">C++</SelectItem>
<SelectItem value="plaintext">Plain text</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
<p className="text-xs text-muted-foreground">Editable</p>
</header>
<Field className="gap-0">
<FieldLabel htmlFor="code-editor" className="sr-only">Code editor</FieldLabel>
<Textarea
id="code-editor"
value={value}
onChange={(event) => setValue(event.target.value)}
spellCheck={false}
className="min-h-72 resize-y rounded-none border-0 bg-transparent p-5 font-mono text-sm leading-6 shadow-none focus-visible:ring-0"
/>
</Field>
<footer className="border-t px-4 py-2 text-xs text-muted-foreground">
Plain text editor · {value.split("\n").length} lines
</footer>
</section>
)
}
import { useState } from "react"
import { Check, Copy } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
const snippets = {
javascript: `fetch("https://api.example.com/trails")\n .then((response) => response.json())\n .then((data) => console.log(data))`,
python: `import requests\n\nresponse = requests.get("https://api.example.com/trails")\nprint(response.json())`,
curl: `curl --request GET \\\n --url https://api.example.com/trails \\\n --header 'Accept: application/json'`,
}
type Snippet = keyof typeof snippets
export default function MultiLanguageCodeBlock() {
const [language, setLanguage] = useState<Snippet>("javascript")
const [copied, setCopied] = useState(false)
const copyCode = async () => {
await navigator.clipboard.writeText(snippets[language])
setCopied(true)
window.setTimeout(() => setCopied(false), 1600)
}
return (
<section className="mx-auto max-w-3xl overflow-hidden rounded-lg border bg-card shadow-sm">
<Tabs value={language} onValueChange={(value) => setLanguage(value as Snippet)}>
<header className="flex items-center justify-between gap-3 border-b px-3 py-2">
<TabsList>
<TabsTrigger value="javascript">JavaScript</TabsTrigger>
<TabsTrigger value="python">Python</TabsTrigger>
<TabsTrigger value="curl">cURL</TabsTrigger>
</TabsList>
<Button variant="ghost" size="icon-sm" onClick={copyCode} aria-label="Copy code">
{copied ? <Check /> : <Copy />}
</Button>
</header>
{(Object.keys(snippets) as Snippet[]).map((key) => (
<TabsContent key={key} value={key} className="m-0">
<pre className="overflow-x-auto p-5 text-sm leading-6" aria-label={`${key} code example`}>
<code>{snippets[key]}</code>
</pre>
</TabsContent>
))}
</Tabs>
</section>
)
}