Skip to content

Commit 1293868

Browse files
Show and copy oklch value
1 parent d95c993 commit 1293868

File tree

4 files changed

+27
-80
lines changed

4 files changed

+27
-80
lines changed

package.json

-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
"@tailwindcss/postcss": "4.0.0",
1818
"@types/mdx": "^2.0.13",
1919
"clsx": "^2.1.1",
20-
"colorizr": "^3.0.7",
2120
"dedent": "^1.5.3",
2221
"fathom-client": "^3.7.2",
2322
"feed": "^4.2.2",

pnpm-lock.yaml

-8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/components/color-palette.tsx

+8-15
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,16 @@ import { Color } from "./color";
88
const __filename = fileURLToPath(import.meta.url);
99
const __dirname = path.dirname(__filename);
1010

11-
const styles = await fs.readFile(
12-
path.join(__dirname, "../../node_modules/tailwindcss/theme.css"),
13-
"utf-8",
14-
);
11+
let styles = await fs.readFile(path.join(__dirname, "../../node_modules/tailwindcss/theme.css"), "utf-8");
1512

16-
const colors: Record<string, Record<string, string>> = {};
17-
for (const line of styles.split("\n")) {
13+
let colors: Record<string, Record<string, string>> = {};
14+
for (let line of styles.split("\n")) {
1815
if (line.startsWith(" --color-")) {
19-
const [key, value] = line
20-
.split(":")
21-
.map((part) => part.trim().replace(";", ""));
22-
const match = key.match(/^--color-([a-z]+)-(\d+)$/);
16+
let [key, value] = line.split(":").map((part) => part.trim().replace(";", ""));
17+
let match = key.match(/^--color-([a-z]+)-(\d+)$/);
2318

2419
if (match) {
25-
const [, group, shade] = match;
20+
let [, group, shade] = match;
2621

2722
if (!colors[group]) {
2823
colors[group] = {};
@@ -51,12 +46,10 @@ export function ColorPalette() {
5146
</div>
5247
{Object.entries(colors).map(([key, shades]) => (
5348
<React.Fragment key={key}>
54-
<p className="font-medium text-gray-950 capitalize sm:pr-12 dark:text-white">
55-
{key}
56-
</p>
49+
<p className="font-medium text-gray-950 capitalize sm:pr-12 dark:text-white">{key}</p>
5750
<div className="grid grid-cols-11 gap-1.5 sm:gap-4">
5851
{Object.keys(shades).map((shade, i) => (
59-
<Color key={i} name={key} shade={shade} />
52+
<Color key={i} name={key} shade={shade} value={shades[shade]} />
6053
))}
6154
</div>
6255
</React.Fragment>

src/components/color.tsx

+19-56
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,49 @@
11
"use client";
22

3-
import { oklch2hex } from "colorizr";
4-
import { useEffect, useRef, useState } from "react";
3+
import { useRef } from "react";
54
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";
126

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);
179

1810
const colorVariableName = `--color-${name}-${shade}`;
1911

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) {
2217
return;
2318
}
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;
5524
}, 1300);
56-
57-
return () => clearTimeout(timeout);
58-
}, [justCopied]);
25+
}
5926

6027
return (
61-
<Tooltip as="div" showDelayMs={100} hideDelayMs={0} className="relative">
28+
<Tooltip as="div" showDelayMs={100} hideDelayMs={0} className="contents">
6229
<TooltipTrigger>
6330
<Button
64-
ref={buttonRef}
6531
type="button"
6632
onClick={copyHexToClipboard}
67-
onTouchEnd={copyHexToClipboard}
6833
style={{ backgroundColor: `var(${colorVariableName})` }}
6934
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",
7136
)}
7237
/>
7338
</TooltipTrigger>
7439
<TooltipPanel
7540
as="div"
7641
anchor="top"
42+
ref={panelRef}
7743
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"
7844
>
79-
{justCopied ? "Copied!" : "Click to copy"}
45+
{value}
8046
</TooltipPanel>
8147
</Tooltip>
8248
);
83-
/*
84-
85-
*/
8649
}

0 commit comments

Comments
 (0)