💫 @Fronchef offers you the best custom made websites according to your needs

Code Snippet

A beautifull code snippet

Code Snippet Overview

Installation

Install all these dependencies

npm install react-syntax-highlighter --save
npm install @heroicons/react

Make these Modifications

tailwind.config.ts

import type { Config } from "tailwindcss";

const colors = require("tailwindcss/colors");

const config: Config = {
  darkMode: ["class"],
  content: [
    "./pages/**/*.{ts,tsx}",
    "./components/**/*.{ts,tsx}",
    "./app/**/*.{ts,tsx}",
    "./src/**/*.{ts,tsx}",
    "./data/**/*.{ts,tsx}",
  ],
  theme: {
    extend: {
      colors: {
        white: colors.white,
        black: colors.black,
        zinc: colors.zinc, // for `bg-zinc-900` and `border-zinc-600`
        green: {
          500: "#22c55e", // `text-green-500`
        },
      },
      maxWidth: {
        "85%": "85%",
      },
      height: {
        auto: "auto",
        "96": "24rem", // 384px equivalent
      },
      maxHeight: {
        "96": "24rem", // 384px equivalent
      },
      borderRadius: {
        lg: "0.5rem", // Default large radius
      },
      padding: {
        1: "0.25rem",
        4: "1rem",
      },
      fontSize: {
        lg: "1.125rem", // Text size
      },
      spacing: {
        "1/2": "50%", // For `translate-y-1/2`
      },
      transitionTimingFunction: {
        "transition-all": "all 0.3s ease", // Hover transitions
      },
    },
  },
  plugins: [],
};

export default config;

global.css

@tailwind base;
@tailwind components;
@tailwind utilities;

:root {
  --background: #ffffff;
  --foreground: #171717;
}

@media (prefers-color-scheme: dark) {
  :root {
    --background: #0a0a0a;
    --foreground: #ededed;
  }
}

body {
  color: var(--foreground);
  background: var(--background);
  font-family: Arial, Helvetica, sans-serif;
}

/* Hide scrollbar for WebKit-based browsers (e.g., Chrome, Safari) */
::-webkit-scrollbar {
  display: none;
}

/* Hide scrollbar for Firefox */
* {
  scrollbar-width: none; /* Firefox */
}

Source Code

components/CodeSnippet.tsx

import { useState, useEffect, useRef } from "react";
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { solarizedlight } from 'react-syntax-highlighter/dist/esm/styles/prism';
import CopyButton from "@/components/root/renderpage/CopyButton";

const CodeBlock = ({ id, code, language = "javascript" }: { id: string; code: string; language?: string }) => {
    const [isExpanded, setIsExpanded] = useState(false);
    const [shouldShowExpand, setShouldShowExpand] = useState(false);
    const [initialHeight, setInitialHeight] = useState<number | undefined>(undefined);
    const codeContainerRef = useRef<HTMLDivElement>(null);

    useEffect(() => {
        const codeHeight = codeContainerRef.current?.scrollHeight ?? 0;

        if (codeHeight > 384) { // 384px = h-96
            setShouldShowExpand(true);
            setInitialHeight(384);
        } else {
            setInitialHeight(codeHeight);
        }
    }, [code]);

    return (
        <div
            className={`relative flex flex-col justify-between border border-zinc-600 bg-zinc-900 w-[100%] md:w-[90%] overflow-hidden mt-5 rounded-lg p-4 text-lg ${isExpanded ? "h-auto" : `h-[${initialHeight}px]`}`}
        >
            <div
                id={id}
                ref={codeContainerRef}
                className={`max-w-[85%] ${isExpanded ? "h-auto overflow-auto" : "max-h-96 overflow-hidden"}`}
            >
                <SyntaxHighlighter
                    language={language}
                    style={solarizedlight}
                    customStyle={{
                        background: "none", // Removes the background color
                        padding: 0,
                        fontSize: '1rem',
                    }}
                    codeTagProps={{ style: { backgroundColor: "transparent" } }} // Ensures transparency
                >
                    {code}
                </SyntaxHighlighter>
            </div>
            {shouldShowExpand && !isExpanded && (
                <div className="absolute inset-x-0 mx-auto top-1/2 transform -translate-y-1/2 flex justify-center">
                    <button
                        className="bg-zinc-700 text-white font-bold py-1 px-4 rounded-md hover:bg-black transition-all"
                        onClick={() => setIsExpanded(true)}
                    >
                        Expand
                    </button>
                </div>
            )}
            <div className="absolute top-4 right-4">
                <CopyButton textToCopy={code} />
            </div>
        </div>
    );
};

export default CodeBlock;
components/CopyButton.tsx

"use client";
import { useState } from "react";
import { ClipboardDocumentIcon, CheckIcon } from "@heroicons/react/24/outline"; 

const CopyButton = ({ textToCopy }: { textToCopy: string }) => {
    const [isCopied, setIsCopied] = useState(false);

    const copyToClipboard = () => {
        navigator.clipboard.writeText(textToCopy)
            .then(() => setIsCopied(true))
            .catch(() => setIsCopied(false));
        setTimeout(() => setIsCopied(false), 2000);
    };

    return (
        <button
            onClick={copyToClipboard}
            className="text-white"
            aria-label="Copy Code"
        >
            {isCopied ? <CheckIcon className="h-6 w-6 text-green-500" /> : <ClipboardDocumentIcon className="h-6 w-6" />}
        </button>
    );
};

export default CopyButton;