|
1 | 1 | "use client";
|
2 | 2 |
|
3 |
| -import { oklch2hex } from "colorizr"; |
4 |
| -import { useEffect, useRef, useState } from "react"; |
| 3 | +import { useRef } from "react"; |
5 | 4 | import clsx from "clsx";
|
6 |
| -import { |
7 |
| - Button, |
8 |
| - Tooltip, |
9 |
| - TooltipPanel, |
10 |
| - TooltipTrigger, |
11 |
| -} from "@headlessui/react"; |
| 5 | +import { Button, Tooltip, TooltipPanel, TooltipTrigger } from "@headlessui/react"; |
12 | 6 |
|
13 |
| -export function Color({ name, shade }: { name: string; shade: string }) { |
14 |
| - const [justCopied, setJustCopied] = useState(false); |
15 |
| - |
16 |
| - const buttonRef = useRef<HTMLButtonElement>(null); |
| 7 | +export function Color({ name, shade, value }: { name: string; shade: string; value: string }) { |
| 8 | + const panelRef = useRef<HTMLDivElement>(null); |
17 | 9 |
|
18 | 10 | const colorVariableName = `--color-${name}-${shade}`;
|
19 | 11 |
|
20 |
| - const copyHexToClipboard = () => { |
21 |
| - if (!buttonRef.current) { |
| 12 | + function copyHexToClipboard(e: React.MouseEvent) { |
| 13 | + e.preventDefault(); |
| 14 | + e.stopPropagation(); |
| 15 | + let panel = panelRef.current; |
| 16 | + if (!panel) { |
22 | 17 | return;
|
23 | 18 | }
|
24 |
| - |
25 |
| - const styleValue = buttonRef.current |
26 |
| - .computedStyleMap() |
27 |
| - .get(colorVariableName); |
28 |
| - |
29 |
| - if (!styleValue) { |
30 |
| - return; |
31 |
| - } |
32 |
| - |
33 |
| - const oklchWithCSSFunctionalNotation = styleValue.toString(); |
34 |
| - |
35 |
| - // oklch(0.808 0.114 19.571) to 0.808 0.114 19.571 |
36 |
| - const oklch = oklchWithCSSFunctionalNotation.slice(6, -1); |
37 |
| - |
38 |
| - // 0.808 0.114 19.571 to [0.808, 0.114, 19.571] |
39 |
| - const oklchTuple = oklch.split(" ").map(Number) as [number, number, number]; |
40 |
| - |
41 |
| - const hex = oklch2hex(oklchTuple); |
42 |
| - |
43 |
| - navigator.clipboard.writeText(hex); |
44 |
| - |
45 |
| - setJustCopied(true); |
46 |
| - }; |
47 |
| - |
48 |
| - useEffect(() => { |
49 |
| - const timeout = setTimeout(() => { |
50 |
| - if (!justCopied) { |
51 |
| - return; |
52 |
| - } |
53 |
| - |
54 |
| - setJustCopied(false); |
| 19 | + let prevValue = panel.innerText; |
| 20 | + navigator.clipboard.writeText(value); |
| 21 | + panel.innerText = "Copied to clipboard!"; |
| 22 | + setTimeout(() => { |
| 23 | + panel.innerText = prevValue; |
55 | 24 | }, 1300);
|
56 |
| - |
57 |
| - return () => clearTimeout(timeout); |
58 |
| - }, [justCopied]); |
| 25 | + } |
59 | 26 |
|
60 | 27 | return (
|
61 |
| - <Tooltip as="div" showDelayMs={100} hideDelayMs={0} className="relative"> |
| 28 | + <Tooltip as="div" showDelayMs={100} hideDelayMs={0} className="contents"> |
62 | 29 | <TooltipTrigger>
|
63 | 30 | <Button
|
64 |
| - ref={buttonRef} |
65 | 31 | type="button"
|
66 | 32 | onClick={copyHexToClipboard}
|
67 |
| - onTouchEnd={copyHexToClipboard} |
68 | 33 | style={{ backgroundColor: `var(${colorVariableName})` }}
|
69 | 34 | className={clsx(
|
70 |
| - "h-full w-full cursor-pointer aspect-1/1 rounded-sm outline -outline-offset-1 outline-black/10 sm:rounded-md dark:outline-white/10 flex items-center justify-center", |
| 35 | + "aspect-1/1 w-full rounded-sm outline -outline-offset-1 outline-black/10 sm:rounded-md dark:outline-white/10", |
71 | 36 | )}
|
72 | 37 | />
|
73 | 38 | </TooltipTrigger>
|
74 | 39 | <TooltipPanel
|
75 | 40 | as="div"
|
76 | 41 | anchor="top"
|
| 42 | + ref={panelRef} |
77 | 43 | className="pointer-events-none z-10 translate-y-2 rounded-full border border-gray-950 bg-gray-950/90 py-0.5 pr-2 pb-1 pl-3 text-center font-mono text-xs/6 font-medium whitespace-nowrap text-white opacity-100 inset-ring inset-ring-white/10 transition-[opacity] starting:opacity-0"
|
78 | 44 | >
|
79 |
| - {justCopied ? "Copied!" : "Click to copy"} |
| 45 | + {value} |
80 | 46 | </TooltipPanel>
|
81 | 47 | </Tooltip>
|
82 | 48 | );
|
83 |
| - /* |
84 |
| - |
85 |
| - */ |
86 | 49 | }
|
0 commit comments