Skip to content

Commit 055c422

Browse files
Add copy button to code blocks in documentation (#9830)
* Add copy button to code blocks for improved documentation usability * Add copy button to code blocks for improved documentation usability * Add copy button to code blocks for improved documentation usability * Make "Copy" button smaller --------- Co-authored-by: Bruno Alla <[email protected]>
1 parent d0a5d5e commit 055c422

File tree

4 files changed

+63
-0
lines changed

4 files changed

+63
-0
lines changed

docs_theme/css/copy-button.css

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
.copy-block-button {
2+
position: absolute;
3+
top: 6px;
4+
right: 6px;
5+
z-index: 10;
6+
white-space: nowrap; /* Prevent text wrap */
7+
}
8+
9+
/* Ensure the PRE container provides positioning context */
10+
pre {
11+
position: relative;
12+
padding-top: 35px; /* Room for the button */
13+
overflow-x: auto; /* Allow horizontal scrolling */
14+
}
15+
16+
/* Code block scrollable */
17+
pre code {
18+
display: block;
19+
overflow-x: auto;
20+
}
21+
22+
/*
23+
The MkDocs/DRF theme injects a <span> inside buttons and applies
24+
a text color that overrides btn-inverse defaults.
25+
This override is intentionally scoped and limited to color only.
26+
*/
27+
.copy-block-button,
28+
.copy-block-button span {
29+
color: #ffffff !important;
30+
}

docs_theme/js/copy-button.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
document.addEventListener("DOMContentLoaded", function () {
2+
document.querySelectorAll("pre > code").forEach(function (codeBlock) {
3+
const button = document.createElement("button");
4+
button.className = "copy-block-button btn btn-inverse btn-mini";
5+
button.type = "button";
6+
button.textContent = "Copy";
7+
8+
button.addEventListener("click", function () {
9+
navigator.clipboard.writeText(codeBlock.textContent)
10+
.then(() => {
11+
button.textContent = "Copied!";
12+
setTimeout(() => button.textContent = "Copy", 1200);
13+
})
14+
.catch(() => {
15+
button.textContent = "Failed";
16+
setTimeout(() => button.textContent = "Copy", 1200);
17+
});
18+
});
19+
20+
const pre = codeBlock.parentNode;
21+
pre.style.position = "relative";
22+
pre.appendChild(button);
23+
});
24+
});

docs_theme/main.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
<link href="{{ 'css/bootstrap.css'|url }}" rel="stylesheet">
1717
<link href="{{ 'css/bootstrap-responsive.css'|url }}" rel="stylesheet">
1818
<link href="{{ 'css/default.css'|url }}" rel="stylesheet">
19+
{% for path in config.extra_css %}
20+
<link href="{{ path|url }}" rel="stylesheet">
21+
{% endfor %}
1922

2023

2124
<script type="text/javascript">

mkdocs.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,9 @@ nav:
8686
- 'Kickstarter Announcement': 'community/kickstarter-announcement.md'
8787
- 'Mozilla Grant': 'community/mozilla-grant.md'
8888
- 'Jobs': 'community/jobs.md'
89+
90+
extra_css:
91+
- css/copy-button.css
92+
93+
extra_javascript:
94+
- js/copy-button.js

0 commit comments

Comments
 (0)