Search

Ctrl + K

CodeSnippet

This document outlines the steps to create CodeSnippet component styled withTailwind CSS and using some npm dependency libraries.

Prerequisites

  • Node.js and npm installed on your machine.
  • Tailwind CSS installed in your project.
  • CVA(class-variance-authority) is a utility for managing CSS class names based on various conditions.
  • clsx is a tiny utility for constructing className strings conditionally.
Step 1: Create variant styles
1// code-snippet.helpers.ts
2import { cva } from "class-variance-authority";
3
4export const codeVariants = cva(
5  "flex items-center justify-between gap-2 rounded-md px-3 py-1.5",
6  {
7    variants: {
8      size: {
9        small: "text-xs",
10        medium: "text-base",
11        large: "text-xl",
12      },
13      color: {
14        primary: "bg-blue-100 text-blue-600",
15        secondary: "bg-gray-100 text-gray-600",
16        success: "bg-green-100 text-green-600",
17        danger: "bg-red-100 text-red-600",
18        warning: "bg-yellow-100 text-yellow-600",
19        info: "bg-cyan-100 text-cyan-600",
20        light: "bg-transparent text-gray-500",
21        dark: "bg-neutral-900 text-white",
22      },
23    },
24    defaultVariants: {
25      size: "medium",
26      color: "primary",
27    },
28  },
29);
30
31export const copyVariants = cva("cursor-pointer animate-zoom-in", {
32  variants: {
33    size: {
34      small: "w-4 h-4",
35      medium: "w-5 h-5",
36      large: "w-6 h-6",
37    },
38  },
39  defaultVariants: {
40    size: "medium",
41  },
42});
43
Step 2: Create CodeSnippet component
1// code-snippet.component.tsx
2import clsx from "clsx";
3import { CheckIcon, CopyIcon } from "lucide-react";
4import { useState } from "react";
5import type { VariantProps } from "class-variance-authority";
6import { codeVariants, copyVariants } from "./code-snippet.helpers";
7
8export interface CodeSnippetProps extends VariantProps<typeof codeVariants> {
9  code: string;
10  showCopy?: boolean;
11  className?: string;
12  labelClassName?: string;
13}
14
15const CodeSnippet: React.FC<CodeSnippetProps> = ({
16  code,
17  showCopy,
18  size,
19  color,
20  className,
21  labelClassName,
22}) => {
23  const [copied, setCopied] = useState<boolean>(false);
24
25  const handleCopy = async () => {
26    if (!navigator?.clipboard) {
27      console.warn("Clipboard not supported");
28      return;
29    }
30
31    try {
32      await navigator.clipboard.writeText(code);
33      setCopied(true);
34      setTimeout(() => setCopied(false), 2000);
35    } catch (error) {
36      console.warn("Copy failed", error);
37    }
38  };
39
40  return (
41    <div className={clsx(codeVariants({ size, color }), className)}>
42      <code className={labelClassName}>{code}</code>
43      {showCopy &&
44        (copied ? (
45          <CheckIcon className={copyVariants({ size })} />
46        ) : (
47          <CopyIcon className={copyVariants({ size })} onClick={handleCopy} />
48        ))}
49    </div>
50  );
51};
52
53export default CodeSnippet;
54