From 7cf3876694c6e54c48ae1269ebcf6fb1e2daec32 Mon Sep 17 00:00:00 2001 From: victorEdeh Date: Sat, 25 Apr 2026 10:56:54 -0700 Subject: [PATCH] feat: add aria-live status regions and dynamic aria-labels for copy-to-clipboard actions (#123) - TruncatedAddress: sr-only live region announces 'Address copied to clipboard'; aria-label toggles between 'Copy address' / 'Address copied' - TransactionHashRow: same pattern for transaction hash copy button - TransactionFailureDrawer: per-field copied state with Check icon feedback, dynamic aria-labels, and sr-only live regions for error code and tx hash copy buttons - App: Toaster explicitly configured with role=status and aria-live=polite via toastOptions.ariaProps - All decorative icons marked aria-hidden=true --- src/App.tsx | 9 +++- .../common/TransactionFailureDrawer.tsx | 46 +++++++++++++++---- src/components/common/TransactionHashRow.tsx | 14 ++++-- src/components/common/TruncatedAddress.tsx | 32 ++++++++----- 4 files changed, 77 insertions(+), 24 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 8687a45..c9f902d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -12,7 +12,14 @@ const router = createBrowserRouter([ function App() { return ( <> - + ); diff --git a/src/components/common/TransactionFailureDrawer.tsx b/src/components/common/TransactionFailureDrawer.tsx index 80dff8e..4896a14 100644 --- a/src/components/common/TransactionFailureDrawer.tsx +++ b/src/components/common/TransactionFailureDrawer.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState } from 'react'; import { Dialog, DialogContent, @@ -7,7 +7,7 @@ import { DialogFooter, } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; -import { AlertCircle, Copy } from 'lucide-react'; +import { AlertCircle, Copy, Check } from 'lucide-react'; import toast from 'react-hot-toast'; import { formatAbsoluteDateTime, formatRelativeTime } from '@/utils/time.utils'; @@ -34,9 +34,13 @@ const TransactionFailureDrawer: React.FC = ({ onRetry, onDismiss, }) => { - const copyToClipboard = (text: string) => { + const [copiedField, setCopiedField] = useState<'errorCode' | 'txHash' | null>(null); + + const copyToClipboard = (text: string, field: 'errorCode' | 'txHash') => { navigator.clipboard.writeText(text); toast.success('Copied to clipboard'); + setCopiedField(field); + setTimeout(() => setCopiedField(null), 2000); }; const handleClose = () => { @@ -100,14 +104,26 @@ const TransactionFailureDrawer: React.FC = ({ + + {copiedField === 'errorCode' ? 'Error code copied to clipboard' : ''} + )} @@ -122,14 +138,26 @@ const TransactionFailureDrawer: React.FC = ({ + + {copiedField === 'txHash' ? 'Transaction hash copied to clipboard' : ''} + )} diff --git a/src/components/common/TransactionHashRow.tsx b/src/components/common/TransactionHashRow.tsx index d51a12d..c4d67c0 100644 --- a/src/components/common/TransactionHashRow.tsx +++ b/src/components/common/TransactionHashRow.tsx @@ -46,14 +46,22 @@ const TransactionHashRow: React.FC = ({ + + {copied ? 'Transaction hash copied to clipboard' : ''} + {explorerUrl && ( = ({ > {truncate(address, prefixChars, suffixChars)} {copyable && ( - + <> + + + {copied ? 'Address copied to clipboard' : ''} + + )} );