1
mirror of https://github.com/jakejarvis/jarv.is.git synced 2026-06-29 19:05:58 -04:00

okay preact is actually pretty cool tbh. (now using it for copy to clipboard buttons)

This commit is contained in:
2021-12-07 08:11:38 -05:00
parent b4cd9eea59
commit 6d64ea647e
6 changed files with 95 additions and 83 deletions
+43 -27
View File
@@ -1,35 +1,51 @@
import { h, render } from "preact";
import { useState } from "preact/hooks";
import copy from "clipboard-copy";
import trimNewlines from "trim-newlines";
// the default text of the copy button:
const defaultText = "Copy";
const successText = "Copied!";
// shared react components:
import { CopyIcon, CheckIcon } from "@primer/octicons-react";
const CopyButton = (props) => {
const [copied, setCopied] = useState(false);
const handleCopy = (e) => {
// stop browser from navigating away from page (this shouldn't happen anyways)
e.preventDefault();
// prevent unintentional double-clicks by unfocusing button
e.target.blur();
// trim any surrounding whitespace from target block's content and send it to the clipboard
copy(trimNewlines(props.content));
// indicate success...
setCopied(true);
// ...but reset everything after 2 seconds
setTimeout(() => {
setCopied(false);
}, 2000);
};
return (
<button
class="copy-button"
title="Copy to clipboard"
aria-label="Copy to clipboard"
onClick={handleCopy}
disabled={copied}
>
{copied ? <CheckIcon size={16} /> : <CopyIcon size={16} />}
</button>
);
};
// loop through each code fence on page (if any)
document.querySelectorAll("div.highlight").forEach((highlightDiv) => {
// bind a new button to the copy action
const button = document.createElement("button");
button.className = "copy-button";
button.textContent = defaultText;
button.addEventListener("click", () => {
// prevent unintentional double-clicks by unfocusing button
button.blur();
// actual code element will have class "language-*" (even if plaintext)
const codeElement = highlightDiv.querySelector('code[class^="language-"]');
// actual code element will have class "language-*", even if plaintext
if (copy(trimNewlines(highlightDiv.querySelector('code[class^="language-"]').textContent))) {
// show a subtle indication of success
button.textContent = successText;
// reset button to original text after 2 seconds
setTimeout(() => {
button.textContent = defaultText;
}, 2000);
}
});
// add Hugo's code block to a new wrapper element, and insert the copy button as a sibling to it
const wrapperDiv = document.createElement("div");
wrapperDiv.className = "highlight-clipboard-enabled";
highlightDiv.before(wrapperDiv);
wrapperDiv.append(highlightDiv, button);
if (codeElement) {
// add the button as a sibling to the original Hugo block whose contents we're copying
render(<CopyButton content={codeElement.textContent} />, highlightDiv);
}
});
+2 -2
View File
@@ -68,7 +68,7 @@ const RepositoryCard = (repo) => (
target="_blank"
rel="noopener noreferrer"
>
<StarIcon size={16} fill="currentColor" />
<StarIcon size={16} />
<span>{repo.stars.toLocaleString("en-US")}</span>
</a>
</div>
@@ -82,7 +82,7 @@ const RepositoryCard = (repo) => (
target="_blank"
rel="noopener noreferrer"
>
<RepoForkedIcon size={16} fill="currentColor" />
<RepoForkedIcon size={16} />
<span>{repo.forks.toLocaleString("en-US")}</span>
</a>
</div>
+9 -14
View File
@@ -34,6 +34,7 @@ div.highlight {
overflow-x: scroll;
margin: 1em 0;
border: 1px solid;
position: relative;
pre {
padding-left: 1.5em;
@@ -44,23 +45,15 @@ div.highlight {
> pre > code {
padding-right: 1.5em;
}
}
// elements dynamically added by clipboard.js code
div.highlight-clipboard-enabled {
position: relative;
button.copy-button {
position: absolute;
top: 0;
right: 0;
width: 5.5em;
padding: 0.75em 0.25em;
border: 1px solid;
padding: 0.75em;
border-width: 0 0 1px 1px;
border-style: solid;
cursor: pointer;
font-size: 0.85em;
font-weight: 500;
line-height: 1;
&:hover {
@include themes.themed(
@@ -69,6 +62,11 @@ div.highlight-clipboard-enabled {
)
);
}
.octicon {
width: 1em;
height: 1em;
}
}
}
@@ -110,9 +108,6 @@ div.highlight-clipboard-enabled {
}
.kd,
// .nb,
// .nl,
// .nv,
.vc,
.vg,
.vi,