Skip to content

Commit

Permalink
Merge pull request #31 from crow-fox/features/color-code-copy
Browse files Browse the repository at this point in the history
Features/color code copy
  • Loading branch information
crow-fox authored May 5, 2024
2 parents f02c1fd + 7e93c19 commit b7cb9fe
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 9 deletions.
59 changes: 50 additions & 9 deletions app/_features/color/ColorGridItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import {
TailwindColors,
TailwindGradedColorName,
TailwindSingleColorName,
getTailwindColors,
} from "@/app/_features/color/tailwind";
import { useTailwindColorQuery } from "@/app/_features/color/useTailwindColorQuery";
import { useClipboardCopy } from "@/app/_utils/useClipboardCopy";
import Link from "next/link";
import { useCallback } from "react";

type Props = {
color:
Expand Down Expand Up @@ -43,19 +44,24 @@ export function ColorGridItem({ color, tailwindColors }: Props) {
currentColor.color.name === color.name &&
currentColor.color.value === color.value;

const { isCopied, clipboardCopy } = useClipboardCopy();

const handleCopy = useCallback(async () => {
await clipboardCopy(color.value);
}, [color.value, clipboardCopy]);

return (
<Link
href={createColorHref(color)}
scroll={false}
<div
className={[
"grid gap-y-3 p-2 hover:shadow-[inset_0_0_0_2px_theme(colors.gray[900])] focus-visible:shadow-[inset_0_0_0_2px_theme(colors.gray[900])] focus-visible:outline-none dark:hover:shadow-[inset_0_0_0_2px_theme(colors.gray[200])] dark:focus-visible:shadow-[inset_0_0_0_2px_theme(colors.gray[200])]",
"relative grid gap-y-2 p-2 ",
isCurrent
? "shadow-[inset_0_0_0_2px_theme(colors.gray[900])] dark:shadow-[inset_0_0_0_2px_theme(colors.gray[200])]"
: "shadow-none",
].join(" ")}
>
<div
className="grid h-10 w-full min-w-20 place-content-center rounded-md border border-gray-100 text-xs/none dark:border-gray-800 "
aria-hidden="true"
className="grid h-10 w-full min-w-20 place-content-center rounded-md border border-gray-100 text-xs/none dark:border-gray-800 "
style={{
backgroundColor: color.value,
color:
Expand All @@ -66,8 +72,43 @@ export function ColorGridItem({ color, tailwindColors }: Props) {
>
{currentColor.type !== "notFound" && "テキスト"}
</div>
<p className=" text-sm/none ">{color.value}</p>

<div className="grid grid-cols-[auto_1fr] items-center gap-x-1 text-sm/none">
<Link
scroll={false}
href={createColorHref(color)}
className="text-sm/none after:absolute after:inset-0 after:block after:hover:shadow-[inset_0_0_0_2px_theme(colors.gray[900])] focus-visible:outline-none after:focus-visible:shadow-[inset_0_0_0_2px_theme(colors.gray[900])] after:dark:hover:shadow-[inset_0_0_0_2px_theme(colors.gray[200])] after:dark:focus-visible:shadow-[inset_0_0_0_2px_theme(colors.gray[200])]"
>
{color.value}
</Link>
<button
onClick={handleCopy}
className=" isolate inline-grid size-6 place-content-center rounded-lg border border-gray-900 bg-white text-sm/none dark:border-gray-200 dark:bg-gray-950"
>
{isCopied ? (
<svg
role="img"
aria-label="コピーしました"
height="1em"
viewBox="0 -960 960 960"
width="1em"
className="fill-current"
>
<path d="M382-240 154-468l57-57 171 171 367-367 57 57-424 424Z" />
</svg>
) : (
<svg
role="img"
aria-label="カラーコードコピー"
height="1em"
viewBox="0 -960 960 960"
width="1em"
className="fill-current"
>
<path d="M360-240q-33 0-56.5-23.5T280-320v-480q0-33 23.5-56.5T360-880h360q33 0 56.5 23.5T800-800v480q0 33-23.5 56.5T720-240H360Zm0-80h360v-480H360v480ZM200-80q-33 0-56.5-23.5T120-160v-560h80v560h440v80H200Zm160-240v-480 480Z" />
</svg>
)}
</button>
</div>
{contrastResult && (
<div className=" grid grid-cols-[auto_1fr] items-center gap-x-1">
<p
Expand All @@ -81,7 +122,7 @@ export function ColorGridItem({ color, tailwindColors }: Props) {
<p className="text-sm/none">{contrastResult.ratio}</p>
</div>
)}
</Link>
</div>
);
}

Expand Down
18 changes: 18 additions & 0 deletions app/_utils/useClipboardCopy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { useCallback, useState } from "react";

export function useClipboardCopy() {
const [isCopied, setIsCopied] = useState(false);

const clipboardCopy = useCallback(
async (text: string, delay: number = 1000) => {
await navigator.clipboard.writeText(text);
setIsCopied(true);
setTimeout(() => {
setIsCopied(false);
}, delay);
},
[],
);

return { isCopied, clipboardCopy } as const;
}

0 comments on commit b7cb9fe

Please sign in to comment.