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.
This commit is contained in:
@@ -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(
|
||||
<ContactLinks
|
||||
phone="+79991234567"
|
||||
username={null}
|
||||
@@ -201,10 +201,44 @@ describe("ContactLinks", () => {
|
||||
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();
|
||||
});
|
||||
expect(tooltip).toBeInTheDocument();
|
||||
|
||||
it("reverts first copy button to Copy icon when copying the other field", async () => {
|
||||
copyToClipboardMock.mockResolvedValue(true);
|
||||
render(
|
||||
<ContactLinks
|
||||
phone="+79991234567"
|
||||
username="alice_dev"
|
||||
layout="block"
|
||||
showCopyButtons
|
||||
/>
|
||||
);
|
||||
const copyPhoneBtn = screen.getByRole("button", {
|
||||
name: /Copy phone number|Скопировать номер/i,
|
||||
});
|
||||
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", () => {
|
||||
|
||||
@@ -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({
|
||||
<span className="truncate">{formatPhoneDisplay(phone!)}</span>
|
||||
</a>
|
||||
{showCopy && (
|
||||
<Tooltip
|
||||
open={copiedKind === "phone"}
|
||||
onOpenChange={(open) => {
|
||||
if (!open) setCopiedKind(null);
|
||||
}}
|
||||
>
|
||||
<TooltipTrigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
className="flex h-12 w-12 shrink-0 items-center justify-center rounded-r-[calc(theme(borderRadius.md)-1px)] text-accent hover:bg-accent/15 focus-visible:outline focus-visible:outline-2 focus-visible:outline-accent focus-visible:outline-offset-[-2px]"
|
||||
aria-label={t("contact.copy_phone")}
|
||||
aria-label={copiedKind === "phone" ? t("contact.copied") : t("contact.copy_phone")}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
void handleCopyPhone(e);
|
||||
}}
|
||||
>
|
||||
{copiedKind === "phone" ? (
|
||||
<Check className="size-5" aria-hidden />
|
||||
) : (
|
||||
<Copy className="size-5" aria-hidden />
|
||||
)}
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="top" sideOffset={8}>
|
||||
{t("contact.copied")}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
@@ -173,30 +159,22 @@ export function ContactLinks({
|
||||
<span className="truncate">@{cleanUsername}</span>
|
||||
</a>
|
||||
{showCopy && (
|
||||
<Tooltip
|
||||
open={copiedKind === "telegram"}
|
||||
onOpenChange={(open) => {
|
||||
if (!open) setCopiedKind(null);
|
||||
}}
|
||||
>
|
||||
<TooltipTrigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
className="flex h-12 w-12 shrink-0 items-center justify-center rounded-r-[calc(theme(borderRadius.md)-1px)] text-accent hover:bg-accent/15 focus-visible:outline focus-visible:outline-2 focus-visible:outline-accent focus-visible:outline-offset-[-2px]"
|
||||
aria-label={t("contact.copy_telegram")}
|
||||
aria-label={copiedKind === "telegram" ? t("contact.copied") : t("contact.copy_telegram")}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
void handleCopyTelegram(e);
|
||||
}}
|
||||
>
|
||||
{copiedKind === "telegram" ? (
|
||||
<Check className="size-5" aria-hidden />
|
||||
) : (
|
||||
<Copy className="size-5" aria-hidden />
|
||||
)}
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="top" sideOffset={8}>
|
||||
{t("contact.copied")}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user