Skip to content

Commit 7645626

Browse files
committed
Implemented the Copy button as required
1 parent 12180a1 commit 7645626

File tree

6 files changed

+114
-4
lines changed

6 files changed

+114
-4
lines changed

assets/sass/content.scss

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,43 @@ pre {
4949
border-radius: 5px;
5050
overflow-x: auto;
5151
}
52+
.code-block-wrapper {
53+
position: relative;
54+
margin-bottom: 1.5rem;
55+
}
56+
57+
.copy-code-button {
58+
position: absolute;
59+
top: 8px;
60+
right: 8px;
61+
width: 28px;
62+
height: 28px;
63+
64+
background: rgba(255, 255, 255, 0.15);
65+
backdrop-filter: blur(4px);
66+
border-radius: 6px;
67+
68+
border: 1px solid rgba(255, 255, 255, 0.25);
69+
cursor: pointer;
70+
71+
display: flex;
72+
align-items: center;
73+
justify-content: center;
74+
75+
transition: background 0.2s ease, border-color 0.2s ease;
76+
77+
svg {
78+
width: 16px;
79+
height: 16px;
80+
fill: white;
81+
}
82+
83+
&:hover {
84+
background: rgba(255, 255, 255, 0.25);
85+
border-color: rgba(255, 255, 255, 0.4);
86+
}
87+
}
88+
5289

5390
details {
5491
margin-bottom: 2em;
@@ -58,5 +95,5 @@ details {
5895
}
5996

6097
details[open] {
61-
border-color: 1px solid var(--text-color);
62-
}
98+
border-color: var(--text-color);
99+
}

layouts/_default/baseof.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
<meta name="twitter:card" content="summary" />
2525

2626
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
27+
2728
</head>
2829
<body>
2930
<a class="skip-to-content-link" href="#main">
@@ -44,7 +45,7 @@ <h1><a href="/">Helmet.js</a></h1>
4445

4546
<main id="main" class="container">
4647
{{ block "main" . }}{{ end }}
47-
</div>
48+
</main>
49+
<script src="/js/copy-code.js" defer></script>
4850
</body>
4951
</html>
50-

static/img/check.svg

Lines changed: 4 additions & 0 deletions
Loading

static/img/copy.svg

Lines changed: 5 additions & 0 deletions
Loading

static/img/error.svg

Lines changed: 5 additions & 0 deletions
Loading

static/js/copy-code.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
document.addEventListener("DOMContentLoaded", () => {
2+
const codeBlocks = document.querySelectorAll("pre > code");
3+
4+
const icons = {
5+
copy: `
6+
<svg viewBox="0 0 28 28">
7+
<path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1
8+
0-2 .9-2 2v16c0 1.1.9 2 2 2h11c1.1 0 2-.9
9+
2-2V7c0-1.1-.9-2-2-2zm0 18H8V7h11v16z"/>
10+
</svg>
11+
`,
12+
check: `
13+
<svg viewBox="0 0 24 24">
14+
<path d="M9 16.17 4.83 12l-1.42 1.41L9 19
15+
21 7l-1.41-1.41z"/>
16+
</svg>
17+
`
18+
};
19+
20+
function setButtonState(btn, icon, label) {
21+
btn.innerHTML = icon;
22+
btn.setAttribute("aria-label", label);
23+
}
24+
25+
codeBlocks.forEach(code => {
26+
const pre = code.parentElement;
27+
const wrapper = document.createElement("div");
28+
29+
wrapper.className = "code-block-wrapper";
30+
pre.replaceWith(wrapper);
31+
wrapper.appendChild(pre);
32+
33+
const button = document.createElement("button");
34+
button.className = "copy-code-button";
35+
setButtonState(button, icons.copy, "Copy code");
36+
37+
wrapper.appendChild(button);
38+
39+
let cooling = false;
40+
41+
button.addEventListener("click", async () => {
42+
if (cooling) return;
43+
cooling = true;
44+
45+
try {
46+
await navigator.clipboard.writeText(code.textContent.trim());
47+
setButtonState(button, icons.check, "Copied");
48+
} catch {
49+
setButtonState(button, icons.copy, "Copy code");
50+
}
51+
52+
setTimeout(() => {
53+
setButtonState(button, icons.copy, "Copy code");
54+
cooling = false;
55+
}, 1000);
56+
});
57+
});
58+
});

0 commit comments

Comments
 (0)