From 65f827888d13053b8f3e6e82ee0ad673731bb67e Mon Sep 17 00:00:00 2001
From: Ryan Huellen
Date: Wed, 22 Jan 2025 22:10:32 -0600
Subject: [PATCH 1/6] feat: ability to copy colors in v4 docs
---
package.json | 1 +
pnpm-lock.yaml | 8 +++
src/components/color-palette.tsx | 94 +++++++++++++++++---------------
src/components/color.tsx | 88 ++++++++++++++++++++++++++++++
4 files changed, 146 insertions(+), 45 deletions(-)
create mode 100644 src/components/color.tsx
diff --git a/package.json b/package.json
index 24e747e48..8535b899c 100644
--- a/package.json
+++ b/package.json
@@ -17,6 +17,7 @@
"@tailwindcss/postcss": "4.0.0",
"@types/mdx": "^2.0.13",
"clsx": "^2.1.1",
+ "colorizr": "^3.0.7",
"dedent": "^1.5.3",
"fathom-client": "^3.7.2",
"feed": "^4.2.2",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 9271272e8..927a9572d 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -32,6 +32,9 @@ importers:
clsx:
specifier: ^2.1.1
version: 2.1.1
+ colorizr:
+ specifier: ^3.0.7
+ version: 3.0.7
dedent:
specifier: ^1.5.3
version: 1.5.3
@@ -1349,6 +1352,9 @@ packages:
resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==}
engines: {node: '>=12.5.0'}
+ colorizr@3.0.7:
+ resolution: {integrity: sha512-CIXYuY/LtF2J0UiWcj7y9RjQBPNwdkawgJIyHrtqzsj2hohsC7c/BBC+9o1NjjxgX59zIoTsE8IO02r3MOIN7Q==}
+
comma-separated-tokens@2.0.3:
resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
@@ -3616,6 +3622,8 @@ snapshots:
color-string: 1.9.1
optional: true
+ colorizr@3.0.7: {}
+
comma-separated-tokens@2.0.3: {}
commander@7.2.0: {}
diff --git a/src/components/color-palette.tsx b/src/components/color-palette.tsx
index 5355e460a..b7739f43a 100644
--- a/src/components/color-palette.tsx
+++ b/src/components/color-palette.tsx
@@ -3,60 +3,64 @@ import path from "node:path";
import { fileURLToPath } from "node:url";
import React from "react";
+import { Color } from "./color";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
-const styles = await fs.readFile(path.join(__dirname, "../../node_modules/tailwindcss/theme.css"), "utf-8");
+const styles = await fs.readFile(
+ path.join(__dirname, "../../node_modules/tailwindcss/theme.css"),
+ "utf-8",
+);
-let colors: Record> = {};
-for (let line of styles.split("\n")) {
- if (line.startsWith(" --color-")) {
- const [key, value] = line.split(":").map((part) => part.trim().replace(";", ""));
- const match = key.match(/^--color-([a-z]+)-(\d+)$/);
+const colors: Record> = {};
+for (const line of styles.split("\n")) {
+ if (line.startsWith(" --color-")) {
+ const [key, value] = line
+ .split(":")
+ .map((part) => part.trim().replace(";", ""));
+ const match = key.match(/^--color-([a-z]+)-(\d+)$/);
- if (match) {
- const [, group, shade] = match;
+ if (match) {
+ const [, group, shade] = match;
- if (!colors[group]) {
- colors[group] = {};
- }
+ if (!colors[group]) {
+ colors[group] = {};
+ }
- colors[group][shade] = value;
- }
- }
+ colors[group][shade] = value;
+ }
+ }
}
export function ColorPalette() {
- return (
-
-
-
50
-
100
-
200
-
300
-
400
-
500
-
600
-
700
-
800
-
900
-
950
-
- {Object.entries(colors).map(([key, shades]) => (
-
- {key}
-
- {Object.keys(shades).map((shade, i) => (
-
- ))}
-
-
- ))}
-
- );
+ return (
+
+
+
50
+
100
+
200
+
300
+
400
+
500
+
600
+
700
+
800
+
900
+
950
+
+ {Object.entries(colors).map(([key, shades]) => (
+
+
+ {key}
+
+
+ {Object.keys(shades).map((shade, i) => (
+
+ ))}
+
+
+ ))}
+
+ );
}
diff --git a/src/components/color.tsx b/src/components/color.tsx
new file mode 100644
index 000000000..2c8f55bf4
--- /dev/null
+++ b/src/components/color.tsx
@@ -0,0 +1,88 @@
+"use client";
+
+import { oklch2hex } from "colorizr";
+import { useEffect, useRef, useState } from "react";
+import clsx from "clsx";
+import {
+ Button,
+ Tooltip,
+ TooltipPanel,
+ TooltipTrigger,
+} from "@headlessui/react";
+
+export function Color({ name, shade }: { name: string; shade: string }) {
+ const [justCopied, setJustCopied] = useState(false);
+
+ const buttonRef = useRef(null);
+
+ const colorVariableName = `--color-${name}-${shade}`;
+
+ const copyHexToClipboard = () => {
+ if (!buttonRef.current) {
+ return;
+ }
+
+ const styleValue = buttonRef.current
+ .computedStyleMap()
+ .get(colorVariableName);
+
+ if (!styleValue) {
+ return;
+ }
+
+ const oklchWithCSSFunctionalNotation = styleValue.toString();
+
+ // oklch(0.808 0.114 19.571) to 0.808 0.114 19.571
+ const oklch = oklchWithCSSFunctionalNotation.slice(6, -1);
+
+ // 0.808 0.114 19.571 to [0.808, 0.114, 19.571]
+ const oklchTuple = oklch.split(" ").map(Number) as [number, number, number];
+
+ const hex = oklch2hex(oklchTuple);
+
+ navigator.clipboard.writeText(hex);
+
+ setJustCopied(true);
+ };
+
+ useEffect(() => {
+ const timeout = setTimeout(() => {
+ if (!justCopied) {
+ return;
+ }
+
+ setJustCopied(false);
+ }, 1300);
+
+ return () => clearTimeout(timeout);
+ }, [justCopied]);
+
+ const whiteHasContrastAgainstShade = Number(shade) > 400;
+
+ return (
+
+
+
+
+
+ {justCopied ? "Copied!" : "Click to copy"}
+
+
+ );
+ /*
+
+ */
+}
From 7c49ff4afef06aca88f9126583ba33eae3793263 Mon Sep 17 00:00:00 2001
From: Ryan Huellen
Date: Wed, 22 Jan 2025 22:22:33 -0600
Subject: [PATCH 2/6] fix: removed unused computation
---
src/components/color.tsx | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/components/color.tsx b/src/components/color.tsx
index 2c8f55bf4..deded517b 100644
--- a/src/components/color.tsx
+++ b/src/components/color.tsx
@@ -57,8 +57,6 @@ export function Color({ name, shade }: { name: string; shade: string }) {
return () => clearTimeout(timeout);
}, [justCopied]);
- const whiteHasContrastAgainstShade = Number(shade) > 400;
-
return (
From d95c993dc06e18a2eebdde1cb6706670b591a000 Mon Sep 17 00:00:00 2001
From: Ryan Huellen
Date: Wed, 22 Jan 2025 22:25:05 -0600
Subject: [PATCH 3/6] style: spaces instead of tabs
---
src/components/color-palette.tsx | 88 +++++++++---------
src/components/color.tsx | 152 +++++++++++++++----------------
2 files changed, 120 insertions(+), 120 deletions(-)
diff --git a/src/components/color-palette.tsx b/src/components/color-palette.tsx
index b7739f43a..43f65f6f2 100644
--- a/src/components/color-palette.tsx
+++ b/src/components/color-palette.tsx
@@ -9,58 +9,58 @@ const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const styles = await fs.readFile(
- path.join(__dirname, "../../node_modules/tailwindcss/theme.css"),
- "utf-8",
+ path.join(__dirname, "../../node_modules/tailwindcss/theme.css"),
+ "utf-8",
);
const colors: Record> = {};
for (const line of styles.split("\n")) {
- if (line.startsWith(" --color-")) {
- const [key, value] = line
- .split(":")
- .map((part) => part.trim().replace(";", ""));
- const match = key.match(/^--color-([a-z]+)-(\d+)$/);
+ if (line.startsWith(" --color-")) {
+ const [key, value] = line
+ .split(":")
+ .map((part) => part.trim().replace(";", ""));
+ const match = key.match(/^--color-([a-z]+)-(\d+)$/);
- if (match) {
- const [, group, shade] = match;
+ if (match) {
+ const [, group, shade] = match;
- if (!colors[group]) {
- colors[group] = {};
- }
+ if (!colors[group]) {
+ colors[group] = {};
+ }
- colors[group][shade] = value;
- }
- }
+ colors[group][shade] = value;
+ }
+ }
}
export function ColorPalette() {
- return (
-
-
-
50
-
100
-
200
-
300
-
400
-
500
-
600
-
700
-
800
-
900
-
950
-
- {Object.entries(colors).map(([key, shades]) => (
-
-
- {key}
-
-
- {Object.keys(shades).map((shade, i) => (
-
- ))}
-
-
- ))}
-
- );
+ return (
+
+
+
50
+
100
+
200
+
300
+
400
+
500
+
600
+
700
+
800
+
900
+
950
+
+ {Object.entries(colors).map(([key, shades]) => (
+
+
+ {key}
+
+
+ {Object.keys(shades).map((shade, i) => (
+
+ ))}
+
+
+ ))}
+
+ );
}
diff --git a/src/components/color.tsx b/src/components/color.tsx
index deded517b..8b176a5af 100644
--- a/src/components/color.tsx
+++ b/src/components/color.tsx
@@ -4,83 +4,83 @@ import { oklch2hex } from "colorizr";
import { useEffect, useRef, useState } from "react";
import clsx from "clsx";
import {
- Button,
- Tooltip,
- TooltipPanel,
- TooltipTrigger,
+ Button,
+ Tooltip,
+ TooltipPanel,
+ TooltipTrigger,
} from "@headlessui/react";
export function Color({ name, shade }: { name: string; shade: string }) {
- const [justCopied, setJustCopied] = useState(false);
-
- const buttonRef = useRef(null);
-
- const colorVariableName = `--color-${name}-${shade}`;
-
- const copyHexToClipboard = () => {
- if (!buttonRef.current) {
- return;
- }
-
- const styleValue = buttonRef.current
- .computedStyleMap()
- .get(colorVariableName);
-
- if (!styleValue) {
- return;
- }
-
- const oklchWithCSSFunctionalNotation = styleValue.toString();
-
- // oklch(0.808 0.114 19.571) to 0.808 0.114 19.571
- const oklch = oklchWithCSSFunctionalNotation.slice(6, -1);
-
- // 0.808 0.114 19.571 to [0.808, 0.114, 19.571]
- const oklchTuple = oklch.split(" ").map(Number) as [number, number, number];
-
- const hex = oklch2hex(oklchTuple);
-
- navigator.clipboard.writeText(hex);
-
- setJustCopied(true);
- };
-
- useEffect(() => {
- const timeout = setTimeout(() => {
- if (!justCopied) {
- return;
- }
-
- setJustCopied(false);
- }, 1300);
-
- return () => clearTimeout(timeout);
- }, [justCopied]);
-
- return (
-
-
-
-
-
- {justCopied ? "Copied!" : "Click to copy"}
-
-
- );
- /*
-
- */
+ const [justCopied, setJustCopied] = useState(false);
+
+ const buttonRef = useRef(null);
+
+ const colorVariableName = `--color-${name}-${shade}`;
+
+ const copyHexToClipboard = () => {
+ if (!buttonRef.current) {
+ return;
+ }
+
+ const styleValue = buttonRef.current
+ .computedStyleMap()
+ .get(colorVariableName);
+
+ if (!styleValue) {
+ return;
+ }
+
+ const oklchWithCSSFunctionalNotation = styleValue.toString();
+
+ // oklch(0.808 0.114 19.571) to 0.808 0.114 19.571
+ const oklch = oklchWithCSSFunctionalNotation.slice(6, -1);
+
+ // 0.808 0.114 19.571 to [0.808, 0.114, 19.571]
+ const oklchTuple = oklch.split(" ").map(Number) as [number, number, number];
+
+ const hex = oklch2hex(oklchTuple);
+
+ navigator.clipboard.writeText(hex);
+
+ setJustCopied(true);
+ };
+
+ useEffect(() => {
+ const timeout = setTimeout(() => {
+ if (!justCopied) {
+ return;
+ }
+
+ setJustCopied(false);
+ }, 1300);
+
+ return () => clearTimeout(timeout);
+ }, [justCopied]);
+
+ return (
+
+
+
+
+
+ {justCopied ? "Copied!" : "Click to copy"}
+
+
+ );
+ /*
+
+ */
}
From 129386832f2a01680c437b89997468aee616a19b Mon Sep 17 00:00:00 2001
From: Philipp Spiess
Date: Thu, 20 Feb 2025 16:42:45 +0100
Subject: [PATCH 4/6] Show and copy oklch value
---
package.json | 1 -
pnpm-lock.yaml | 8 ----
src/components/color-palette.tsx | 23 ++++------
src/components/color.tsx | 75 ++++++++------------------------
4 files changed, 27 insertions(+), 80 deletions(-)
diff --git a/package.json b/package.json
index 8535b899c..24e747e48 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,6 @@
"@tailwindcss/postcss": "4.0.0",
"@types/mdx": "^2.0.13",
"clsx": "^2.1.1",
- "colorizr": "^3.0.7",
"dedent": "^1.5.3",
"fathom-client": "^3.7.2",
"feed": "^4.2.2",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 927a9572d..9271272e8 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -32,9 +32,6 @@ importers:
clsx:
specifier: ^2.1.1
version: 2.1.1
- colorizr:
- specifier: ^3.0.7
- version: 3.0.7
dedent:
specifier: ^1.5.3
version: 1.5.3
@@ -1352,9 +1349,6 @@ packages:
resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==}
engines: {node: '>=12.5.0'}
- colorizr@3.0.7:
- resolution: {integrity: sha512-CIXYuY/LtF2J0UiWcj7y9RjQBPNwdkawgJIyHrtqzsj2hohsC7c/BBC+9o1NjjxgX59zIoTsE8IO02r3MOIN7Q==}
-
comma-separated-tokens@2.0.3:
resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
@@ -3622,8 +3616,6 @@ snapshots:
color-string: 1.9.1
optional: true
- colorizr@3.0.7: {}
-
comma-separated-tokens@2.0.3: {}
commander@7.2.0: {}
diff --git a/src/components/color-palette.tsx b/src/components/color-palette.tsx
index 43f65f6f2..f2364932d 100644
--- a/src/components/color-palette.tsx
+++ b/src/components/color-palette.tsx
@@ -8,21 +8,16 @@ import { Color } from "./color";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
-const styles = await fs.readFile(
- path.join(__dirname, "../../node_modules/tailwindcss/theme.css"),
- "utf-8",
-);
+let styles = await fs.readFile(path.join(__dirname, "../../node_modules/tailwindcss/theme.css"), "utf-8");
-const colors: Record> = {};
-for (const line of styles.split("\n")) {
+let colors: Record> = {};
+for (let line of styles.split("\n")) {
if (line.startsWith(" --color-")) {
- const [key, value] = line
- .split(":")
- .map((part) => part.trim().replace(";", ""));
- const match = key.match(/^--color-([a-z]+)-(\d+)$/);
+ let [key, value] = line.split(":").map((part) => part.trim().replace(";", ""));
+ let match = key.match(/^--color-([a-z]+)-(\d+)$/);
if (match) {
- const [, group, shade] = match;
+ let [, group, shade] = match;
if (!colors[group]) {
colors[group] = {};
@@ -51,12 +46,10 @@ export function ColorPalette() {
{Object.entries(colors).map(([key, shades]) => (
-
- {key}
-
+ {key}
{Object.keys(shades).map((shade, i) => (
-
+
))}
diff --git a/src/components/color.tsx b/src/components/color.tsx
index 8b176a5af..41c9f20bb 100644
--- a/src/components/color.tsx
+++ b/src/components/color.tsx
@@ -1,86 +1,49 @@
"use client";
-import { oklch2hex } from "colorizr";
-import { useEffect, useRef, useState } from "react";
+import { useRef } from "react";
import clsx from "clsx";
-import {
- Button,
- Tooltip,
- TooltipPanel,
- TooltipTrigger,
-} from "@headlessui/react";
+import { Button, Tooltip, TooltipPanel, TooltipTrigger } from "@headlessui/react";
-export function Color({ name, shade }: { name: string; shade: string }) {
- const [justCopied, setJustCopied] = useState(false);
-
- const buttonRef = useRef(null);
+export function Color({ name, shade, value }: { name: string; shade: string; value: string }) {
+ const panelRef = useRef(null);
const colorVariableName = `--color-${name}-${shade}`;
- const copyHexToClipboard = () => {
- if (!buttonRef.current) {
+ function copyHexToClipboard(e: React.MouseEvent) {
+ e.preventDefault();
+ e.stopPropagation();
+ let panel = panelRef.current;
+ if (!panel) {
return;
}
-
- const styleValue = buttonRef.current
- .computedStyleMap()
- .get(colorVariableName);
-
- if (!styleValue) {
- return;
- }
-
- const oklchWithCSSFunctionalNotation = styleValue.toString();
-
- // oklch(0.808 0.114 19.571) to 0.808 0.114 19.571
- const oklch = oklchWithCSSFunctionalNotation.slice(6, -1);
-
- // 0.808 0.114 19.571 to [0.808, 0.114, 19.571]
- const oklchTuple = oklch.split(" ").map(Number) as [number, number, number];
-
- const hex = oklch2hex(oklchTuple);
-
- navigator.clipboard.writeText(hex);
-
- setJustCopied(true);
- };
-
- useEffect(() => {
- const timeout = setTimeout(() => {
- if (!justCopied) {
- return;
- }
-
- setJustCopied(false);
+ let prevValue = panel.innerText;
+ navigator.clipboard.writeText(value);
+ panel.innerText = "Copied to clipboard!";
+ setTimeout(() => {
+ panel.innerText = prevValue;
}, 1300);
-
- return () => clearTimeout(timeout);
- }, [justCopied]);
+ }
return (
-
+
- {justCopied ? "Copied!" : "Click to copy"}
+ {value}
);
- /*
-
- */
}
From 926488ad5fadd68832de89b5f7c8cbbbd1cd5ac6 Mon Sep 17 00:00:00 2001
From: Philipp Spiess
Date: Thu, 20 Feb 2025 16:59:30 +0100
Subject: [PATCH 5/6] Add shift key modifier to get legacy hex values
---
src/components/color.tsx | 336 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 330 insertions(+), 6 deletions(-)
diff --git a/src/components/color.tsx b/src/components/color.tsx
index 41c9f20bb..368627ecc 100644
--- a/src/components/color.tsx
+++ b/src/components/color.tsx
@@ -1,13 +1,304 @@
"use client";
-import { useRef } from "react";
+import { useEffect, useRef, useState } from "react";
import clsx from "clsx";
import { Button, Tooltip, TooltipPanel, TooltipTrigger } from "@headlessui/react";
+const hexColors = {
+ slate: {
+ 50: "#f8fafc",
+ 100: "#f1f5f9",
+ 200: "#e2e8f0",
+ 300: "#cbd5e1",
+ 400: "#94a3b8",
+ 500: "#64748b",
+ 600: "#475569",
+ 700: "#334155",
+ 800: "#1e293b",
+ 900: "#0f172a",
+ 950: "#020617",
+ },
+ gray: {
+ 50: "#f9fafb",
+ 100: "#f3f4f6",
+ 200: "#e5e7eb",
+ 300: "#d1d5db",
+ 400: "#9ca3af",
+ 500: "#6b7280",
+ 600: "#4b5563",
+ 700: "#374151",
+ 800: "#1f2937",
+ 900: "#111827",
+ 950: "#030712",
+ },
+ zinc: {
+ 50: "#fafafa",
+ 100: "#f4f4f5",
+ 200: "#e4e4e7",
+ 300: "#d4d4d8",
+ 400: "#a1a1aa",
+ 500: "#71717a",
+ 600: "#52525b",
+ 700: "#3f3f46",
+ 800: "#27272a",
+ 900: "#18181b",
+ 950: "#09090b",
+ },
+ neutral: {
+ 50: "#fafafa",
+ 100: "#f5f5f5",
+ 200: "#e5e5e5",
+ 300: "#d4d4d4",
+ 400: "#a3a3a3",
+ 500: "#737373",
+ 600: "#525252",
+ 700: "#404040",
+ 800: "#262626",
+ 900: "#171717",
+ 950: "#0a0a0a",
+ },
+ stone: {
+ 50: "#fafaf9",
+ 100: "#f5f5f4",
+ 200: "#e7e5e4",
+ 300: "#d6d3d1",
+ 400: "#a8a29e",
+ 500: "#78716c",
+ 600: "#57534e",
+ 700: "#44403c",
+ 800: "#292524",
+ 900: "#1c1917",
+ 950: "#0c0a09",
+ },
+ red: {
+ 50: "#fef2f2",
+ 100: "#fee2e2",
+ 200: "#fecaca",
+ 300: "#fca5a5",
+ 400: "#f87171",
+ 500: "#ef4444",
+ 600: "#dc2626",
+ 700: "#b91c1c",
+ 800: "#991b1b",
+ 900: "#7f1d1d",
+ 950: "#450a0a",
+ },
+ orange: {
+ 50: "#fff7ed",
+ 100: "#ffedd5",
+ 200: "#fed7aa",
+ 300: "#fdba74",
+ 400: "#fb923c",
+ 500: "#f97316",
+ 600: "#ea580c",
+ 700: "#c2410c",
+ 800: "#9a3412",
+ 900: "#7c2d12",
+ 950: "#431407",
+ },
+ amber: {
+ 50: "#fffbeb",
+ 100: "#fef3c7",
+ 200: "#fde68a",
+ 300: "#fcd34d",
+ 400: "#fbbf24",
+ 500: "#f59e0b",
+ 600: "#d97706",
+ 700: "#b45309",
+ 800: "#92400e",
+ 900: "#78350f",
+ 950: "#451a03",
+ },
+ yellow: {
+ 50: "#fefce8",
+ 100: "#fef9c3",
+ 200: "#fef08a",
+ 300: "#fde047",
+ 400: "#facc15",
+ 500: "#eab308",
+ 600: "#ca8a04",
+ 700: "#a16207",
+ 800: "#854d0e",
+ 900: "#713f12",
+ 950: "#422006",
+ },
+ lime: {
+ 50: "#f7fee7",
+ 100: "#ecfccb",
+ 200: "#d9f99d",
+ 300: "#bef264",
+ 400: "#a3e635",
+ 500: "#84cc16",
+ 600: "#65a30d",
+ 700: "#4d7c0f",
+ 800: "#3f6212",
+ 900: "#365314",
+ 950: "#1a2e05",
+ },
+ green: {
+ 50: "#f0fdf4",
+ 100: "#dcfce7",
+ 200: "#bbf7d0",
+ 300: "#86efac",
+ 400: "#4ade80",
+ 500: "#22c55e",
+ 600: "#16a34a",
+ 700: "#15803d",
+ 800: "#166534",
+ 900: "#14532d",
+ 950: "#052e16",
+ },
+ emerald: {
+ 50: "#ecfdf5",
+ 100: "#d1fae5",
+ 200: "#a7f3d0",
+ 300: "#6ee7b7",
+ 400: "#34d399",
+ 500: "#10b981",
+ 600: "#059669",
+ 700: "#047857",
+ 800: "#065f46",
+ 900: "#064e3b",
+ 950: "#022c22",
+ },
+ teal: {
+ 50: "#f0fdfa",
+ 100: "#ccfbf1",
+ 200: "#99f6e4",
+ 300: "#5eead4",
+ 400: "#2dd4bf",
+ 500: "#14b8a6",
+ 600: "#0d9488",
+ 700: "#0f766e",
+ 800: "#115e59",
+ 900: "#134e4a",
+ 950: "#042f2e",
+ },
+ cyan: {
+ 50: "#ecfeff",
+ 100: "#cffafe",
+ 200: "#a5f3fc",
+ 300: "#67e8f9",
+ 400: "#22d3ee",
+ 500: "#06b6d4",
+ 600: "#0891b2",
+ 700: "#0e7490",
+ 800: "#155e75",
+ 900: "#164e63",
+ 950: "#083344",
+ },
+ sky: {
+ 50: "#f0f9ff",
+ 100: "#e0f2fe",
+ 200: "#bae6fd",
+ 300: "#7dd3fc",
+ 400: "#38bdf8",
+ 500: "#0ea5e9",
+ 600: "#0284c7",
+ 700: "#0369a1",
+ 800: "#075985",
+ 900: "#0c4a6e",
+ 950: "#082f49",
+ },
+ blue: {
+ 50: "#eff6ff",
+ 100: "#dbeafe",
+ 200: "#bfdbfe",
+ 300: "#93c5fd",
+ 400: "#60a5fa",
+ 500: "#3b82f6",
+ 600: "#2563eb",
+ 700: "#1d4ed8",
+ 800: "#1e40af",
+ 900: "#1e3a8a",
+ 950: "#172554",
+ },
+ indigo: {
+ 50: "#eef2ff",
+ 100: "#e0e7ff",
+ 200: "#c7d2fe",
+ 300: "#a5b4fc",
+ 400: "#818cf8",
+ 500: "#6366f1",
+ 600: "#4f46e5",
+ 700: "#4338ca",
+ 800: "#3730a3",
+ 900: "#312e81",
+ 950: "#1e1b4b",
+ },
+ violet: {
+ 50: "#f5f3ff",
+ 100: "#ede9fe",
+ 200: "#ddd6fe",
+ 300: "#c4b5fd",
+ 400: "#a78bfa",
+ 500: "#8b5cf6",
+ 600: "#7c3aed",
+ 700: "#6d28d9",
+ 800: "#5b21b6",
+ 900: "#4c1d95",
+ 950: "#2e1065",
+ },
+ purple: {
+ 50: "#faf5ff",
+ 100: "#f3e8ff",
+ 200: "#e9d5ff",
+ 300: "#d8b4fe",
+ 400: "#c084fc",
+ 500: "#a855f7",
+ 600: "#9333ea",
+ 700: "#7e22ce",
+ 800: "#6b21a8",
+ 900: "#581c87",
+ 950: "#3b0764",
+ },
+ fuchsia: {
+ 50: "#fdf4ff",
+ 100: "#fae8ff",
+ 200: "#f5d0fe",
+ 300: "#f0abfc",
+ 400: "#e879f9",
+ 500: "#d946ef",
+ 600: "#c026d3",
+ 700: "#a21caf",
+ 800: "#86198f",
+ 900: "#701a75",
+ 950: "#4a044e",
+ },
+ pink: {
+ 50: "#fdf2f8",
+ 100: "#fce7f3",
+ 200: "#fbcfe8",
+ 300: "#f9a8d4",
+ 400: "#f472b6",
+ 500: "#ec4899",
+ 600: "#db2777",
+ 700: "#be185d",
+ 800: "#9d174d",
+ 900: "#831843",
+ 950: "#500724",
+ },
+ rose: {
+ 50: "#fff1f2",
+ 100: "#ffe4e6",
+ 200: "#fecdd3",
+ 300: "#fda4af",
+ 400: "#fb7185",
+ 500: "#f43f5e",
+ 600: "#e11d48",
+ 700: "#be123c",
+ 800: "#9f1239",
+ 900: "#881337",
+ 950: "#4c0519",
+ },
+} as any;
+
export function Color({ name, shade, value }: { name: string; shade: string; value: string }) {
- const panelRef = useRef(null);
+ let useShift = useShiftKey();
+ let panelRef = useRef(null);
- const colorVariableName = `--color-${name}-${shade}`;
+ let colorVariableName = `--color-${name}-${shade}`;
+ let hexValue = hexColors[name]?.[shade];
function copyHexToClipboard(e: React.MouseEvent) {
e.preventDefault();
@@ -17,8 +308,13 @@ export function Color({ name, shade, value }: { name: string; shade: string; val
return;
}
let prevValue = panel.innerText;
- navigator.clipboard.writeText(value);
- panel.innerText = "Copied to clipboard!";
+ if (e.shiftKey) {
+ navigator.clipboard.writeText(hexColors[name][shade]);
+ panel.innerText = "Copied hex value!";
+ } else {
+ navigator.clipboard.writeText(value);
+ panel.innerText = "Copied to clipboard!";
+ }
setTimeout(() => {
panel.innerText = prevValue;
}, 1300);
@@ -42,8 +338,36 @@ export function Color({ name, shade, value }: { name: string; shade: string; val
ref={panelRef}
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"
>
- {value}
+ {useShift && hexValue ? hexValue : value}
);
}
+
+function useShiftKey(): boolean {
+ let [isShiftPressed, setIsShiftPressed] = useState(false);
+
+ useEffect(() => {
+ let handleKeyDown = (event: KeyboardEvent) => {
+ if (event.key === "Shift") {
+ setIsShiftPressed(true);
+ }
+ };
+
+ let handleKeyUp = (event: KeyboardEvent) => {
+ if (event.key === "Shift") {
+ setIsShiftPressed(false);
+ }
+ };
+
+ window.addEventListener("keydown", handleKeyDown);
+ window.addEventListener("keyup", handleKeyUp);
+
+ return () => {
+ window.removeEventListener("keydown", handleKeyDown);
+ window.removeEventListener("keyup", handleKeyUp);
+ };
+ }, []);
+
+ return isShiftPressed;
+}
From 13a4ece60cb80cbdd9c3e1aac54c502fca6672e7 Mon Sep 17 00:00:00 2001
From: Philipp Spiess
Date: Fri, 21 Feb 2025 10:55:00 +0100
Subject: [PATCH 6/6] Make it at least do something when clicked in Safari
---
src/components/color.tsx | 27 ++++++++++++++++-----------
1 file changed, 16 insertions(+), 11 deletions(-)
diff --git a/src/components/color.tsx b/src/components/color.tsx
index 368627ecc..315ef9632 100644
--- a/src/components/color.tsx
+++ b/src/components/color.tsx
@@ -295,7 +295,7 @@ const hexColors = {
export function Color({ name, shade, value }: { name: string; shade: string; value: string }) {
let useShift = useShiftKey();
- let panelRef = useRef(null);
+ let panelRef = useRef(null);
let colorVariableName = `--color-${name}-${shade}`;
let hexValue = hexColors[name]?.[shade];
@@ -303,20 +303,20 @@ export function Color({ name, shade, value }: { name: string; shade: string; val
function copyHexToClipboard(e: React.MouseEvent) {
e.preventDefault();
e.stopPropagation();
+
let panel = panelRef.current;
- if (!panel) {
- return;
- }
- let prevValue = panel.innerText;
+ if (!panel) return;
+
+ let prevValue = panel.innerHTML;
if (e.shiftKey) {
navigator.clipboard.writeText(hexColors[name][shade]);
- panel.innerText = "Copied hex value!";
+ panel.innerHTML = "Copied hex value!";
} else {
navigator.clipboard.writeText(value);
- panel.innerText = "Copied to clipboard!";
+ panel.innerHTML = "Copied to clipboard!";
}
setTimeout(() => {
- panel.innerText = prevValue;
+ panel.innerHTML = prevValue;
}, 1300);
}
@@ -335,10 +335,15 @@ export function Color({ name, shade, value }: { name: string; shade: string; val
- {useShift && hexValue ? hexValue : value}
+ {
+ if (panel) panelRef.current = panel;
+ }}
+ >
+ {useShift && hexValue ? hexValue : value}
+
);