ArctisDocs
Search (Ctrl+K)

CodeBlock

tsx
1import CodeBlock from './CodeBlock'
2
3// Simple usage
4<CodeBlock code="pnpm add @arctis/ui" lang="bash" />
5
6// With line numbers
7<CodeBlock code={sourceCode} lang="tsx" showLineNumbers />
bash
pnpm add prism-react-renderer

Installation

bash
pnpm add prism-react-renderer

Usage

tsx
1import CodeBlock from './CodeBlock'
2
3// Simple usage
4<CodeBlock code="pnpm add @arctis/ui" lang="bash" />
5
6// With line numbers
7<CodeBlock code={sourceCode} lang="tsx" showLineNumbers />

Code

tsx
1"use client";
2
3import { useState } from "react";
4import { Highlight, themes } from "prism-react-renderer";
5
6export type CodeBlockProps = {
7 code: string;
8 lang?: string;
9 showLineNumbers?: boolean;
10};
11
12export function CodeBlock({
13 code,
14 lang = "tsx",
15 showLineNumbers = false,
16}: CodeBlockProps) {
17 const [copied, setCopied] = useState(false);
18
19 const copy = async () => {
20 await navigator.clipboard.writeText(code);
21 setCopied(true);
22 setTimeout(() => setCopied(false), 1200);
23 };
24
25 return (
26 <div className="relative overflow-hidden rounded border border-white/10 bg-[#050509]">
27 {/* Header */}
28 <div className="flex items-center justify-between border-b border-white/10 px-3 py-2 text-[11px] text-white/50">
29 <div className="flex items-center gap-2">
30 <span className="uppercase tracking-wide">{lang || "code"}</span>
31 </div>
32
33 <button
34 onClick={copy}
35 className="rounded border border-white/20 px-2 py-0.5 text-[10px] hover:border-white/40"
36 >
37 {copied ? "Copied" : "Copy"}
38 </button>
39 </div>
40
41 {/* Body */}
42 <Highlight
43 theme={themes.okaidia}
44 code={code.trimEnd()}
45 language={lang as any}
46 >
47 {({ className, style, tokens, getLineProps, getTokenProps }) => (
48 <pre
49 className={`${className} overflow-auto p-3 text-xs`}
50 style={style}
51 >
52 {tokens.map((line, i) => {
53 // Prism sometimes inserts the last blank line → completely discards the blank line
54 const isLastEmptyLine =
55 i === tokens.length - 1 &&
56 line.length === 1 &&
57 line[0]!.content.trim() === "";
58
59 if (isLastEmptyLine) return null;
60
61 return (
62 <div key={i} {...getLineProps({ line })} className="flex gap-4">
63 {showLineNumbers && (
64 <span className="select-none opacity-50">{i + 1}</span>
65 )}
66
67 <span className="flex-1">
68 {line.map((token, key) => (
69 <span key={key} {...getTokenProps({ token })} />
70 ))}
71 </span>
72 </div>
73 );
74 })}
75 </pre>
76 )}
77 </Highlight>
78 </div>
79 );
80}
81
82/**
83 Arctis UI Component — <CodeBlock>
84
85 Created with 💛 by Ranaufal Muha
86 https://ranaufalmuha.com
87
88 Hi! Thank you for using this component.
89 You’re free to copy, modify, or use it in any project you like.
90
91 If possible, please keep this small header as appreciation.
92 It helps others know where the component came from ❤️
93
94 Usage:
95 import { CodeBlock } from "@arctis/ui";
96
97 // Simple usage
98 <CodeBlock code="pnpm add @arctis/ui" lang="bash" />
99
100 // With line numbers
101 <CodeBlock code={sourceCode} lang="tsx" showLineNumbers />
102 */