|
22 | 22 | >{{ fileName }}
|
23 | 23 | </Filename>
|
24 | 24 | <div class="container-general">
|
25 |
| - <button class="copy-button" @click="copyToClipboard">Copy</button> |
| 25 | + <button |
| 26 | + class="copy-button" |
| 27 | + :class="{ copied: isCopied }" |
| 28 | + @click="copyToClipboard" |
| 29 | + aria-label="Copy code to clipboard" |
| 30 | + > |
| 31 | + <svg |
| 32 | + v-if="!isCopied" |
| 33 | + xmlns="http://www.w3.org/2000/svg" |
| 34 | + viewbox="0 0 24 24" |
| 35 | + width="24" |
| 36 | + height="24" |
| 37 | + fill="currentColor" |
| 38 | + ><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 |
| 39 | + 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/> |
| 40 | + </svg> |
| 41 | + <svg |
| 42 | + v-if="isCopied" |
| 43 | + xmlns="http://www.w3.org/2000/svg" |
| 44 | + viewbox="0 0 24 24" |
| 45 | + width="24" |
| 46 | + height="24" |
| 47 | + fill="currentColor" |
| 48 | + ><path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"/> |
| 49 | + </svg> |
| 50 | + </button> |
26 | 51 | <!-- Do not add newlines in <pre>, as they'll appear in the rendered HTML. -->
|
27 | 52 | <pre><CodeBlock><template
|
28 | 53 | v-for="(line, index) in syntaxHighlightedLines"
|
@@ -56,6 +81,7 @@ export default {
|
56 | 81 | data() {
|
57 | 82 | return {
|
58 | 83 | syntaxHighlightedLines: [],
|
| 84 | + isCopied: false, |
59 | 85 | };
|
60 | 86 | },
|
61 | 87 | props: {
|
@@ -127,8 +153,15 @@ export default {
|
127 | 153 | const lines = this.content;
|
128 | 154 | const text = lines.join('\n');
|
129 | 155 | navigator.clipboard.writeText(text)
|
130 |
| - .then(() => console.log('Copied!')) |
131 |
| - .catch(err => console.error('Failed to copy: ', err)); |
| 156 | + .then(() => { |
| 157 | + this.isCopied = true; |
| 158 | + setTimeout(() => { |
| 159 | + this.isCopied = false; |
| 160 | + }, 1000); |
| 161 | + }) |
| 162 | + .catch(err => ( |
| 163 | + console.error('Failed to copy text: ', err) |
| 164 | + )); |
132 | 165 | },
|
133 | 166 | },
|
134 | 167 | };
|
@@ -206,11 +239,47 @@ code {
|
206 | 239 |
|
207 | 240 | .container-general {
|
208 | 241 | overflow: auto;
|
| 242 | + position: relative; |
209 | 243 | }
|
210 | 244 |
|
211 | 245 | .container-general,
|
212 | 246 | pre {
|
213 | 247 | flex-grow: 1;
|
214 | 248 | }
|
215 | 249 |
|
| 250 | +.copy-button { |
| 251 | + position: absolute; |
| 252 | + top: 1em; |
| 253 | + right: 1em; |
| 254 | + background: var(--color-syntax-clipboard-bg, #e0e0e0); |
| 255 | + border: none; |
| 256 | + border-radius: 6px; |
| 257 | + padding: 7px 6px; |
| 258 | + cursor: pointer; |
| 259 | + display: none; |
| 260 | + transition: all 0.2s ease-in-out; |
| 261 | +} |
| 262 | +
|
| 263 | +.copy-button svg { |
| 264 | + width: 24px; |
| 265 | + height: 24px; |
| 266 | + opacity: 0.8; |
| 267 | +} |
| 268 | +
|
| 269 | +.copy-button:hover { |
| 270 | + background-color: var(--code-syntax-clipboard-hover-bg, #d0d0d0); |
| 271 | +} |
| 272 | +
|
| 273 | +.copy-button:hover svg { |
| 274 | + opacity: 1; |
| 275 | +} |
| 276 | +
|
| 277 | +.copy-button.copied svg { |
| 278 | + color: var(--color-syntax-clipboard-check-color, #007aff); |
| 279 | +} |
| 280 | +
|
| 281 | +.container-general:hover .copy-button { |
| 282 | + display: flex; |
| 283 | +} |
| 284 | +
|
216 | 285 | </style>
|
0 commit comments