Skip to content

Commit 2ca2728

Browse files
committed
feat(copy-button): add toast notifications for copy success and error handling
1 parent b9ff7a7 commit 2ca2728

File tree

2 files changed

+26
-4
lines changed

2 files changed

+26
-4
lines changed

dashboard/src/components/common/copy-button.tsx

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import { Button } from '@/components/ui/button'
22
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
33
import { useClipboard } from '@/hooks/use-clipboard'
44
import { Check, Copy, Link } from 'lucide-react'
5-
import { useCallback } from 'react'
5+
import { useCallback, useEffect, useRef } from 'react'
66
import { useTranslation } from 'react-i18next'
7+
import { toast } from 'sonner'
78

89
interface CopyButtonProps {
910
value: string
@@ -12,22 +13,40 @@ interface CopyButtonProps {
1213
defaultMessage?: string
1314
icon?: 'copy' | 'link'
1415
onClick?: (e: React.MouseEvent) => void
16+
showToast?: boolean
17+
toastSuccessMessage?: string
18+
toastErrorMessage?: string
1519
}
1620

17-
export function CopyButton({ value, className, copiedMessage = 'Copied!', defaultMessage = 'Click to copy', icon = 'copy', onClick }: CopyButtonProps) {
21+
export function CopyButton({ value, className, copiedMessage = 'Copied!', defaultMessage = 'Click to copy', icon = 'copy', onClick, showToast = false, toastSuccessMessage, toastErrorMessage }: CopyButtonProps) {
1822
const { t } = useTranslation()
1923

20-
const { copy, copied } = useClipboard({ timeout: 1500 })
24+
const { copy, copied, error } = useClipboard({ timeout: 1500 })
25+
const shouldShowToast = useRef(false)
26+
2127
const handleCopy = useCallback(
2228
async (e: React.MouseEvent) => {
2329
e.preventDefault()
2430
e.stopPropagation()
31+
shouldShowToast.current = showToast
2532
await copy(value)
2633
onClick?.(e)
2734
},
28-
[copy, value, onClick],
35+
[copy, value, onClick, showToast],
2936
)
3037

38+
useEffect(() => {
39+
if (!shouldShowToast.current) return
40+
41+
if (copied) {
42+
toast.success(toastSuccessMessage ? t(toastSuccessMessage) : t(copiedMessage))
43+
shouldShowToast.current = false
44+
} else if (error) {
45+
toast.error(toastErrorMessage ? t(toastErrorMessage) : t('copyFailed', { defaultValue: 'Failed to copy' }))
46+
shouldShowToast.current = false
47+
}
48+
}, [copied, error, toastSuccessMessage, toastErrorMessage, copiedMessage, t])
49+
3150
return (
3251
<Tooltip open={copied ? true : undefined}>
3352
<TooltipTrigger asChild>

dashboard/src/components/users/action-buttons.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,9 @@ const ActionButtons: FC<ActionButtonsProps> = ({ user }) => {
374374
copiedMessage="usersTable.copied"
375375
defaultMessage="usersTable.copyLink"
376376
icon="link"
377+
showToast={true}
378+
toastSuccessMessage="usersTable.copied"
379+
toastErrorMessage="copyFailed"
377380
/>
378381
<Tooltip open={copied ? true : undefined}>
379382
<DropdownMenu>

0 commit comments

Comments
 (0)