Skip to content

Commit dd19367

Browse files
committed
add visual feedback
1 parent bbc983e commit dd19367

File tree

1 file changed

+50
-4
lines changed

1 file changed

+50
-4
lines changed

src/components/CopyPageButton.tsx

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,15 @@ import {
1313
PiMarkdownLogo,
1414
PiClipboardTextLight,
1515
PiArrowSquareOutLight,
16+
PiCheckCircleLight,
17+
PiXCircleLight,
1618
} from "react-icons/pi";
1719

20+
type CopyState = "idle" | "success" | "error";
21+
1822
export default function CopyPageButton() {
1923
const [isOpen, setIsOpen] = useState(false);
24+
const [copyState, setCopyState] = useState<CopyState>("idle");
2025

2126
const { refs, floatingStyles, context } = useFloating({
2227
open: isOpen,
@@ -42,10 +47,25 @@ export default function CopyPageButton() {
4247
const markdownUrl = new URL("index.md", window.location.href).toString();
4348
try {
4449
const response = await fetch(markdownUrl);
50+
51+
if (!response.ok) {
52+
throw new Error(`Received ${response.status} on ${response.url}`);
53+
}
54+
4555
const markdown = await response.text();
4656
await navigator.clipboard.writeText(markdown);
57+
58+
setCopyState("success");
59+
setTimeout(() => {
60+
setCopyState("idle");
61+
}, 1500);
4762
} catch (error) {
4863
console.error("Failed to copy Markdown:", error);
64+
65+
setCopyState("error");
66+
setTimeout(() => {
67+
setCopyState("idle");
68+
}, 1500);
4969
}
5070
};
5171

@@ -64,15 +84,41 @@ export default function CopyPageButton() {
6484
},
6585
];
6686

87+
const getButtonContent = () => {
88+
if (copyState === "success") {
89+
return (
90+
<>
91+
<PiCheckCircleLight className="h-4 w-4 text-green-600" />
92+
<span>Copied!</span>
93+
</>
94+
);
95+
}
96+
97+
if (copyState === "error") {
98+
return (
99+
<>
100+
<PiXCircleLight className="h-4 w-4 text-red-600" />
101+
<span>Failed to copy</span>
102+
</>
103+
);
104+
}
105+
106+
return (
107+
<>
108+
<PiMarkdownLogo />
109+
<span>Copy Page</span>
110+
</>
111+
);
112+
};
113+
67114
return (
68115
<>
69116
<button
70117
ref={refs.setReference}
71118
{...getReferenceProps()}
72-
className="inline-flex h-8 items-center justify-center gap-2 rounded border border-[--sl-color-hairline] bg-transparent px-3 text-sm text-black"
119+
className="inline-flex h-8 cursor-pointer items-center justify-center gap-2 rounded border border-[--sl-color-hairline] bg-transparent px-3 text-sm text-black hover:bg-[--sl-color-bg-nav]"
73120
>
74-
Copy Page
75-
<PiMarkdownLogo />
121+
{getButtonContent()}
76122
</button>
77123
{isOpen && (
78124
<FloatingPortal>
@@ -86,7 +132,7 @@ export default function CopyPageButton() {
86132
<li key={label}>
87133
<button
88134
onClick={onClick}
89-
className="block w-full bg-transparent px-3 py-2 text-left text-black no-underline hover:bg-[--sl-color-bg-nav]"
135+
className="relative block w-full cursor-pointer bg-transparent px-3 py-2 text-left text-black no-underline hover:bg-[--sl-color-bg-nav]"
90136
>
91137
<div className="flex items-center gap-2 text-sm">
92138
<Icon className="h-4 w-4" />

0 commit comments

Comments
 (0)