CodeBlock

A styled code container with a language badge, copy-to-clipboard button, optional line numbers, and scrollable overflow. Designed for displaying code snippets in AI chat UIs.

CodeBlock — Basic
typescript
import { useState, useEffect } from "react";
interface User {
id: string;
name: string;
email: string;
}
export function useUser(id: string) {
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(`/api/users/${id}`)
.then((res) => res.json())
.then((data) => {
setUser(data);
setLoading(false);
});
}, [id]);
return { user, loading };
}
CodeBlock — Line Numbers
python
1def fibonacci(n):
2 if n <= 1:
3 return n
4 return fibonacci(n - 1) + fibonacci(n - 2)
5
6for i in range(10):
7 print(fibonacci(i))
CodeBlock — Scrollable (maxHeight)
javascript
1// Line 1: processing step 1
2const result_1 = await process(input_1);
3// Line 2: processing step 2
4const result_2 = await process(input_2);
5// Line 3: processing step 3
6const result_3 = await process(input_3);
7// Line 4: processing step 4
8const result_4 = await process(input_4);
9// Line 5: processing step 5
10const result_5 = await process(input_5);
11// Line 6: processing step 6
12const result_6 = await process(input_6);
13// Line 7: processing step 7
14const result_7 = await process(input_7);
15// Line 8: processing step 8
16const result_8 = await process(input_8);
17// Line 9: processing step 9
18const result_9 = await process(input_9);
19// Line 10: processing step 10
20const result_10 = await process(input_10);
21// Line 11: processing step 11
22const result_11 = await process(input_11);
23// Line 12: processing step 12
24const result_12 = await process(input_12);
25// Line 13: processing step 13
26const result_13 = await process(input_13);
27// Line 14: processing step 14
28const result_14 = await process(input_14);
29// Line 15: processing step 15
30const result_15 = await process(input_15);
31// Line 16: processing step 16
32const result_16 = await process(input_16);
33// Line 17: processing step 17
34const result_17 = await process(input_17);
35// Line 18: processing step 18
36const result_18 = await process(input_18);
37// Line 19: processing step 19
38const result_19 = await process(input_19);
39// Line 20: processing step 20
40const result_20 = await process(input_20);
41// Line 21: processing step 21
42const result_21 = await process(input_21);
43// Line 22: processing step 22
44const result_22 = await process(input_22);
45// Line 23: processing step 23
46const result_23 = await process(input_23);
47// Line 24: processing step 24
48const result_24 = await process(input_24);
49// Line 25: processing step 25
50const result_25 = await process(input_25);
51// Line 26: processing step 26
52const result_26 = await process(input_26);
53// Line 27: processing step 27
54const result_27 = await process(input_27);
55// Line 28: processing step 28
56const result_28 = await process(input_28);
57// Line 29: processing step 29
58const result_29 = await process(input_29);
59// Line 30: processing step 30
60const result_30 = await process(input_30);

Import

tsx
import { CodeBlock } from "@arc-lo/ui";

Basic usage

tsx
<CodeBlock
  language="typescript"
  code={`const x = 42;
console.log(x);`}
/>

With line numbers

tsx
<CodeBlock
  language="python"
  showLineNumbers
  code={pythonCode}
/>

Custom max height

tsx
<CodeBlock
  language="json"
  maxHeight="200px"
  code={longJsonString}
/>

With copy callback

tsx
<CodeBlock
  code={snippet}
  onCopy={() => toast("Copied!")}
/>

Props

PropTypeDefaultDescription
codestringThe code string to display (required)
languagestringLanguage label shown in the header
showLineNumbersbooleanfalseShow line numbers
maxHeightstring"400px"Max height before scrolling
onCopy() => voidCalled when copy button is clicked