Skip to content

Commit bc1fdc1

Browse files
author
Jesse Haigh
committed
add failure to copy logic and cross icon
1 parent fd410e7 commit bc1fdc1

File tree

2 files changed

+59
-11
lines changed

2 files changed

+59
-11
lines changed

src/components/ContentNode/CodeListing.vue

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@
2525
<button
2626
v-if="copyToClipboard"
2727
class="copy-button"
28-
:class="{ copied: isCopied }"
28+
:class="copyState"
2929
@click="copyCodeToClipboard"
3030
:aria-label="$t('icons.copy')"
3131
:title="$t('icons.copy')"
3232
>
33-
<CopyIcon v-if="!isCopied" class="copy-icon"/>
34-
<CheckmarkIcon v-if="isCopied" class="checkmark-icon"/>
33+
<CopyIcon v-if="copyState === 'idle'" class="copy-icon"/>
34+
<CheckmarkIcon v-if="copyState === 'success'" class="checkmark-icon"/>
35+
<CrossIcon v-if="copyState === 'failure'" class="cross-icon"/>
3536
</button>
3637
<!-- Do not add newlines in <pre>, as they'll appear in the rendered HTML. -->
3738
<pre><CodeBlock><template
@@ -58,6 +59,7 @@ import Language from 'docc-render/constants/Language';
5859
import CodeBlock from 'docc-render/components/CodeBlock.vue';
5960
import CopyIcon from 'docc-render/components/Icons/CopyIcon.vue';
6061
import CheckmarkIcon from 'docc-render/components/Icons/CheckmarkIcon.vue';
62+
import CrossIcon from 'docc-render/components/Icons/CrossIcon.vue';
6163
import { highlightContent, registerHighlightLanguage } from 'docc-render/utils/syntax-highlight';
6264
6365
import CodeListingFilename from './CodeListingFilename.vue';
@@ -69,11 +71,12 @@ export default {
6971
CodeBlock,
7072
CopyIcon,
7173
CheckmarkIcon,
74+
CrossIcon,
7275
},
7376
data() {
7477
return {
7578
syntaxHighlightedLines: [],
76-
isCopied: false,
79+
copyState: 'idle',
7780
};
7881
},
7982
props: {
@@ -151,14 +154,17 @@ export default {
151154
copyCodeToClipboard() {
152155
navigator.clipboard.writeText(this.copyableText)
153156
.then(() => {
154-
this.isCopied = true;
157+
this.copyState = 'success';
158+
})
159+
.catch((err) => {
160+
console.error('Failed to copy text: ', err);
161+
this.copyState = 'failure';
162+
})
163+
.finally(() => {
155164
setTimeout(() => {
156-
this.isCopied = false;
165+
this.copyState = 'idle';
157166
}, 1000);
158-
})
159-
.catch(err => (
160-
console.error('Failed to copy text: ', err)
161-
));
167+
});
162168
},
163169
},
164170
};
@@ -289,9 +295,14 @@ pre {
289295
fill: var(--color-figure-gray);
290296
}
291297
292-
.copy-button.copied .checkmark-icon {
298+
.copy-button.success .checkmark-icon {
293299
color: var(--color-figure-blue);
294300
fill: currentColor;
295301
}
296302
303+
.copy-button.failure .cross-icon {
304+
color: var(--color-figure-red);
305+
fill: currentColor;
306+
}
307+
297308
</style>

src/components/Icons/CrossIcon.vue

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<!--
2+
This source file is part of the Swift.org open source project
3+
4+
Copyright (c) 2025 Apple Inc. and the Swift project authors
5+
Licensed under Apache License v2.0 with Runtime Library Exception
6+
7+
See https://swift.org/LICENSE.txt for license information
8+
See https://swift.org/CONTRIBUTORS.txt for Swift project authors
9+
-->
10+
11+
<template>
12+
<SVGIcon
13+
class="CrossIcon"
14+
viewBox="0 0 24 24"
15+
themeId="cross"
16+
>
17+
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41
18+
10.59 12 5 17.59 6.41 19 12 13.41
19+
17.59 19 19 17.59 13.41 12z"/>
20+
</SVGIcon>
21+
</template>
22+
23+
<script>
24+
import SVGIcon from 'docc-render/components/SVGIcon.vue';
25+
26+
export default {
27+
name: 'CrossIcon',
28+
components: { SVGIcon },
29+
};
30+
</script>
31+
32+
<style scoped lang="scss">
33+
.CrossIcon {
34+
opacity: 1;
35+
stroke: currentColor;
36+
}
37+
</style>

0 commit comments

Comments
 (0)