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:
- Syntax Highlighting:
Utilizes react-code-block for syntax highlighting, ensuring that your code is readable and visually appealing.
- Line Numbers:
- Provides optional line numbers for better readability and reference.
- Copy to Clipboard:
- Includes a built-in button to easily copy the code to the clipboard, enhancing user convenience.
- File Name Display:
- Optionally displays the filename above the code block, which can be useful for indicating the context of the code snippet.
- Highlighted Lines:
- Supports highlighting specific lines of code, which can be useful for tutorials and code reviews.
- Responsive Design:
- Styled with Tailwind CSS, ensuring the component is responsive and fits well into modern web designs.
Benefits of Using React Tailwind CodeBlock:
- Integration:
- Easily integrates with React applications without the need for additional libraries, reducing dependency bloat and potential conflicts.
- Customization:
- Highly customizable through props and Tailwind CSS classes, allowing you to tailor the appearance and functionality to meet your needs.
- Performance:
- Lightweight and performant, leveraging React's rendering capabilities and Tailwind's utility-first CSS approach.
- 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.
- Maintenance:
- Being a React component, it benefits from React's ecosystem, including hooks and state management, making it easy to maintain and extend.
1npm install react-code-block react-use react-children-utilities clsx
Code.tsx1import { CodeBlock } from "react-code-block";2import { useCopyToClipboard } from "react-use";3import { useState } from "react";4import { onlyText } from "react-children-utilities";5import clsx from "clsx";6import React from "react";78interface CodeProps extends React.HTMLAttributes<HTMLDivElement> {9filename?: string;10hideLineNumbers?: boolean;11children: React.ReactNode;12lines?: (number | string)[];13useMaxHeight?: boolean;14}1516// Code component that renders a code block with line numbers and syntax highlighting.17// It also supports copying the code to the clipboard.18export const Code = React.memo(19({20children, // The code to be displayed21filename, // Optional filename to display22hideLineNumbers = false, // Whether to hide line numbers23lines = [], // Optional array of lines to highlight24useMaxHeight = true, // Whether to limit the height of the code block25...props // Additional HTML attributes for the code block26}: CodeProps) => {27// Hook to copy text to the clipboard28const [, copyToClipboard] = useCopyToClipboard();29// State to track whether the code is currently being copied30const [isCopied, setIsCopied] = useState(false);31// Extract the code from the children prop32const code = React.useMemo(() => onlyText(children), [children]);33// Extract the language from the className prop34const options = props?.className?.split(",");35const language = options?.[0].replace(/language-/, "") || "text";3637// Function to copy the code to the clipboard38const copyCode = React.useCallback(() => {39copyToClipboard(code);40setIsCopied(true);41}, [code, copyToClipboard]);4243// Effect to reset the isCopied state after 2 seconds44React.useEffect(() => {45const timeout = setTimeout(() => {46setIsCopied(false);47}, 2000);4849return () => clearTimeout(timeout);50}, [isCopied]);5152// Render the code block with line numbers and syntax highlighting53return (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.Code62className={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<span81className={`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>9495{/* Button to copy the code to the clipboard */}96<button97className={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)}104onClick={copyCode}105>106{/* SVG icon to indicate whether the code is copied or not */}107<svg108xmlns="http://www.w3.org/2000/svg"109fill="none"110viewBox="0 0 24 24"111strokeWidth={2}112stroke="currentColor"113className="h-2 w-2 md:h-4 md:w-4"114>115{isCopied ? (116<path117strokeLinecap="round"118strokeLinejoin="round"119d="M4.5 12.75l6 6 9-13.5"120/>121) : (122<path123strokeLinecap="round"124strokeLinejoin="round"125d="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);135136Code.displayName = "Code";
Example.tsx1import React from 'react';2import { Code } from './Code';34const Example = () => {5return (6<div>7<h1>Example Code Block</h1>8<Code filename="example.js" language="javascript" lines={[1, 2]}>9{`const greeting = "Hello, world!";10console.log(greeting);`}11</Code>12</div>13);14};1516export 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.