Skip to content

Commit d311b28

Browse files
committed
feat(contact): enhance email section with copy functionality and styling
1 parent d5af0b1 commit d311b28

File tree

3 files changed

+195
-2
lines changed

3 files changed

+195
-2
lines changed

src/pages/en/contact.astro

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,43 @@ import BaseLayout from "../../layouts/BaseLayout.astro";
1515

1616
<div class="card">
1717
<div class="kicker">email</div>
18-
<h3>hello@rocketdeploy.dev</h3>
18+
19+
<div class="email-row">
20+
<h3>
21+
<a
22+
href="mailto:hello@rocketdeploy.dev"
23+
target="_blank"
24+
rel="noopener"
25+
class="email-link"
26+
>
27+
hello@rocketdeploy.dev
28+
</a>
29+
</h3>
30+
31+
<div class="email-actions">
32+
<button
33+
class="icon-btn"
34+
aria-label="Copy email address"
35+
title="Copy"
36+
type="button"
37+
onclick="window.copyEmail(this)"
38+
>
39+
40+
</button>
41+
42+
<a
43+
class="icon-btn"
44+
href="mailto:hello@rocketdeploy.dev"
45+
target="_blank"
46+
rel="noopener"
47+
aria-label="Write email"
48+
title="Write"
49+
>
50+
51+
</a>
52+
</div>
53+
</div>
54+
1955
<p>
2056
Entry point for collaboration discussions.
2157
</p>
@@ -47,4 +83,43 @@ import BaseLayout from "../../layouts/BaseLayout.astro";
4783
</div>
4884
</div>
4985
</div>
86+
87+
<script is:inline>
88+
window.copyEmail = async (button) => {
89+
if (!(button instanceof HTMLButtonElement)) return;
90+
91+
const email = "hello@rocketdeploy.dev";
92+
const original = button.textContent ?? "⧉";
93+
94+
const showTick = () => {
95+
button.textContent = "✔";
96+
button.disabled = true;
97+
setTimeout(() => {
98+
button.textContent = original;
99+
button.disabled = false;
100+
}, 1500);
101+
};
102+
103+
try {
104+
if (navigator.clipboard && window.isSecureContext) {
105+
await navigator.clipboard.writeText(email);
106+
} else {
107+
const ta = document.createElement("textarea");
108+
ta.value = email;
109+
ta.setAttribute("readonly", "");
110+
ta.style.position = "fixed";
111+
ta.style.opacity = "0";
112+
document.body.appendChild(ta);
113+
ta.focus();
114+
ta.select();
115+
document.execCommand("copy");
116+
document.body.removeChild(ta);
117+
}
118+
} catch (err) {
119+
console.warn("Copy failed:", err);
120+
}
121+
122+
showTick();
123+
};
124+
</script>
50125
</BaseLayout>

src/pages/pl/kontakt.astro

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,43 @@ import BaseLayout from "../../layouts/BaseLayout.astro";
1515

1616
<div class="card">
1717
<div class="kicker">email</div>
18-
<h3>hello@rocketdeploy.dev</h3>
18+
19+
<div class="email-row">
20+
<h3>
21+
<a
22+
href="mailto:hello@rocketdeploy.dev"
23+
target="_blank"
24+
rel="noopener"
25+
class="email-link"
26+
>
27+
hello@rocketdeploy.dev
28+
</a>
29+
</h3>
30+
31+
<div class="email-actions">
32+
<button
33+
class="icon-btn"
34+
aria-label="Kopiuj adres email"
35+
title="Kopiuj"
36+
type="button"
37+
onclick="window.copyEmail(this)"
38+
>
39+
40+
</button>
41+
42+
<a
43+
class="icon-btn"
44+
href="mailto:hello@rocketdeploy.dev"
45+
target="_blank"
46+
rel="noopener"
47+
aria-label="Napisz email"
48+
title="Napisz"
49+
>
50+
51+
</a>
52+
</div>
53+
</div>
54+
1955
<p>
2056
Punkt startowy do rozmowy o współpracy.
2157
</p>
@@ -47,4 +83,43 @@ import BaseLayout from "../../layouts/BaseLayout.astro";
4783
</div>
4884
</div>
4985
</div>
86+
87+
<script is:inline>
88+
window.copyEmail = async (button) => {
89+
if (!(button instanceof HTMLButtonElement)) return;
90+
91+
const email = "hello@rocketdeploy.dev";
92+
const original = button.textContent ?? "⧉";
93+
94+
const showTick = () => {
95+
button.textContent = "✔";
96+
button.disabled = true;
97+
setTimeout(() => {
98+
button.textContent = original;
99+
button.disabled = false;
100+
}, 1500);
101+
};
102+
103+
try {
104+
if (navigator.clipboard && window.isSecureContext) {
105+
await navigator.clipboard.writeText(email);
106+
} else {
107+
const ta = document.createElement("textarea");
108+
ta.value = email;
109+
ta.setAttribute("readonly", "");
110+
ta.style.position = "fixed";
111+
ta.style.opacity = "0";
112+
document.body.appendChild(ta);
113+
ta.focus();
114+
ta.select();
115+
document.execCommand("copy");
116+
document.body.removeChild(ta);
117+
}
118+
} catch (err) {
119+
console.warn("Copy failed:", err);
120+
}
121+
122+
showTick();
123+
};
124+
</script>
50125
</BaseLayout>

src/styles/global.css

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,4 +366,47 @@ h1{
366366
top: .05em;
367367
font-family: var(--mono);
368368
color: var(--faint);
369+
}
370+
371+
.email-row {
372+
display: flex;
373+
align-items: center;
374+
gap: 12px;
375+
}
376+
377+
.email-link {
378+
color: inherit;
379+
text-decoration: none;
380+
}
381+
382+
.email-link:hover {
383+
text-decoration: underline;
384+
}
385+
386+
.email-actions {
387+
display: flex;
388+
gap: 8px;
389+
}
390+
391+
.icon-btn {
392+
width: 34px;
393+
height: 34px;
394+
border-radius: 50%;
395+
border: 1px solid var(--border, rgba(255,255,255,0.15));
396+
background: transparent;
397+
color: inherit;
398+
font-size: 14px;
399+
line-height: 1;
400+
cursor: pointer;
401+
display: grid;
402+
place-items: center;
403+
}
404+
405+
.icon-btn:hover {
406+
background: rgba(255,255,255,0.06);
407+
}
408+
409+
.icon-btn:disabled {
410+
cursor: default;
411+
opacity: 0.9;
369412
}

0 commit comments

Comments
 (0)