From 41f428d066be3cf38fce33edd1715ae6cd01e29e Mon Sep 17 00:00:00 2001 From: zvspany Date: Mon, 9 Mar 2026 17:10:32 +0100 Subject: [PATCH] feat(converter): add copy-to-clipboard action for converted value --- components/converter/converter-card.tsx | 53 +++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/components/converter/converter-card.tsx b/components/converter/converter-card.tsx index d89cb42..5ddefa0 100644 --- a/components/converter/converter-card.tsx +++ b/components/converter/converter-card.tsx @@ -1,7 +1,14 @@ "use client"; import { useEffect, useMemo, useState } from "react"; -import { AlertTriangle, ArrowUpDown, Loader2, RefreshCcw } from "lucide-react"; +import { + AlertTriangle, + ArrowUpDown, + Check, + Copy, + Loader2, + RefreshCcw, +} from "lucide-react"; import { CurrencyIcon } from "@/components/converter/currency-icon"; import { CurrencySelect } from "@/components/converter/currency-select"; @@ -117,6 +124,7 @@ export function ConverterCard({ const [amountInput, setAmountInput] = useState("1"); const [fromCode, setFromCode] = useState(DEFAULT_FROM); const [toCode, setToCode] = useState(DEFAULT_TO); + const [isCopied, setIsCopied] = useState(false); const debouncedAmount = useDebouncedValue(amountInput, 120); @@ -195,6 +203,22 @@ export function ConverterCard({ setToCode(fromCode); }; + const handleCopyConvertedValue = async () => { + if (convertedValue === null || !toAsset) { + return; + } + + const text = `${formatAmount(convertedValue, toAsset)} ${toAsset.code}`; + + try { + await navigator.clipboard.writeText(text); + setIsCopied(true); + window.setTimeout(() => setIsCopied(false), 1400); + } catch { + setIsCopied(false); + } + }; + if (isLoading && !data) { return ; } @@ -368,9 +392,30 @@ export function ConverterCard({
-

- Converted value -

+
+

+ Converted value +

+ +
{fromAsset && toAsset ? (