From 0ca1e96d6bf75b17988dd60d4e500d7a86a5985a Mon Sep 17 00:00:00 2001 From: Tarun Chauhan Date: Tue, 10 Jan 2023 21:35:00 +0530 Subject: [PATCH 1/5] feat: add copy to clipboard in code blocks --- website/siteConfig.js | 7 +++- website/static/css/code-block-buttons.css | 42 ++++++++++++++++++++ website/static/js/code-block-buttons.js | 47 +++++++++++++++++++++++ 3 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 website/static/css/code-block-buttons.css create mode 100644 website/static/js/code-block-buttons.js diff --git a/website/siteConfig.js b/website/siteConfig.js index b4d93ab11a45..9c20ded7e76e 100644 --- a/website/siteConfig.js +++ b/website/siteConfig.js @@ -56,9 +56,14 @@ 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", + "/css/code-block-buttons.css", ], algolia: { apiKey: process.env.ALGOLIA_PRETTIER_API_KEY, diff --git a/website/static/css/code-block-buttons.css b/website/static/css/code-block-buttons.css new file mode 100644 index 000000000000..bf2c1246d55c --- /dev/null +++ b/website/static/css/code-block-buttons.css @@ -0,0 +1,42 @@ +/* "Copy" code block button */ +pre { + position: relative; +} + +pre .btnIcon { + position: absolute; + top: -5px; + right: 16px; + z-index: 2; + cursor: pointer; + border: 1px solid transparent; + padding: 0; + background-color: transparent; + height: 30px; + transition: all 0.25s ease-out; + display: none; +} + +pre .btnIcon:hover { + text-decoration: none; + display: block; +} + +pre code[class*="language-"]:hover + .btnIcon { + display: block; +} + +.btnIcon__body { + align-items: center; + display: flex; + color: #535b64; +} + +.btnIcon svg { + fill: currentColor; + margin-right: 0.4em; +} + +.btnIcon__label { + font-size: 11px; +} diff --git a/website/static/js/code-block-buttons.js b/website/static/js/code-block-buttons.js new file mode 100644 index 000000000000..68f1953d1ce9 --- /dev/null +++ b/website/static/js/code-block-buttons.js @@ -0,0 +1,47 @@ +"use strict"; + +window.addEventListener("load", () => { + function button(label, ariaLabel, icon, className) { + const btn = document.createElement("button"); + btn.classList.add("btnIcon", className); + btn.setAttribute("type", "button"); + btn.setAttribute("aria-label", ariaLabel); + btn.innerHTML = + '
' + + icon + + '' + + label + + "" + + "
"; + return btn; + } + + function addButtons(codeBlockSelector, btn) { + for (const code of document.querySelectorAll(codeBlockSelector)) { + code.parentNode.appendChild(btn.cloneNode(true)); + } + } + + const copyIcon = + ''; + + addButtons( + ".hljs", + button("Copy", "Copy code to clipboard", copyIcon, "btnClipboard") + ); + // eslint-disable-next-line no-undef + const clipboard = new ClipboardJS(".btnClipboard", { + target(trigger) { + return trigger.parentNode.querySelector("code"); + }, + }); + + clipboard.on("success", (event) => { + event.clearSelection(); + const textEl = event.trigger.querySelector(".btnIcon__label"); + textEl.textContent = "Copied"; + setTimeout(() => { + textEl.textContent = "Copy"; + }, 2000); + }); +}); From 30c26eb18e5b920899d2c506c6a245a1d968fced Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Thu, 12 Jan 2023 14:54:12 +0800 Subject: [PATCH 2/5] Use the same style as docusaurus v2 --- website/static/css/code-block-buttons.css | 73 +++++++++++------- website/static/js/code-block-buttons.js | 90 ++++++++++++----------- website/yarn.lock | 6 +- 3 files changed, 99 insertions(+), 70 deletions(-) diff --git a/website/static/css/code-block-buttons.css b/website/static/css/code-block-buttons.css index bf2c1246d55c..f1aa6ec3e413 100644 --- a/website/static/css/code-block-buttons.css +++ b/website/static/css/code-block-buttons.css @@ -1,42 +1,63 @@ -/* "Copy" code block button */ -pre { +/* "Copy" code block button, style from docusaurus v2 */ + +.code-block-with-actions { position: relative; } -pre .btnIcon { +.code-block-actions { position: absolute; - top: -5px; - right: 16px; - z-index: 2; - cursor: pointer; - border: 1px solid transparent; - padding: 0; - background-color: transparent; - height: 30px; - transition: all 0.25s ease-out; - display: none; + top: 10px; + right: 10px; } -pre .btnIcon:hover { - text-decoration: none; - display: block; +.code-block-copy-button { + width: 32px; + height: 32px; + border: 1px solid #dadde1; + border-radius: 6px; + display: flex; + transition: opacity .2s ease-in-out; + opacity: 0; + position: relative; + cursor: pointer; + color: #393A34; + background-color: #f6f8fa; } -pre code[class*="language-"]:hover + .btnIcon { - display: block; +.code-block-with-actions:hover .code-block-copy-button { + opacity: 0.4; } -.btnIcon__body { - align-items: center; - display: flex; - color: #535b64; +.code-block-with-actions:hover .code-block-copy-button:hover { + opacity: 1; } -.btnIcon svg { +.code-block-copy-button__icon { fill: currentColor; - margin-right: 0.4em; + position: absolute; + width: 18px; + height: 18px; + left: 0; + right: 0; + top: 0; + bottom: 0; + margin: auto; + transition: .15s; +} + +.code-block-copy-button__icon--copied { + color: #00d600; + opacity: 0; + transform: scale(.33); +} + +.code-block-copy-button--copied .code-block-copy-button__icon--copy { + opacity: 0; + transform: scale(.33); } -.btnIcon__label { - font-size: 11px; +.code-block-copy-button--copied .code-block-copy-button__icon--copied { + transition-delay: 75ms; + transform: scale(1); + opacity: 1; } diff --git a/website/static/js/code-block-buttons.js b/website/static/js/code-block-buttons.js index 68f1953d1ce9..c4c1c13a350c 100644 --- a/website/static/js/code-block-buttons.js +++ b/website/static/js/code-block-buttons.js @@ -1,47 +1,55 @@ +/* global ClipboardJS */ + "use strict"; -window.addEventListener("load", () => { - function button(label, ariaLabel, icon, className) { - const btn = document.createElement("button"); - btn.classList.add("btnIcon", className); - btn.setAttribute("type", "button"); - btn.setAttribute("aria-label", ariaLabel); - btn.innerHTML = - '
' + - icon + - '' + - label + - "" + - "
"; - return btn; - } +(function () { + const CONTAINER_CLASS_NAME = "code-block-with-actions"; + const ACTIONS_CONATINER_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 ATIA_LABEL = "Copy code to clipboard"; + const ATIA_LABEL_COPIED = "Copied"; - function addButtons(codeBlockSelector, btn) { - for (const code of document.querySelectorAll(codeBlockSelector)) { - code.parentNode.appendChild(btn.cloneNode(true)); - } - } + function init(codeBlock) { + const container = codeBlock.parentNode; + container.classList.add(CONTAINER_CLASS_NAME); - const copyIcon = - ''; - - addButtons( - ".hljs", - button("Copy", "Copy code to clipboard", copyIcon, "btnClipboard") - ); - // eslint-disable-next-line no-undef - const clipboard = new ClipboardJS(".btnClipboard", { - target(trigger) { - return trigger.parentNode.querySelector("code"); - }, - }); + const actionsContainer = Object.assign(document.createElement("div"), { + className: ACTIONS_CONATINER_CLASS_NAME, + }); + const copyButton = Object.assign(document.createElement("button"), { + className: COPY_BUTTON_CLASS_NAME, + type: "button", + innerHTML: + `` + + ``, + }); + copyButton.setAttribute("aria-label", ATIA_LABEL); - clipboard.on("success", (event) => { - event.clearSelection(); - const textEl = event.trigger.querySelector(".btnIcon__label"); - textEl.textContent = "Copied"; - setTimeout(() => { - textEl.textContent = "Copy"; - }, 2000); + new ClipboardJS(copyButton, { target: () => codeBlock }).on( + "success", + (event) => { + event.clearSelection(); + copyButton.classList.add(COPY_BUTTON_COPIED_CLASS_NAME); + copyButton.setAttribute("aria-label", ATIA_LABEL_COPIED); + + setTimeout(() => { + copyButton.classList.remove(COPY_BUTTON_COPIED_CLASS_NAME); + copyButton.setAttribute("aria-label", ATIA_LABEL); + }, 2000); + } + ); + + actionsContainer.appendChild(copyButton); + container.appendChild(actionsContainer); + } + + window.addEventListener("load", () => { + for (const codeBlock of document.querySelectorAll("pre > code.hljs")) { + init(codeBlock); + } }); -}); +})(); diff --git a/website/yarn.lock b/website/yarn.lock index 3abc0b3ae398..99a7ef961a5f 100644 --- a/website/yarn.lock +++ b/website/yarn.lock @@ -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" From bbc3168386cb261632106d38450da7ebf4838575 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Thu, 12 Jan 2023 15:02:21 +0800 Subject: [PATCH 3/5] Remove style from siteConfig.js --- website/siteConfig.js | 1 - website/static/css/code-block-buttons.css | 10 +++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/website/siteConfig.js b/website/siteConfig.js index 9c20ded7e76e..a8046d438bde 100644 --- a/website/siteConfig.js +++ b/website/siteConfig.js @@ -63,7 +63,6 @@ const siteConfig = { ], stylesheets: [ "//unpkg.com/@sandhose/prettier-animated-logo@1.0.3/dist/wide.css", - "/css/code-block-buttons.css", ], algolia: { apiKey: process.env.ALGOLIA_PRETTIER_API_KEY, diff --git a/website/static/css/code-block-buttons.css b/website/static/css/code-block-buttons.css index f1aa6ec3e413..73207981c241 100644 --- a/website/static/css/code-block-buttons.css +++ b/website/static/css/code-block-buttons.css @@ -16,11 +16,11 @@ border: 1px solid #dadde1; border-radius: 6px; display: flex; - transition: opacity .2s ease-in-out; + transition: opacity 0.2s ease-in-out; opacity: 0; position: relative; cursor: pointer; - color: #393A34; + color: #393a34; background-color: #f6f8fa; } @@ -42,18 +42,18 @@ top: 0; bottom: 0; margin: auto; - transition: .15s; + transition: 0.15s; } .code-block-copy-button__icon--copied { color: #00d600; opacity: 0; - transform: scale(.33); + transform: scale(0.33); } .code-block-copy-button--copied .code-block-copy-button__icon--copy { opacity: 0; - transform: scale(.33); + transform: scale(0.33); } .code-block-copy-button--copied .code-block-copy-button__icon--copied { From 952fd940a0ce1b8c7924c17c79f49d2d99cb65c0 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Thu, 12 Jan 2023 15:06:12 +0800 Subject: [PATCH 4/5] Fix typo --- website/static/js/code-block-buttons.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/website/static/js/code-block-buttons.js b/website/static/js/code-block-buttons.js index c4c1c13a350c..899c01ee1d16 100644 --- a/website/static/js/code-block-buttons.js +++ b/website/static/js/code-block-buttons.js @@ -4,21 +4,21 @@ (function () { const CONTAINER_CLASS_NAME = "code-block-with-actions"; - const ACTIONS_CONATINER_CLASS_NAME = "code-block-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 ATIA_LABEL = "Copy code to clipboard"; - const ATIA_LABEL_COPIED = "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_CONATINER_CLASS_NAME, + className: ACTIONS_CONTAINER_CLASS_NAME, }); const copyButton = Object.assign(document.createElement("button"), { className: COPY_BUTTON_CLASS_NAME, @@ -27,18 +27,18 @@ `` + ``, }); - copyButton.setAttribute("aria-label", ATIA_LABEL); + 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", ATIA_LABEL_COPIED); + copyButton.setAttribute("aria-label", ARIA_LABEL_COPIED); setTimeout(() => { copyButton.classList.remove(COPY_BUTTON_COPIED_CLASS_NAME); - copyButton.setAttribute("aria-label", ATIA_LABEL); + copyButton.setAttribute("aria-label", ARIA_LABEL); }, 2000); } ); From 1bc88fea6933d74b2ac06b55579d76d31379d3cc Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Thu, 12 Jan 2023 15:09:47 +0800 Subject: [PATCH 5/5] Disable button on copied --- website/static/js/code-block-buttons.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/website/static/js/code-block-buttons.js b/website/static/js/code-block-buttons.js index 899c01ee1d16..dd09911f34b6 100644 --- a/website/static/js/code-block-buttons.js +++ b/website/static/js/code-block-buttons.js @@ -35,10 +35,12 @@ 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); } );