This document outlines the steps to create CodeSnippet
component styled withTailwind CSS and using some npm dependency libraries.
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.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
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