From 5b73bd00588d8c206ec78c8ab14492a206980d87 Mon Sep 17 00:00:00 2001 From: nkrambo Date: Fri, 30 May 2025 15:45:50 -0700 Subject: [PATCH] fix(CodeBlock): update copy states --- assets/images/icon-copy.svg | 1 + .../new-javascripts/application.js | 43 ++++++++++++------- .../stylesheets/new-stylesheets/_syntax.scss | 40 +++++++++++------ .../stylesheets/new-stylesheets/_themes.scss | 8 ++++ 4 files changed, 65 insertions(+), 27 deletions(-) create mode 100644 assets/images/icon-copy.svg diff --git a/assets/images/icon-copy.svg b/assets/images/icon-copy.svg new file mode 100644 index 000000000..bdee8facd --- /dev/null +++ b/assets/images/icon-copy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/javascripts/new-javascripts/application.js b/assets/javascripts/new-javascripts/application.js index 4b966bfae..955afc964 100644 --- a/assets/javascripts/new-javascripts/application.js +++ b/assets/javascripts/new-javascripts/application.js @@ -45,28 +45,41 @@ document.addEventListener('DOMContentLoaded', function () { if (navigator && navigator.clipboard) { const codeBlocks = document.querySelectorAll( ':is([class^="language-"] pre.highlight, .code-box pre code)', - ) + ); + + const copyIcon = ``; + const copiedIcon = ``; codeBlocks.forEach((codeBlock) => { - const button = document.createElement('button') - const codeElement = codeBlock.querySelector('code') || codeBlock - const container = codeBlock.parentElement + const button = document.createElement('button'); + const codeElement = codeBlock.querySelector('code') || codeBlock; + const container = codeBlock.parentElement; - container.style.position = 'relative' - container.appendChild(button) - button.innerText = 'copy' + button.classList.add('copy-button'); + container.appendChild(button); + button.innerHTML = copyIcon button.addEventListener('mousedown', async () => { - const originalText = button.innerText + const originalIcon = copyIcon; // Store the original icon - await navigator.clipboard.writeText(codeElement.innerText) - button.innerText = 'copied!' + try { + await navigator.clipboard.writeText(codeElement.innerText); - setTimeout(() => { - button.innerText = originalText - }, 1000) - }) - }) + button.classList.add('copied'); + button.innerHTML = copiedIcon; + + setTimeout(() => { + button.classList.remove('copied'); + button.innerHTML = originalIcon; + }, 1000); + } catch (err) { + console.error('Failed to copy text: ', err); + setTimeout(() => { + button.innerHTML = originalIcon; // Revert to original icon + }, 1000); + } + }); + }); } // Check for reduced motion setting diff --git a/assets/stylesheets/new-stylesheets/_syntax.scss b/assets/stylesheets/new-stylesheets/_syntax.scss index bce4d85a8..50d0da39f 100644 --- a/assets/stylesheets/new-stylesheets/_syntax.scss +++ b/assets/stylesheets/new-stylesheets/_syntax.scss @@ -3,27 +3,43 @@ position: relative; button { - background-color: #c5c5c5; - color: white; - border: 0; - padding: 5px 8px; - font-family: sans-serif; - transition: background-color 0.2s; - cursor: pointer; position: absolute; - top: 0; - right: 0; + top: 1em; + right: 1em; + background: none; + border: medium; + cursor: pointer; + padding: 7px 6px; + border-radius: 6px; + transition: all 0.2s ease-in-out; display: none; - border-radius: 0 10px 0 0; + background-color: var(--color-syntax-clipboard-bg); + + svg { + width: 20px; + height: 20px; + opacity: 0.8; + } + + &.copied { + svg { + color: var(--color-syntax-clipboard-check-color); + } + } + &:hover { - background-color: #868686; + background-color: var(--color-syntax-clipboard-hover-bg); + + svg { + opacity: 1; + } } } &:hover { button { - display: block; + display: flex; } } } diff --git a/assets/stylesheets/new-stylesheets/_themes.scss b/assets/stylesheets/new-stylesheets/_themes.scss index fa9171512..55392a861 100644 --- a/assets/stylesheets/new-stylesheets/_themes.scss +++ b/assets/stylesheets/new-stylesheets/_themes.scss @@ -70,6 +70,10 @@ --nav-scroller-gradient-end: #fff; // syntax + --color-syntax-clipboard-bg: rgb(223, 223, 247); + --color-syntax-clipboard-hover-bg: rgb(216, 216, 242); + --color-syntax-clipboard-check-color: rgb(12, 156, 12); + --color-syntax-attributes: rgb(148, 113, 0); --color-syntax-characters: rgb(39, 42, 216); --color-syntax-comments: rgb(112, 127, 140); @@ -165,6 +169,10 @@ --nav-scroller-gradient-end: #000; // syntax + --color-syntax-clipboard-bg: rgb(71, 79, 110); + --color-syntax-clipboard-hover-bg: rgb(80, 89, 124); + --color-syntax-clipboard-check-color: rgb(11, 242, 11); + --color-syntax-attributes: rgb(204, 151, 104); --color-syntax-characters: rgb(217, 201, 124); --color-syntax-comments: rgb(127, 140, 152);