Skip to content

Commit 7691f77

Browse files
authored
Adding useClipboard hook (#425)
* Adding useClipboard hook * Using useClipboard hook rather than react-copy-to-clipboard
1 parent 36025e9 commit 7691f77

File tree

12 files changed

+80
-159
lines changed

12 files changed

+80
-159
lines changed

packages/checkout/package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
"motion": "^12.9.2",
3737
"pako": "^2.1.0",
3838
"qrcode.react": "^4.2.0",
39-
"react-copy-to-clipboard": "^5.1.0",
4039
"timeago-react": "^3.0.7"
4140
},
4241
"peerDependencies": {
@@ -58,7 +57,6 @@
5857
"@0xsequence/connect": "workspace:*",
5958
"@tanstack/react-query": "^5.74.11",
6059
"@types/pako": "^2.0.3",
61-
"@types/react-copy-to-clipboard": "^5.0.7",
6260
"ethers": "^6.13.7",
6361
"react": "^19.1.0",
6462
"react-dom": "^19.1.0",
Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,27 @@
11
import { Button, CheckmarkIcon, CopyIcon } from '@0xsequence/design-system'
2-
import React, { useEffect, useState, type ComponentProps } from 'react'
3-
import { CopyToClipboard } from 'react-copy-to-clipboard'
2+
import { useClipboard } from '@0xsequence/hooks'
3+
import React, { type ComponentProps } from 'react'
44

55
type ButtonProps = ComponentProps<typeof Button>
66

77
interface CopyButtonProps extends ButtonProps {
88
text: string
9+
inline?: boolean
910
}
1011

1112
export const CopyButton = (props: CopyButtonProps) => {
12-
const { text, size = 'xs', ...rest } = props
13-
const [isCopied, setCopy] = useState(false)
13+
const { text, size = 'xs', inline = false, ...rest } = props
14+
const [isCopied, setCopied] = useClipboard({ timeout: 4000 })
1415

15-
useEffect(() => {
16-
if (isCopied) {
17-
setTimeout(() => {
18-
setCopy(false)
19-
}, 4000)
20-
}
21-
}, [isCopied])
22-
23-
const handleCopy = () => {
24-
setCopy(true)
25-
}
26-
27-
return (
28-
<CopyToClipboard text={text} onCopy={handleCopy}>
29-
<Button size={size} leftIcon={isCopied ? CheckmarkIcon : CopyIcon} label={isCopied ? 'Copied' : 'Copy'} {...rest} />
30-
</CopyToClipboard>
16+
return inline ? (
17+
<Button size={size} variant="text" leftIcon={isCopied ? CheckmarkIcon : CopyIcon} onClick={() => setCopied(text)} />
18+
) : (
19+
<Button
20+
size={size}
21+
leftIcon={isCopied ? CheckmarkIcon : CopyIcon}
22+
label={isCopied ? 'Copied' : 'Copy'}
23+
onClick={() => setCopied(text)}
24+
{...rest}
25+
/>
3126
)
3227
}

packages/checkout/src/views/PaymentSelection/TransferFunds.tsx

Lines changed: 9 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { Card, CheckmarkIcon, CopyIcon, IconButton, Text, truncateAddress } from '@0xsequence/design-system'
2+
import { useClipboard } from '@0xsequence/hooks'
23
import { QRCodeCanvas } from 'qrcode.react'
3-
import { useEffect, useState } from 'react'
4-
import { CopyToClipboard } from 'react-copy-to-clipboard'
54
import { useAccount } from 'wagmi'
65

76
import { useSelectPaymentModal, useTransferFundsModal } from '../../hooks'
@@ -10,19 +9,7 @@ export const TransferFunds = () => {
109
const { openTransferFundsModal } = useTransferFundsModal()
1110
const { openSelectPaymentModal, closeSelectPaymentModal, selectPaymentSettings } = useSelectPaymentModal()
1211
const { address: userAddress } = useAccount()
13-
const [isCopied, setCopy] = useState(false)
14-
15-
useEffect(() => {
16-
if (isCopied) {
17-
setTimeout(() => {
18-
setCopy(false)
19-
}, 4000)
20-
}
21-
}, [isCopied])
22-
23-
const handleCopy = () => {
24-
setCopy(true)
25-
}
12+
const [isCopied, setCopied] = useClipboard({ timeout: 4000 })
2613

2714
const onClickQrCode = (e: React.MouseEvent<HTMLDivElement>) => {
2815
e.preventDefault()
@@ -83,14 +70,13 @@ export const TransferFunds = () => {
8370
e.preventDefault()
8471
}}
8572
>
86-
<CopyToClipboard text={userAddress || ''} onCopy={handleCopy}>
87-
<IconButton
88-
className="text-muted"
89-
variant="base"
90-
size="md"
91-
icon={isCopied ? () => <CheckmarkIcon size="lg" /> : () => <CopyIcon size="lg" />}
92-
/>
93-
</CopyToClipboard>
73+
<IconButton
74+
className="text-muted"
75+
variant="base"
76+
size="md"
77+
icon={isCopied ? () => <CheckmarkIcon size="lg" /> : () => <CopyIcon size="lg" />}
78+
onClick={() => setCopied(userAddress || '')}
79+
/>
9480
</div>
9581
</Card>
9682
</div>

packages/checkout/src/views/TransferToWallet/CopyButton.tsx

Lines changed: 0 additions & 37 deletions
This file was deleted.

packages/checkout/src/views/TransferToWallet/QRCode.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Skeleton } from '@0xsequence/design-system'
22
import { QRCodeCanvas } from 'qrcode.react'
33

4-
import { CopyButton } from './CopyButton'
4+
import { CopyButton } from '../../components/CopyButton'
55

66
interface QRCodeProps {
77
value: string | undefined

packages/hooks/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,8 @@
5858
"viem": "^2.28.1",
5959
"vite": "^6.3.4",
6060
"vitest": "^2.1.9"
61+
},
62+
"dependencies": {
63+
"copy-to-clipboard": "^3.3.3"
6164
}
6265
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import copy from 'copy-to-clipboard'
2+
import { useEffect, useState } from 'react'
3+
4+
interface UseClipboardProps {
5+
timeout?: number
6+
}
7+
8+
export const useClipboard = (props?: UseClipboardProps) => {
9+
const [isCopied, setIsCopied] = useState(false)
10+
const timeout = props && props.timeout
11+
12+
useEffect(() => {
13+
if (isCopied) {
14+
const id = setTimeout(() => {
15+
setIsCopied(false)
16+
}, timeout)
17+
18+
return () => {
19+
clearTimeout(id)
20+
}
21+
}
22+
}, [isCopied, timeout])
23+
24+
return [
25+
isCopied,
26+
(text: string) => {
27+
copy(text)
28+
setIsCopied(true)
29+
}
30+
] as const
31+
}

packages/hooks/src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,5 @@ export { useGetSwapQuote } from './hooks/Combination/useGetSwapQuote'
4242
export { useGetSwapRoutes } from './hooks/Combination/useGetSwapRoutes'
4343

4444
// Etc
45-
export { useClearCachedBalances } from './hooks/useClearCachedBalances.js'
45+
export { useClearCachedBalances } from './hooks/useClearCachedBalances'
46+
export { useClipboard } from './hooks/useClipboard'

packages/wallet-widget/package.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@
3737
"fuse.js": "^6.6.2",
3838
"micro-observables": "1.7.2",
3939
"motion": "^12.9.2",
40-
"qrcode.react": "^4.2.0",
41-
"react-copy-to-clipboard": "^5.1.0"
40+
"qrcode.react": "^4.2.0"
4241
},
4342
"peerDependencies": {
4443
"@0xsequence/api": "2.3.11",
@@ -60,7 +59,6 @@
6059
"@0xsequence/connect": "workspace:*",
6160
"@0xsequence/hooks": "workspace:*",
6261
"@tanstack/react-query": "^5.74.11",
63-
"@types/react-copy-to-clipboard": "^5.0.7",
6462
"ethers": "^6.13.7",
6563
"react": "^19.1.0",
6664
"react-dom": "^19.1.0",
Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Button, CheckmarkIcon, CopyIcon } from '@0xsequence/design-system'
2-
import { useEffect, useState, type ComponentProps } from 'react'
3-
import { CopyToClipboard } from 'react-copy-to-clipboard'
2+
import { useClipboard } from '@0xsequence/hooks'
3+
import type { ComponentProps } from 'react'
44

55
type ButtonProps = ComponentProps<typeof Button>
66

@@ -11,31 +11,18 @@ interface CopyButtonProps extends ButtonProps {
1111

1212
export const CopyButton = (props: CopyButtonProps) => {
1313
const { buttonVariant = 'icon', text, size = 'xs', ...rest } = props
14-
const [isCopied, setCopy] = useState(false)
15-
16-
useEffect(() => {
17-
if (isCopied) {
18-
setTimeout(() => {
19-
setCopy(false)
20-
}, 2000)
21-
}
22-
}, [isCopied])
23-
24-
const handleCopy = () => {
25-
setCopy(true)
26-
}
14+
const [isCopied, setCopied] = useClipboard({ timeout: 4000 })
2715

2816
const label = isCopied ? 'Copied!' : 'Copy'
2917

3018
return (
31-
<CopyToClipboard text={text} onCopy={handleCopy}>
32-
<Button
33-
size={size!}
34-
leftIcon={isCopied ? CheckmarkIcon : CopyIcon}
35-
label={buttonVariant === 'with-label' ? label : undefined}
36-
variant={buttonVariant === 'icon' ? 'ghost' : 'glass'}
37-
{...rest}
38-
/>
39-
</CopyToClipboard>
19+
<Button
20+
size={size!}
21+
leftIcon={isCopied ? CheckmarkIcon : CopyIcon}
22+
label={buttonVariant === 'with-label' ? label : undefined}
23+
variant={buttonVariant === 'icon' ? 'ghost' : 'glass'}
24+
onClick={() => setCopied(text)}
25+
{...rest}
26+
/>
4027
)
4128
}

0 commit comments

Comments
 (0)