diff --git a/css/style.css b/css/style.css index 63ee3a3..3dbaeab 100644 --- a/css/style.css +++ b/css/style.css @@ -1648,9 +1648,8 @@ footer.footer-modern a:hover { width: 32px; height: 32px; padding: 0; - display: inline-flex; - align-items: center; - justify-content: center; + display: grid; + place-items: center; border: 1px solid var(--border-color); border-radius: var(--radius-sm); background: var(--bg-subtle); @@ -1677,14 +1676,34 @@ footer.footer-modern a:hover { border-color: var(--accent); } -.code-copy i { +.code-copy svg { + display: block; +} + +/* "Copied" toast — pops up just left of the button */ +.code-copy-toast { + position: absolute; + top: 0.5rem; + right: calc(0.5rem + 32px + 8px); /* clears the 32px button + gap */ + height: 32px; display: flex; align-items: center; - justify-content: center; - width: 100%; - height: 100%; - font-size: 0.95rem; - line-height: 1; + padding: 0 0.6rem; + border-radius: var(--radius-sm); + background: var(--accent); + color: var(--accent-contrast); + font-size: var(--font-size-xs); + font-weight: 600; + white-space: nowrap; + pointer-events: none; + opacity: 0; + transform: translateX(6px); + transition: opacity 0.15s ease, transform 0.15s ease; +} + +.code-copy-toast.is-visible { + opacity: 1; + transform: translateX(0); } /* Touch devices have no hover — keep the button discoverable */ diff --git a/js/blowdit.js b/js/blowdit.js index ae4d4df..b499a4d 100644 --- a/js/blowdit.js +++ b/js/blowdit.js @@ -561,6 +561,16 @@ }); } + // Inline SVGs — centred in their own viewBox, so no icon-font baseline / + // side-bearing offsets to fight. + var SVG_COPY = '' + + ''; + var SVG_CHECK = ''; + function enhance(pre) { // Skip if already wrapped if (pre.parentNode && pre.parentNode.classList && @@ -575,7 +585,12 @@ btn.type = 'button'; btn.className = 'code-copy'; btn.setAttribute('aria-label', T.copyCode); - btn.innerHTML = ''; + btn.innerHTML = SVG_COPY; + + // "Copied" toast that pops up next to the button + var toast = document.createElement('span'); + toast.className = 'code-copy-toast'; + toast.textContent = T.copied; var resetTimer = null; btn.addEventListener('click', function () { @@ -583,18 +598,21 @@ var text = (code ? code.textContent : pre.textContent) || ''; copyText(text).then(function () { btn.classList.add('is-copied'); - btn.innerHTML = ''; + btn.innerHTML = SVG_CHECK; btn.setAttribute('aria-label', T.copied); + toast.classList.add('is-visible'); clearTimeout(resetTimer); resetTimer = setTimeout(function () { btn.classList.remove('is-copied'); - btn.innerHTML = ''; + btn.innerHTML = SVG_COPY; btn.setAttribute('aria-label', T.copyCode); - }, 1800); + toast.classList.remove('is-visible'); + }, 1000); }).catch(function () {}); }); wrap.appendChild(btn); + wrap.appendChild(toast); } var pres = document.querySelectorAll('.content pre, .tab-panel pre');