Skip to content

Commit 63c7b55

Browse files
✨ Add copy button
1 parent 6b21a4d commit 63c7b55

File tree

3 files changed

+54
-15
lines changed

3 files changed

+54
-15
lines changed

index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
footer {
2626
padding: 20px;
27-
margin: 50vh 0 0;
27+
margin: 20vh 0 0;
2828
text-align: center;
2929
border-top: 1px solid #000;
3030
}

src/class/HTMLCodeBlockElement.ts

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ export default class HTMLCodeBlockElement extends HTMLElement {
6363
};
6464
})();
6565
#a11yName: HTMLElement;
66+
#copyButton: HTMLButtonElement;
6667
#codeBlock: HTMLElement;
6768
#codeWrap: HTMLPreElement;
6869
/** Actual value of the accessor `value` */
@@ -88,9 +89,11 @@ export default class HTMLCodeBlockElement extends HTMLElement {
8889
this.textContent = '';
8990
this.#a11yName.textContent = this.#label;
9091
this.#slots.name.hidden = !this.#label;
92+
this.#slots.copyButton.hidden = !this.#controls;
9193
this.#codeBlock.textContent = '';
9294
this.#codeBlock.insertAdjacentHTML('afterbegin', markup);
9395
this.append(this.#a11yName);
96+
this.append(this.#copyButton);
9497
this.append(this.#codeWrap);
9598
}
9699

@@ -206,21 +209,8 @@ export default class HTMLCodeBlockElement extends HTMLElement {
206209
super();
207210

208211
/* -------------------------------------------------------------------------
209-
* Setup Shadow DOM contents
212+
* Setup DOM contents
210213
* ---------------------------------------------------------------------- */
211-
/**
212-
* The container of minimum text that will be read even
213-
* if the accessible name (label attribute value) is omitted.
214-
*/
215-
const a11yNamePrefix = (() => {
216-
const span = document.createElement('span');
217-
218-
span.id = 'semantics';
219-
span.hidden = true;
220-
span.textContent = 'Code Block';
221-
222-
return span;
223-
})()
224214
/** Container of accessible names (label attribute values). */
225215
const a11yName = (() => {
226216
const span = document.createElement('span');
@@ -230,6 +220,14 @@ export default class HTMLCodeBlockElement extends HTMLElement {
230220

231221
return span;
232222
})();
223+
const copyButton = (() => {
224+
const button = document.createElement('button');
225+
226+
button.slot = 'copy-button';
227+
button.textContent = 'Copy';
228+
229+
return button;
230+
})();
233231
const codeElm = (() => {
234232
const code = document.createElement('code');
235233

@@ -246,6 +244,24 @@ export default class HTMLCodeBlockElement extends HTMLElement {
246244

247245
return pre;
248246
})();
247+
248+
249+
/* -------------------------------------------------------------------------
250+
* Setup Shadow DOM contents
251+
* ---------------------------------------------------------------------- */
252+
/**
253+
* The container of minimum text that will be read even
254+
* if the accessible name (label attribute value) is omitted.
255+
*/
256+
const a11yNamePrefix = (() => {
257+
const span = document.createElement('span');
258+
259+
span.id = 'semantics';
260+
span.hidden = true;
261+
span.textContent = 'Code Block';
262+
263+
return span;
264+
})()
249265
const container = (() => {
250266
const div = document.createElement('div');
251267

@@ -271,6 +287,7 @@ export default class HTMLCodeBlockElement extends HTMLElement {
271287
this.#language = this.getAttribute('language') || '';
272288
this.#controls = this.getAttribute('controls') !== null;
273289
this.#a11yName = a11yName;
290+
this.#copyButton = copyButton;
274291
this.#codeBlock = codeElm;
275292
this.#codeWrap = preElm;
276293
}

src/utils/add-style.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ style.textContent = `
1515
position: absolute;
1616
top: 0;
1717
left: 0;
18+
z-index: 0;
1819
padding: 0 5px;
1920
max-width: 90%;
2021
color: #fff;
@@ -25,6 +26,27 @@ style.textContent = `
2526
background: #75758a;
2627
box-sizing: border-box;
2728
}
29+
30+
code-block button {
31+
all: unset;
32+
outline: revert;
33+
position: absolute;
34+
right: 0;
35+
top: 0;
36+
z-index: 1;
37+
padding: 10px;
38+
display: block;
39+
font-family: inherit;
40+
color: #fff;
41+
opacity: 0;
42+
mix-blend-mode: exclusion;
43+
}
44+
45+
code-block:hover button,
46+
code-block button:focus {
47+
opacity: 1;
48+
}
49+
2850
code-block pre,
2951
code-block code {
3052
font-family: inherit;

0 commit comments

Comments
 (0)