Vasyl Putra

React Tailwind CodeBlock

The React Tailwind CodeBlock component is designed to display code snippets with syntax highlighting, line numbers, and a convenient copy-to-clipboard feature. Written with React and styled using Tailwind CSS, it offers a lightweight and flexible solution for embedding code in your web applications.

Key Features:

  1. Syntax Highlighting:

Utilizes react-code-block for syntax highlighting, ensuring that your code is readable and visually appealing.

  1. Line Numbers:
    • Provides optional line numbers for better readability and reference.
  2. Copy to Clipboard:
    • Includes a built-in button to easily copy the code to the clipboard, enhancing user convenience.
  3. File Name Display:
    • Optionally displays the filename above the code block, which can be useful for indicating the context of the code snippet.
  4. Highlighted Lines:
    • Supports highlighting specific lines of code, which can be useful for tutorials and code reviews.
  5. Responsive Design:
    • Styled with Tailwind CSS, ensuring the component is responsive and fits well into modern web designs.

Benefits of Using React Tailwind CodeBlock:

  1. Integration:
    • Easily integrates with React applications without the need for additional libraries, reducing dependency bloat and potential conflicts.
  2. Customization:
    • Highly customizable through props and Tailwind CSS classes, allowing you to tailor the appearance and functionality to meet your needs.
  3. Performance:
    • Lightweight and performant, leveraging React's rendering capabilities and Tailwind's utility-first CSS approach.
  4. User Experience:
    • Enhances user experience with features like copy-to-clipboard and syntax highlighting, making it easier for users to interact with and understand the code.
  5. Maintenance:
    • Being a React component, it benefits from React's ecosystem, including hooks and state management, making it easy to maintain and extend.
1
npm install react-code-block react-use react-children-utilities clsx
Code.tsx
1
import { CodeBlock } from "react-code-block";
2
import { useCopyToClipboard } from "react-use";
3
import { useState } from "react";
4
import { onlyText } from "react-children-utilities";
5
import clsx from "clsx";
6
import React from "react";
7
8
interface CodeProps extends React.HTMLAttributes<HTMLDivElement> {
9
filename?: string;
10
hideLineNumbers?: boolean;
11
children: React.ReactNode;
12
lines?: (number | string)[];
13
useMaxHeight?: boolean;
14
}
15
16
// Code component that renders a code block with line numbers and syntax highlighting.
17
// It also supports copying the code to the clipboard.
18
export const Code = React.memo(
19
({
20
children, // The code to be displayed
21
filename, // Optional filename to display
22
hideLineNumbers = false, // Whether to hide line numbers
23
lines = [], // Optional array of lines to highlight
24
useMaxHeight = true, // Whether to limit the height of the code block
25
...props // Additional HTML attributes for the code block
26
}: CodeProps) => {
27
// Hook to copy text to the clipboard
28
const [, copyToClipboard] = useCopyToClipboard();
29
// State to track whether the code is currently being copied
30
const [isCopied, setIsCopied] = useState(false);
31
// Extract the code from the children prop
32
const code = React.useMemo(() => onlyText(children), [children]);
33
// Extract the language from the className prop
34
const options = props?.className?.split(",");
35
const language = options?.[0].replace(/language-/, "") || "text";
36
37
// Function to copy the code to the clipboard
38
const copyCode = React.useCallback(() => {
39
copyToClipboard(code);
40
setIsCopied(true);
41
}, [code, copyToClipboard]);
42
43
// Effect to reset the isCopied state after 2 seconds
44
React.useEffect(() => {
45
const timeout = setTimeout(() => {
46
setIsCopied(false);
47
}, 2000);
48
49
return () => clearTimeout(timeout);
50
}, [isCopied]);
51
52
// Render the code block with line numbers and syntax highlighting
53
return (
54
<CodeBlock code={code} language={language} lines={lines}>
55
<div className="code-block relative mt-6 rounded-xl border border-gray-200 bg-gray-50">
56
{filename && (
57
<div className="rounded-t-xl bg-gray-200/40 px-4 py-2 text-xs dark:text-black">
58
{filename}
59
</div>
60
)}
61
<CodeBlock.Code
62
className={clsx(
63
"no-scrollbar overflow-auto rounded-xl bg-gray-900 !p-2 shadow-lg md:!p-6",
64
{ "max-h-96": useMaxHeight },
65
)}
66
>
67
{({ isLineHighlighted }) => (
68
<div className="relative table-row">
69
{!hideLineNumbers ? (
70
<CodeBlock.LineNumber className="table-cell select-none pr-4 text-right text-xs text-gray-500" />
71
) : (
72
<div className="table-cell pl-4" />
73
)}
74
<CodeBlock.LineContent className="table-cell w-full pr-10 text-[0.6rem] tracking-tight md:pr-4 md:text-xs">
75
{isLineHighlighted && (
76
<div className="absolute inset-0 border-l-2 border-blue-500 bg-blue-500/10" />
77
)}
78
<CodeBlock.Token className="relative">
79
{({ isTokenHighlighted, children }) => (
80
<span
81
className={`relative ${isTokenHighlighted ? "px-1" : ""}`}
82
>
83
{isTokenHighlighted && (
84
<span className="absolute -inset-y-0.5 inset-x-0 rounded-md bg-blue-500/20" />
85
)}
86
<span className="relative">{children}</span>
87
</span>
88
)}
89
</CodeBlock.Token>
90
</CodeBlock.LineContent>
91
</div>
92
)}
93
</CodeBlock.Code>
94
95
{/* Button to copy the code to the clipboard */}
96
<button
97
className={clsx(
98
"absolute right-3 rounded-md border border-gray-300/60 bg-gray-200/70 p-[0.2rem] text-gray-500 shadow-sm md:p-1.5",
99
{
100
"top-3": !filename,
101
"top-[2.6rem] md:top-11": filename,
102
},
103
)}
104
onClick={copyCode}
105
>
106
{/* SVG icon to indicate whether the code is copied or not */}
107
<svg
108
xmlns="http://www.w3.org/2000/svg"
109
fill="none"
110
viewBox="0 0 24 24"
111
strokeWidth={2}
112
stroke="currentColor"
113
className="h-2 w-2 md:h-4 md:w-4"
114
>
115
{isCopied ? (
116
<path
117
strokeLinecap="round"
118
strokeLinejoin="round"
119
d="M4.5 12.75l6 6 9-13.5"
120
/>
121
) : (
122
<path
123
strokeLinecap="round"
124
strokeLinejoin="round"
125
d="M15.666 3.888A2.25 2.25 0 0013.5 2.25h-3c-1.03 0-1.9.693-2.166 1.638m7.332 0c.055.194.084.4.084.612v0a.75.75 0 01-.75.75H9a.75.75 0 01-.75-.75v0c0-.212.03-.418.084-.612m7.332 0c.646.049 1.288.11 1.927.184 1.1.128 1.907 1.077 1.907 2.185V19.5a2.25 2.25 0 01-2.25 2.25H6.75A2.25 2.25 0 014.5 19.5V6.257c0-1.108.806-2.057 1.907-2.185"
126
/>
127
)}
128
</svg>
129
</button>
130
</div>
131
</CodeBlock>
132
);
133
},
134
);
135
136
Code.displayName = "Code";
Example.tsx
1
import React from 'react';
2
import { Code } from './Code';
3
4
const Example = () => {
5
return (
6
<div>
7
<h1>Example Code Block</h1>
8
<Code filename="example.js" language="javascript" lines={[1, 2]}>
9
{`const greeting = "Hello, world!";
10
console.log(greeting);`}
11
</Code>
12
</div>
13
);
14
};
15
16
export default Example;

In summary, the React Tailwind CodeBlock component provides a streamlined and efficient way to display code snippets with essential features, making it a valuable addition to any React project. By using this component, you ensure that your code is not only functional but also presented in a professional and user-friendly manner.

By a coffee for Puvvl

Keep Updated

Stay ahead of the curve with Puvvl.dev! Join our mailing list to receive exclusive, handpicked updates and important news. Be the first to know about our latest advancements and innovations.