feat: add copy buttons for code blocks (#217)

* feat: copy button on snippet code

* refactor: update func name, styles and refactor backToTop

Rename the function name `copyButton` to `attachCopyButtons`. Update copy button styles. Fix broken `backToTop` function by attaching `astro:after-swap` event listener.

---------

Co-authored-by: Sat Naing <satnaingdev@gmail.com>
This commit is contained in:
Qisthi Ramadhani
2024-01-07 21:45:47 +07:00
committed by GitHub
parent 1b4164226a
commit 6e7d76a0d3
+49 -2
View File
@@ -100,10 +100,57 @@ const layoutProps = {
</style> </style>
<script is:inline> <script is:inline>
/* When the user clicks on the "Back to Top" button, /** Attaches copy buttons to code blocks in the document,
* scroll to the top of the document */ * allowing users to copy code easily. */
function attachCopyButtons() {
let copyButtonLabel = "Copy";
let codeBlocks = Array.from(document.querySelectorAll("pre"));
for (let codeBlock of codeBlocks) {
let wrapper = document.createElement("div");
wrapper.style.position = "relative";
let copyButton = document.createElement("button");
copyButton.className =
"copy-code absolute right-3 -top-3 rounded bg-skin-card px-2 py-1 text-xs leading-4 text-skin-base font-medium";
copyButton.innerHTML = copyButtonLabel;
codeBlock.setAttribute("tabindex", "0");
codeBlock.appendChild(copyButton);
// wrap codebock with relative parent element
codeBlock.parentNode.insertBefore(wrapper, codeBlock);
wrapper.appendChild(codeBlock);
copyButton.addEventListener("click", async () => {
await copyCode(codeBlock, copyButton);
});
}
async function copyCode(block, button) {
let code = block.querySelector("code");
let text = code.innerText;
await navigator.clipboard.writeText(text);
// visual feedback that task is completed
button.innerText = "Copied";
setTimeout(() => {
button.innerText = copyButtonLabel;
}, 700);
}
}
attachCopyButtons();
document.addEventListener("astro:after-swap", attachCopyButtons);
/** Scrolls the document to the top when
* the "Back to Top" button is clicked. */
function backToTop() {
document.querySelector("#back-to-top")?.addEventListener("click", () => { document.querySelector("#back-to-top")?.addEventListener("click", () => {
document.body.scrollTop = 0; // For Safari document.body.scrollTop = 0; // For Safari
document.documentElement.scrollTop = 0; // For Chrome, Firefox, IE and Opera document.documentElement.scrollTop = 0; // For Chrome, Firefox, IE and Opera
}); });
}
backToTop();
document.addEventListener("astro:after-swap", backToTop);
</script> </script>