Skip to content

Commit 095819e

Browse files
Feat : Enable click-to-copy for email address in footer (#190)
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
1 parent 59904c0 commit 095819e

3 files changed

Lines changed: 89 additions & 6 deletions

File tree

components/copy-email-button.tsx

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
"use client";
2+
3+
import Image from "next/image";
4+
import { useState, useRef, useEffect } from "react";
5+
import Hint from "./hint";
6+
7+
const EMAIL = "support@circuitverse.org";
8+
const COPIED_TOOLTIP_DURATION = 1500;
9+
export default function CopyEmailButton() {
10+
const [copied, setCopied] = useState(false);
11+
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
12+
useEffect(() => {
13+
return () => {
14+
if (timeoutRef.current) {
15+
clearTimeout(timeoutRef.current);
16+
}
17+
};
18+
}, []);
19+
const handleCopy = async () => {
20+
if (!navigator.clipboard) {
21+
console.error("Clipboard API not available");
22+
return;
23+
}
24+
try {
25+
await navigator.clipboard.writeText(EMAIL);
26+
setCopied(true);
27+
if (timeoutRef.current) {
28+
clearTimeout(timeoutRef.current);
29+
}
30+
timeoutRef.current = setTimeout(() => {
31+
setCopied(false);
32+
timeoutRef.current = null;
33+
}, COPIED_TOOLTIP_DURATION);
34+
} catch (error) {
35+
console.error("Failed to copy email:", error);
36+
}
37+
};
38+
return (
39+
<div className="relative">
40+
<Hint label="Email">
41+
<button
42+
type="button"
43+
onClick={handleCopy}
44+
aria-label="Email"
45+
className="text-zinc-400 hover:bg-zinc-100 dark:hover:bg-zinc-800 p-2 rounded-full transition-all duration-200"
46+
>
47+
<Image
48+
src="/gmail.svg"
49+
alt="Email"
50+
width={20}
51+
height={20}
52+
className="w-5 h-5"
53+
/>
54+
</button>
55+
</Hint>
56+
57+
{copied && (
58+
<div className="absolute -top-9 left-1/2 -translate-x-1/2 whitespace-nowrap
59+
rounded-md bg-zinc-900 px-2 py-1 text-xs text-white
60+
dark:bg-zinc-100 dark:text-zinc-900 shadow-md">
61+
Email Copied!
62+
</div>
63+
)}
64+
</div>
65+
);
66+
}

components/footer.tsx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
} from "lucide-react";
1212

1313
import Hint from "./hint";
14+
import CopyEmailButton from "./copy-email-button";
1415

1516
import { Config } from "@/types/config";
1617

@@ -143,15 +144,18 @@ export const Footer = async ({ config }: FooterProps) => {
143144
</Link>
144145
</Hint>
145146

146-
<Hint label="Email">
147+
<CopyEmailButton />
148+
149+
<Hint label="Slack">
147150
<Link
148-
href="mailto:support@circuitverse.org"
149-
className="text-zinc-400 group/em hover:bg-zinc-100 dark:hover:bg-zinc-800 p-2 sm:p-2 rounded-full transition-all duration-200"
150-
aria-label="Email"
151+
href="https://circuitverse-team.slack.com/ssb/redirect"
152+
target="_blank"
153+
className="text-zinc-400 hover:bg-zinc-100 dark:hover:bg-zinc-800 p-2 sm:p-2 rounded-full transition-all duration-200"
154+
aria-label="Slack"
151155
>
152156
<Image
153-
src="/gmail.svg"
154-
alt="Email"
157+
src="/slack.svg"
158+
alt="Slack"
155159
width={20}
156160
height={20}
157161
className="w-5 h-5 sm:w-5 sm:h-5"

public/slack.svg

Lines changed: 13 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)