From dc87b3ad97deb5c51d826c5b51a598f51072eaab Mon Sep 17 00:00:00 2001 From: Nikolay Tatarinov Date: Sat, 7 Mar 2026 00:11:36 +0300 Subject: [PATCH] feat: update copy functionality in ContactLinks component - Modified the copy button behavior to display "Copied" via button aria-label instead of a tooltip after a successful copy action. - Enhanced the component to revert the copy button icon when switching between phone number and Telegram username copy actions. - Updated tests to reflect changes in copy button functionality and ensure proper rendering based on user interactions. --- .../components/contact/ContactLinks.test.tsx | 44 ++++++++-- .../src/components/contact/ContactLinks.tsx | 80 +++++++------------ 2 files changed, 68 insertions(+), 56 deletions(-) diff --git a/webapp-next/src/components/contact/ContactLinks.test.tsx b/webapp-next/src/components/contact/ContactLinks.test.tsx index 507a2e5..567bc47 100644 --- a/webapp-next/src/components/contact/ContactLinks.test.tsx +++ b/webapp-next/src/components/contact/ContactLinks.test.tsx @@ -184,9 +184,9 @@ describe("ContactLinks", () => { expect(triggerHapticLightMock).toHaveBeenCalled(); }); - it("shows Copied text in tooltip after successful copy", async () => { + it("shows Copied via button aria-label and no tooltip after successful copy", async () => { copyToClipboardMock.mockResolvedValue(true); - renderWithTooltip( + render( { fireEvent.click(copyBtn); }); - const tooltip = await screen.findByRole("tooltip", { - name: /Copied|Скопировано/i, + expect(screen.queryByRole("tooltip")).not.toBeInTheDocument(); + expect( + screen.getByRole("button", { name: /Copied|Скопировано/i }) + ).toBeInTheDocument(); + }); + + it("reverts first copy button to Copy icon when copying the other field", async () => { + copyToClipboardMock.mockResolvedValue(true); + render( + + ); + const copyPhoneBtn = screen.getByRole("button", { + name: /Copy phone number|Скопировать номер/i, }); - expect(tooltip).toBeInTheDocument(); + const copyTelegramBtn = screen.getByRole("button", { + name: /Copy Telegram username|Скопировать логин Telegram/i, + }); + await act(async () => { + fireEvent.click(copyPhoneBtn); + }); + expect( + screen.getByRole("button", { name: /Copied|Скопировано/i }) + ).toBeInTheDocument(); + + await act(async () => { + fireEvent.click(copyTelegramBtn); + }); + expect( + screen.getByRole("button", { name: /Copy phone number|Скопировать номер/i }) + ).toBeInTheDocument(); + expect( + screen.getByRole("button", { name: /Copied|Скопировано/i }) + ).toBeInTheDocument(); }); it("does not show copy buttons when showCopyButtons is false", () => { diff --git a/webapp-next/src/components/contact/ContactLinks.tsx b/webapp-next/src/components/contact/ContactLinks.tsx index 0654a50..09ada3c 100644 --- a/webapp-next/src/components/contact/ContactLinks.tsx +++ b/webapp-next/src/components/contact/ContactLinks.tsx @@ -12,14 +12,8 @@ import { openPhoneLink } from "@/lib/open-phone-link"; import { openTelegramProfile } from "@/lib/telegram-link"; import { triggerHapticLight } from "@/lib/telegram-haptic"; import { copyToClipboard } from "@/lib/copy-to-clipboard"; -import { Button } from "@/components/ui/button"; -import { - Tooltip, - TooltipContent, - TooltipTrigger, -} from "@/components/ui/tooltip"; import { cn } from "@/lib/utils"; -import { Phone as PhoneIcon, Send as TelegramIcon, Copy } from "lucide-react"; +import { Phone as PhoneIcon, Send as TelegramIcon, Copy, Check } from "lucide-react"; const COPIED_RESET_MS = 1800; @@ -128,30 +122,22 @@ export function ContactLinks({ {formatPhoneDisplay(phone!)} {showCopy && ( - { - if (!open) setCopiedKind(null); + - - - {t("contact.copied")} - - + {copiedKind === "phone" ? ( + + ) : ( + + )} + )} )} @@ -173,30 +159,22 @@ export function ContactLinks({ @{cleanUsername} {showCopy && ( - { - if (!open) setCopiedKind(null); + - - - {t("contact.copied")} - - + {copiedKind === "telegram" ? ( + + ) : ( + + )} + )} )}