From 9c550d1dfb4083982a4228ab32476417548e0602 Mon Sep 17 00:00:00 2001 From: Adedeji Mustapha Date: Sat, 28 Mar 2026 09:25:29 +0100 Subject: [PATCH] ui: Implement detailed empty state for token search --- src/components/TokenDropdown.tsx | 71 ++++++++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 8 deletions(-) diff --git a/src/components/TokenDropdown.tsx b/src/components/TokenDropdown.tsx index 9da711b..4caacac 100644 --- a/src/components/TokenDropdown.tsx +++ b/src/components/TokenDropdown.tsx @@ -1,9 +1,12 @@ +"use client"; + import React, { useState, useRef, useEffect, useMemo } from "react"; -import { ChevronDown, Search, X } from "lucide-react"; +import { ChevronDown, Search, X, Copy } from "lucide-react"; import { useDebounce } from "../hooks/useDebounce"; import { useRecentTokens } from "../hooks/useRecentTokens"; import { useWatchlist } from "../hooks/useWatchlist"; import StarIcon from "./StarIcon"; +import toast from "react-hot-toast"; interface TokenDropdownProps { onTokenChange?: (token: string) => void; @@ -21,9 +24,18 @@ export default function TokenDropdown({ onTokenChange }: TokenDropdownProps) { // Debounce the search input with 300ms delay const debouncedSearch = useDebounce(searchInput, 300); - // Hardcoded array of tokens as required + // Hardcoded array of tokens const tokens = ["XLM", "USDC", "yXLM"]; + /** * ISSUE #86: Mock addresses for copy functionality. + * In a production environment, these would come from a token list API. + */ + const mockAddresses: Record = { + "XLM": "native", + "USDC": "CBQ6O7Y4O7Z5J2... (Stellar Contract)", + "yXLM": "CBP3T2... (Yield Stellar Asset)", + }; + // Memoize filtered tokens based on debounced search value const filteredTokens = useMemo(() => { return tokens.filter((token) => @@ -61,6 +73,23 @@ export default function TokenDropdown({ onTokenChange }: TokenDropdownProps) { } }; + /** + * ISSUE #86: Clipboard handler. + * Uses stopPropagation to ensure the dropdown doesn't close when copying. + */ + const handleCopyAddress = (e: React.MouseEvent, token: string) => { + e.stopPropagation(); + const address = mockAddresses[token] || "Address not found"; + + navigator.clipboard.writeText(address) + .then(() => { + toast.success("Token Address Copied!"); + }) + .catch(() => { + toast.error("Failed to copy address"); + }); + }; + return (
{/* Selected Token Button */} @@ -96,7 +125,7 @@ export default function TokenDropdown({ onTokenChange }: TokenDropdownProps) { {searchInput && (
); -} +} \ No newline at end of file