Skip to content

Commit 824ad88

Browse files
authored
feat: swizzle copy button to fix copy/paste with customizable value (#2134)
1 parent ff6b7f8 commit 824ad88

File tree

2 files changed

+99
-0
lines changed

2 files changed

+99
-0
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import React, {useCallback, useState, useRef, useEffect} from 'react';
2+
import clsx from 'clsx';
3+
import copy from 'copy-text-to-clipboard';
4+
import {translate} from '@docusaurus/Translate';
5+
import type {Props} from '@theme/CodeBlock/CopyButton';
6+
import IconCopy from '@theme/Icon/Copy';
7+
import IconSuccess from '@theme/Icon/Success';
8+
9+
import styles from './styles.module.css';
10+
import { parseCustomizableValuesToString } from '@site/src/components/CustomizableValue';
11+
12+
export default function CopyButton({code, className}: Props): JSX.Element {
13+
const [isCopied, setIsCopied] = useState(false);
14+
const copyTimeout = useRef<number | undefined>(undefined);
15+
const handleCopyCode = useCallback(() => {
16+
copy(parseCustomizableValuesToString(code));
17+
setIsCopied(true);
18+
copyTimeout.current = window.setTimeout(() => {
19+
setIsCopied(false);
20+
}, 1000);
21+
}, [code]);
22+
23+
useEffect(() => () => window.clearTimeout(copyTimeout.current), []);
24+
25+
return (
26+
<button
27+
type="button"
28+
aria-label={
29+
isCopied
30+
? translate({
31+
id: 'theme.CodeBlock.copied',
32+
message: 'Copied',
33+
description: 'The copied button label on code blocks',
34+
})
35+
: translate({
36+
id: 'theme.CodeBlock.copyButtonAriaLabel',
37+
message: 'Copy code to clipboard',
38+
description: 'The ARIA label for copy code blocks button',
39+
})
40+
}
41+
title={translate({
42+
id: 'theme.CodeBlock.copy',
43+
message: 'Copy',
44+
description: 'The copy button label on code blocks',
45+
})}
46+
className={clsx(
47+
'clean-btn',
48+
className,
49+
styles.copyButton,
50+
isCopied && styles.copyButtonCopied,
51+
)}
52+
onClick={handleCopyCode}>
53+
<span className={styles.copyButtonIcons} aria-hidden="true">
54+
<IconCopy className={styles.copyButtonIcon} />
55+
<IconSuccess className={styles.copyButtonSuccessIcon} />
56+
</span>
57+
</button>
58+
);
59+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
:global(.theme-code-block:hover) .copyButtonCopied {
2+
opacity: 1 !important;
3+
}
4+
5+
.copyButtonIcons {
6+
position: relative;
7+
width: 1.125rem;
8+
height: 1.125rem;
9+
}
10+
11+
.copyButtonIcon,
12+
.copyButtonSuccessIcon {
13+
position: absolute;
14+
top: 0;
15+
left: 0;
16+
fill: currentColor;
17+
opacity: inherit;
18+
width: inherit;
19+
height: inherit;
20+
transition: all var(--ifm-transition-fast) ease;
21+
}
22+
23+
.copyButtonSuccessIcon {
24+
top: 50%;
25+
left: 50%;
26+
transform: translate(-50%, -50%) scale(0.33);
27+
opacity: 0;
28+
color: #00d600;
29+
}
30+
31+
.copyButtonCopied .copyButtonIcon {
32+
transform: scale(0.33);
33+
opacity: 0;
34+
}
35+
36+
.copyButtonCopied .copyButtonSuccessIcon {
37+
transform: translate(-50%, -50%) scale(1);
38+
opacity: 1;
39+
transition-delay: 0.075s;
40+
}

0 commit comments

Comments
 (0)