CodeBlock
CodeBlock shows a snippet of source code in a dark frame with an optional header for a file name, a language label, custom actions and a copy-to-clipboard button.
import { CodeBlock } from 'jarvis-react-ui';
Basic
Pass the source as code. It is rendered as plain text, so no escaping is needed. The copy button
is on by default.
import { CodeBlock } from 'jarvis-react-ui';
export default function Basic() {
return <CodeBlock code="npm install jarvis-react-ui" />;
}
Title and language
title (usually a file name) and language are shown in the header. The language is only a label;
CodeBlock does not highlight code by itself.
import { CodeBlock } from 'jarvis-react-ui';
const SOURCE = `import { Button } from 'jarvis-react-ui';
export function App() {
return <Button variant="primary">Engage</Button>;
}`;
export default function TitleAndLanguage() {
return <CodeBlock title="App.tsx" language="tsx" code={SOURCE} />;
}
Header actions
actions renders extra controls at the right end of the header, before the copy button. Use small
icon buttons such as IconButton with size="sm".
import { useState } from 'react';
import { WrapText } from 'lucide-react';
import { CodeBlock, IconButton } from 'jarvis-react-ui';
const SOURCE = `const status = await fetch('/api/reactor/status').then((res) => res.json()); // a deliberately long line`;
export default function WithActions() {
const [wrap, setWrap] = useState(false);
return (
<CodeBlock
className={wrap ? '[&_pre]:whitespace-pre-wrap' : undefined}
title="status.ts"
language="ts"
code={SOURCE}
actions={
<IconButton
icon={WrapText}
label={wrap ? 'Disable line wrap' : 'Enable line wrap'}
size="sm"
aria-pressed={wrap}
onClick={() => setWrap((w) => !w)}
/>
}
/>
);
}
Not copyable
Set copyable={false} to hide the copy button, e.g. for logs or output that nobody should paste.
Without title, language, actions and the copy button, the header is not rendered at all.
import { CodeBlock } from 'jarvis-react-ui';
export default function NotCopyable() {
return (
<CodeBlock
language="log"
copyable={false}
code={
'[12:04:31] link established\n[12:04:32] handshake ok\n[12:04:33] streaming telemetry'
}
/>
);
}
Copy feedback
onCopy is called with the code after it reached the clipboard. Combine it with
useToast to confirm the copy; reusing a toast id keeps repeated copies from
stacking.
import { CodeBlock, useToast } from 'jarvis-react-ui';
export default function CopyToast() {
const { toast } = useToast();
return (
<CodeBlock
className="w-full"
code="npm i jarvis-react-ui"
language="bash"
onCopy={() => toast({ id: 'copied', variant: 'success', title: 'Copied' })}
/>
);
}
Syntax highlighting
CodeBlock does not ship a highlighter. To show colored code, highlight it yourself (ideally at
build time, e.g. with shiki) and pass the resulting markup as html. It is
injected into the <code> element, while code is still used for the copy button. Every code
sample on this site works that way: the demo sources are highlighted by shiki during the build and
handed to CodeBlock together with the raw source.
import { CodeBlock } from 'jarvis-react-ui';
const CODE = "import { Button } from 'jarvis-react-ui';";
// Trusted markup generated at build time (e.g. by shiki), never user input.
const HTML =
'<span class="text-accent-bright">import</span> { Button } ' +
'<span class="text-accent-bright">from</span> ' +
'<span class="text-success">\'jarvis-react-ui\'</span>;';
export default function Highlighted() {
return <CodeBlock title="App.tsx" language="tsx" code={CODE} html={HTML} />;
}
Warning: Trusted markup only
htmlis injected withdangerouslySetInnerHTMLand is not sanitized. Only pass markup that you generated yourself from trusted sources. Never pass user input, URL parameters or API responses, because that opens the door to cross-site scripting (XSS).
Accessibility
- The code is rendered in a native
<pre><code>, which scrolls horizontally for long lines and keeps whitespace intact. - The copy button is an IconButton labelled "Copy code"; after a successful copy its label and tooltip switch to "Copied" for 1.5 seconds.
- Copying uses the async Clipboard API, which browsers only allow in secure contexts (HTTPS or localhost). Where it is unavailable the button does nothing.
API
| Prop | Type | Default | Description |
|---|---|---|---|
code (required) |
string |
Raw source code. Copied to the clipboard and rendered as plain text when html is absent. |
|
actions |
ReactNode |
Content rendered at the right end of the header, next to the copy button. | |
className |
string |
Additional class names for the outer frame (wraps the header and the <pre>). |
|
copyable |
boolean |
true |
Shows the copy-to-clipboard button. |
html |
string |
Pre-highlighted markup for the inside of the <code> element, e.g. produced by shiki at build time. It is injected as HTML, so it must come from a trusted source, never from user input. |
|
language |
string |
Language label shown in the header, e.g. tsx. |
|
onCopy |
((code: string) => void) |
Called with the code after it was copied to the clipboard, e.g. to show a toast. Not called when copying fails or the clipboard API is unavailable. | |
title |
ReactNode |
Title shown in the header, e.g. a file name. |