Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 42 additions & 1 deletion _layouts/default.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
{{ content }}
</div>
</div>

<div class="visually-hidden" aria-live="polite" role="status"></div>

<script>
// open external links in new tab
var links = document.links;
Expand All @@ -25,6 +26,46 @@
}
}
</script>
<script>
// copy to clipboard button on code blocks
if (navigator.clipboard && typeof navigator.clipboard.writeText === 'function') {
var statusRegion = document.querySelector('[aria-live="polite"][role="status"]');
var preBlocks = document.querySelectorAll('pre.highlight');
var preBlocksLength = preBlocks.length;
var j;
for (j = 0; j < preBlocksLength; j++) {
(function (pre) {
var wrapper = document.createElement('div');
wrapper.className = 'pre-wrapper';
Comment on lines +38 to +39

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested the wrapping on the live site, just the wrapper code with no other changes, and didn't see any visible spacing shift between code blocks and surrounding content. The margin-collapsing thing is real in principle but doesn't apply here since the surrounding markdown elements all have their own margins.

Gonna skip this one. If you spot a regression after merge let me know and I'll handle it in CSS instead of the computed-style JS approach Copilot suggested.

pre.parentNode.insertBefore(wrapper, pre);
wrapper.appendChild(pre);

var button = document.createElement('button');
button.className = 'copy-btn';
button.type = 'button';
button.textContent = 'Copy';

button.addEventListener('click', function () {
var code = pre.querySelector('code');
var text = code ? (code.textContent || '') : (pre.textContent || '');
navigator.clipboard.writeText(text).then(function () {
button.textContent = 'Copied';
statusRegion.textContent = '';
statusRegion.textContent = 'Copied to clipboard';
setTimeout(function () { button.textContent = 'Copy'; }, 1500);
}).catch(function () {
button.textContent = 'Failed';
statusRegion.textContent = '';
statusRegion.textContent = 'Copy to clipboard failed';
setTimeout(function () { button.textContent = 'Copy'; }, 1500);
});
Comment on lines +51 to +61

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Clearing the status region before setting the new message in both the success and failure branches.

Quick heads up though, in my earlier testing VoiceOver on macOS wasn't reliably announcing the aria-live region at all, so this fix is more for NVDA/JAWS than VoiceOver. It's a recognized pattern so I added it, but the VoiceOver gap from before is still a thing.

});

wrapper.appendChild(button);
})(preBlocks[j]);
}
}
</script>
{% include analytics.html %}
</body>
</html>
52 changes: 51 additions & 1 deletion main.css
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ pre > code:focus {
} */

/* Code */
/* .highlight .hll { background-color: #ffc;
/* .highlight .hll { background-color: #ffc;
.highlight .c { color: #999; }
.highlight .err { color: #a00; background-color: #faa }
.highlight .k { color: #069; }
Expand Down Expand Up @@ -699,3 +699,53 @@ pre.highlight {
.highlight .gi {
color: #a6e22e;
}

/* Copy to clipboard button */
.pre-wrapper {
position: relative;
}

.copy-btn {
position: absolute;
top: 8px;
right: 8px;
Comment on lines +709 to +711

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. I’d prefer to avoid sticky if possible, so let’s move the button outside the scrollable element instead. That’s how GitHub handles copy buttons in code blocks. It’s a slightly bigger change, but I think it’s worth it here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense to go with the wrapper approach instead of sticky. The JS wraps each <pre> in a .pre-wrapper div at runtime, then positions the button on the wrapper so it stays pinned when the code block scrolls horizontally. I tested it on the long meta tags block and the button holds its position now.

min-width: 60px;
padding: 4px 10px;
font-family: inherit;
font-size: 12px;
color: #abb2bf;
background: transparent;
border: 1px solid #abb2bf;
border-radius: 4px;
cursor: pointer;
opacity: 0;
text-align: center;
transition: opacity 0.15s ease-in-out;
Comment thread
joshbuchea marked this conversation as resolved.
pointer-events: none;
}

.pre-wrapper:hover .copy-btn,
.copy-btn:focus {
opacity: 1;
pointer-events: auto;
}
Comment thread
joshbuchea marked this conversation as resolved.

.copy-btn:hover {
background: rgba(171, 178, 191, 0.1);
}

@media (hover: none) {
.copy-btn {
opacity: 1;
pointer-events: auto;
}
}

.visually-hidden {
clip-path: inset(50%);
height: 1px;
width: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
}