Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add copy to clipboard in code blocks #14153

Merged
merged 5 commits into from Jan 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 5 additions & 1 deletion website/siteConfig.js
Expand Up @@ -56,7 +56,11 @@ const siteConfig = {
},
usePrism: ["javascript", "jsx", "typescript", "ts", "js", "html", "css"],
useEnglishUrl: true,
scripts: ["https://buttons.github.io/buttons.js"],
scripts: [
"https://buttons.github.io/buttons.js",
"https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.0/clipboard.min.js",
"/js/code-block-buttons.js",
],
stylesheets: [
"//unpkg.com/@sandhose/prettier-animated-logo@1.0.3/dist/wide.css",
],
Expand Down
63 changes: 63 additions & 0 deletions website/static/css/code-block-buttons.css
@@ -0,0 +1,63 @@
/* "Copy" code block button, style from docusaurus v2 */

.code-block-with-actions {
position: relative;
}

.code-block-actions {
position: absolute;
top: 10px;
right: 10px;
}

.code-block-copy-button {
width: 32px;
height: 32px;
border: 1px solid #dadde1;
border-radius: 6px;
display: flex;
transition: opacity 0.2s ease-in-out;
opacity: 0;
position: relative;
cursor: pointer;
color: #393a34;
background-color: #f6f8fa;
}

.code-block-with-actions:hover .code-block-copy-button {
opacity: 0.4;
}

.code-block-with-actions:hover .code-block-copy-button:hover {
opacity: 1;
}

.code-block-copy-button__icon {
fill: currentColor;
position: absolute;
width: 18px;
height: 18px;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
transition: 0.15s;
}

.code-block-copy-button__icon--copied {
color: #00d600;
opacity: 0;
transform: scale(0.33);
}

.code-block-copy-button--copied .code-block-copy-button__icon--copy {
opacity: 0;
transform: scale(0.33);
}

.code-block-copy-button--copied .code-block-copy-button__icon--copied {
transition-delay: 75ms;
transform: scale(1);
opacity: 1;
}
57 changes: 57 additions & 0 deletions website/static/js/code-block-buttons.js
@@ -0,0 +1,57 @@
/* global ClipboardJS */

"use strict";

(function () {
const CONTAINER_CLASS_NAME = "code-block-with-actions";
const ACTIONS_CONTAINER_CLASS_NAME = "code-block-actions";
const COPY_BUTTON_CLASS_NAME = "code-block-copy-button";
const COPY_BUTTON_COPIED_CLASS_NAME = `${COPY_BUTTON_CLASS_NAME}--copied`;
const COPY_BUTTON_ICON_CLASS_NAME = `${COPY_BUTTON_CLASS_NAME}__icon`;
const COPY_BUTTON_COPY_ICON_CLASS_NAME = `${COPY_BUTTON_ICON_CLASS_NAME}--copy`;
const COPY_BUTTON_COPIED_ICON_CLASS_NAME = `${COPY_BUTTON_ICON_CLASS_NAME}--copied`;
const ARIA_LABEL = "Copy code to clipboard";
const ARIA_LABEL_COPIED = "Copied";

function init(codeBlock) {
const container = codeBlock.parentNode;
container.classList.add(CONTAINER_CLASS_NAME);

const actionsContainer = Object.assign(document.createElement("div"), {
className: ACTIONS_CONTAINER_CLASS_NAME,
});
const copyButton = Object.assign(document.createElement("button"), {
className: COPY_BUTTON_CLASS_NAME,
type: "button",
innerHTML:
`<svg class="${COPY_BUTTON_ICON_CLASS_NAME} ${COPY_BUTTON_COPY_ICON_CLASS_NAME}" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg>` +
`<svg class="${COPY_BUTTON_ICON_CLASS_NAME} ${COPY_BUTTON_COPIED_ICON_CLASS_NAME}" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg>`,
});
copyButton.setAttribute("aria-label", ARIA_LABEL);

new ClipboardJS(copyButton, { target: () => codeBlock }).on(
"success",
(event) => {
event.clearSelection();
copyButton.classList.add(COPY_BUTTON_COPIED_CLASS_NAME);
copyButton.setAttribute("aria-label", ARIA_LABEL_COPIED);
copyButton.disabled = true;

setTimeout(() => {
copyButton.classList.remove(COPY_BUTTON_COPIED_CLASS_NAME);
copyButton.setAttribute("aria-label", ARIA_LABEL);
copyButton.disabled = false;
}, 2000);
}
);

actionsContainer.appendChild(copyButton);
container.appendChild(actionsContainer);
}

window.addEventListener("load", () => {
for (const codeBlock of document.querySelectorAll("pre > code.hljs")) {
init(codeBlock);
}
});
})();
6 changes: 3 additions & 3 deletions website/yarn.lock
Expand Up @@ -2558,9 +2558,9 @@ dashdash@^1.12.0:
assert-plus "^1.0.0"

date-fns@^2.16.1:
version "2.28.0"
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.28.0.tgz#9570d656f5fc13143e50c975a3b6bbeb46cd08b2"
integrity sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw==
version "2.29.3"
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8"
integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==

debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0:
version "2.6.9"
Expand Down