add copy wallet address functionality with feedback#95
add copy wallet address functionality with feedback#95Salman8311 wants to merge 4 commits intoStabilityNexus:mainfrom
Conversation
…te, and Portfolio
WalkthroughNavigation links now dynamically style based on the current route using Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related issues
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/components/layout/Navbar.tsx`:
- Around line 59-101: Replace the hardcoded nav labels in the Navbar component
with translation keys: remove literal strings "Explore", "Create", "Portfolio"
and use your i18n hook/utility (e.g., useTranslations/useTranslation) to render
t('nav.explore'), t('nav.create'), t('nav.portfolio'); add those keys to the
locale resource files and import the translation hook at the top of Navbar.tsx,
keeping the existing Link elements and isActive(...) logic intact; while
editing, normalize JSX indentation in the <nav> and child <Link> blocks for
consistent formatting.
In `@src/components/ui/walletButton.tsx`:
- Line 45: The hardcoded user-visible string "Connect Wallet" in the
WalletButton component (src/components/ui/walletButton.tsx) must be externalized
for i18n: replace the literal with a lookup from your localization/resource
system (e.g., use t('wallet.connect') or messages.connectWallet) and add the key
"wallet.connect" (or agreed key) to the resource files for all supported
locales; update imports in walletButton.tsx to include the i18n helper (e.g.,
useTranslation or messages import) and ensure the component uses that translated
value instead of the hardcoded string.
- Around line 72-74: The title attribute and hardcoded button labels in
WalletButton need i18n: replace the literal title="Copy wallet address" and the
labels 'Copy'/'Copied!' with calls to your localization function (e.g.,
t('wallet.copy') / t('wallet.copied')) and load the translation hook where
WalletButton is defined (or import the i18n helper) so the UI uses resource keys
instead of hardcoded strings; update translation resources with keys for
wallet.copy and wallet.copied and use the component's copied state to choose the
appropriate localized string.
- Around line 52-76: Extract the duplicated className string used by the chain
and account buttons into a shared constant (e.g., BUTTON_BASE_CLASS) at the top
of the WalletButton component file and replace the inline className for the
buttons that call openChainModal and openAccountModal with that constant; ensure
the copy button remains unchanged or optionally reuse the constant with
additional classes if desired, and keep existing handlers (openChainModal,
openAccountModal, handleCopy) and render values (chain.name,
account.displayName, account.address, copied) intact.
- Around line 9-22: The handleCopy function uses setTimeout to reset setCopied
but never clears the timer on unmount, risking state updates on an unmounted
component; change handleCopy to store the timeout id (e.g., in a ref like
copyTimeoutRef) and clearTimeout(copyTimeoutRef.current) in a useEffect cleanup
that runs on unmount, and ensure you set copyTimeoutRef.current = undefined
after clearing; also surface clipboard failures to the user instead of only
console.error by setting an error state or calling the existing UI
notification/toast (e.g., setCopyError or showToast) inside the catch block so
users receive feedback when navigator.clipboard.writeText fails.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: edbb8c72-e11f-4362-bf67-0fb6540569c5
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (2)
src/components/layout/Navbar.tsxsrc/components/ui/walletButton.tsx
| <nav | ||
| className={cn( | ||
| "hidden min-[900px]:flex absolute left-1/2 transform -translate-x-1/2 space-x-2 text-md text-center px-3 py-2 rounded-full", | ||
| "bg-[#f0f1f4] dark:bg-[#1a1b1f] text-gray-900 dark:text-white backdrop-blur-sm", | ||
| "font-[var(--font-bebas-nueue)]" | ||
| )} | ||
| > | ||
| <Link | ||
| href="/explorePools" | ||
| className={cn( | ||
| "px-4 py-1 rounded-full transition-all", | ||
| isActive("/explorePools") | ||
| ? "bg-black text-white dark:bg-white dark:text-black" | ||
| : "text-gray-900 dark:text-white hover:text-yellow-500" | ||
| )} | ||
| > | ||
| Explore | ||
| </Link> | ||
|
|
||
| <Link | ||
| href="/createPool" | ||
| className={cn( | ||
| "px-4 py-1 rounded-full transition-all", | ||
| isActive("/createPool") | ||
| ? "bg-black text-white dark:bg-white dark:text-black" | ||
| : "text-gray-900 dark:text-white hover:text-yellow-500" | ||
| )} | ||
| > | ||
| Create | ||
| </Link> | ||
|
|
||
| <Link | ||
| href="/portfolio" | ||
| className={cn( | ||
| "px-4 py-1 rounded-full transition-all", | ||
| isActive("/portfolio") | ||
| ? "bg-black text-white dark:bg-white dark:text-black" | ||
| : "text-gray-900 dark:text-white hover:text-yellow-500" | ||
| )} | ||
| > | ||
| Portfolio | ||
| </Link> | ||
| </nav> |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Externalize user-visible strings for i18n.
The navigation labels "Explore", "Create", and "Portfolio" are hardcoded. Per coding guidelines, user-visible strings should be externalized to resource files for internationalization.
♻️ Example refactor using i18n
- >
- Explore
- </Link>
+ >
+ {t('nav.explore')}
+ </Link>Consider using a library like next-intl or react-i18next to manage translations.
Minor: Inconsistent indentation in JSX.
The <nav> block and its child <Link> elements have inconsistent indentation (mix of leading spaces). While this doesn't affect functionality, it impacts readability.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/components/layout/Navbar.tsx` around lines 59 - 101, Replace the
hardcoded nav labels in the Navbar component with translation keys: remove
literal strings "Explore", "Create", "Portfolio" and use your i18n hook/utility
(e.g., useTranslations/useTranslation) to render t('nav.explore'),
t('nav.create'), t('nav.portfolio'); add those keys to the locale resource files
and import the translation hook at the top of Navbar.tsx, keeping the existing
Link elements and isActive(...) logic intact; while editing, normalize JSX
indentation in the <nav> and child <Link> blocks for consistent formatting.
| const handleCopy = async (address?: string) => { | ||
| if (!address) return; | ||
|
|
||
| try { | ||
| await navigator.clipboard.writeText(address); | ||
| setCopied(true); | ||
|
|
||
| setTimeout(() => { | ||
| setCopied(false); | ||
| }, 1500); | ||
| } catch (error) { | ||
| console.error('Failed to copy wallet address:', error); | ||
| } | ||
| }; |
There was a problem hiding this comment.
Potential memory leak: setTimeout not cleaned up on unmount.
If the component unmounts before the 1500ms timeout completes, setCopied will be called on an unmounted component. Consider using a ref to track mount state or converting to useEffect for cleanup.
Additionally, on clipboard failure, only console.error is called—users receive no feedback that the copy failed.
🛠️ Proposed fix using a mounted ref
+import { useState, useRef, useEffect } from 'react';
-import { useState } from 'react';
import { ConnectButton } from '@rainbow-me/rainbowkit';
export default function WalletButton() {
const [copied, setCopied] = useState(false);
+ const mountedRef = useRef(true);
+
+ useEffect(() => {
+ return () => {
+ mountedRef.current = false;
+ };
+ }, []);
const handleCopy = async (address?: string) => {
if (!address) return;
try {
await navigator.clipboard.writeText(address);
setCopied(true);
setTimeout(() => {
- setCopied(false);
+ if (mountedRef.current) {
+ setCopied(false);
+ }
}, 1500);
} catch (error) {
console.error('Failed to copy wallet address:', error);
+ // Optionally provide user feedback on failure
}
};🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/components/ui/walletButton.tsx` around lines 9 - 22, The handleCopy
function uses setTimeout to reset setCopied but never clears the timer on
unmount, risking state updates on an unmounted component; change handleCopy to
store the timeout id (e.g., in a ref like copyTimeoutRef) and
clearTimeout(copyTimeoutRef.current) in a useEffect cleanup that runs on
unmount, and ensure you set copyTimeoutRef.current = undefined after clearing;
also surface clipboard failures to the user instead of only console.error by
setting an error state or calling the existing UI notification/toast (e.g.,
setCopyError or showToast) inside the catch block so users receive feedback when
navigator.clipboard.writeText fails.
| type="button" | ||
| className="px-4 py-2 rounded-full bg-black text-white dark:bg-white dark:text-black hover:opacity-80 transition" | ||
| > | ||
| Connect Wallet |
There was a problem hiding this comment.
Hardcoded user-visible string violates i18n guidelines.
"Connect Wallet" should be externalized to a resource file for internationalization support.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/components/ui/walletButton.tsx` at line 45, The hardcoded user-visible
string "Connect Wallet" in the WalletButton component
(src/components/ui/walletButton.tsx) must be externalized for i18n: replace the
literal with a lookup from your localization/resource system (e.g., use
t('wallet.connect') or messages.connectWallet) and add the key "wallet.connect"
(or agreed key) to the resource files for all supported locales; update imports
in walletButton.tsx to include the i18n helper (e.g., useTranslation or messages
import) and ensure the component uses that translated value instead of the
hardcoded string.
| <button | ||
| onClick={openChainModal} | ||
| type="button" | ||
| className="px-3 py-1 rounded-full bg-[#f0f1f4] dark:bg-[#1a1b1f] text-gray-900 dark:text-white border border-gray-300 dark:border-gray-700 hover:bg-gray-200 dark:hover:bg-[#2a2b30] transition" | ||
| > | ||
| {chain.name} | ||
| </button> | ||
|
|
||
| <button | ||
| onClick={openAccountModal} | ||
| type="button" | ||
| className="px-3 py-1 rounded-full bg-[#f0f1f4] dark:bg-[#1a1b1f] text-gray-900 dark:text-white border border-gray-300 dark:border-gray-700 hover:bg-gray-200 dark:hover:bg-[#2a2b30] transition" | ||
| > | ||
| {account.displayName} | ||
| </button> | ||
|
|
||
| <button | ||
| onClick={() => handleCopy(account.address)} | ||
| type="button" | ||
| className="px-3 py-1 rounded-full bg-black text-white dark:bg-white dark:text-black hover:opacity-80 transition" | ||
| title="Copy wallet address" | ||
| > | ||
| {copied ? 'Copied!' : 'Copy'} | ||
| </button> | ||
| </div> |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Consider extracting repeated button styles.
The chain and account buttons share nearly identical className strings. Extracting to a shared constant or utility improves maintainability and reduces duplication.
♻️ Optional refactor
+const secondaryButtonClass =
+ "px-3 py-1 rounded-full bg-[`#f0f1f4`] dark:bg-[`#1a1b1f`] text-gray-900 dark:text-white border border-gray-300 dark:border-gray-700 hover:bg-gray-200 dark:hover:bg-[`#2a2b30`] transition";
+
return (
<div className="flex items-center gap-2">
<button
onClick={openChainModal}
type="button"
- className="px-3 py-1 rounded-full bg-[`#f0f1f4`] dark:bg-[`#1a1b1f`] text-gray-900 dark:text-white border border-gray-300 dark:border-gray-700 hover:bg-gray-200 dark:hover:bg-[`#2a2b30`] transition"
+ className={secondaryButtonClass}
>
{chain.name}
</button>
<button
onClick={openAccountModal}
type="button"
- className="px-3 py-1 rounded-full bg-[`#f0f1f4`] dark:bg-[`#1a1b1f`] text-gray-900 dark:text-white border border-gray-300 dark:border-gray-700 hover:bg-gray-200 dark:hover:bg-[`#2a2b30`] transition"
+ className={secondaryButtonClass}
>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <button | |
| onClick={openChainModal} | |
| type="button" | |
| className="px-3 py-1 rounded-full bg-[#f0f1f4] dark:bg-[#1a1b1f] text-gray-900 dark:text-white border border-gray-300 dark:border-gray-700 hover:bg-gray-200 dark:hover:bg-[#2a2b30] transition" | |
| > | |
| {chain.name} | |
| </button> | |
| <button | |
| onClick={openAccountModal} | |
| type="button" | |
| className="px-3 py-1 rounded-full bg-[#f0f1f4] dark:bg-[#1a1b1f] text-gray-900 dark:text-white border border-gray-300 dark:border-gray-700 hover:bg-gray-200 dark:hover:bg-[#2a2b30] transition" | |
| > | |
| {account.displayName} | |
| </button> | |
| <button | |
| onClick={() => handleCopy(account.address)} | |
| type="button" | |
| className="px-3 py-1 rounded-full bg-black text-white dark:bg-white dark:text-black hover:opacity-80 transition" | |
| title="Copy wallet address" | |
| > | |
| {copied ? 'Copied!' : 'Copy'} | |
| </button> | |
| </div> | |
| const secondaryButtonClass = | |
| "px-3 py-1 rounded-full bg-[`#f0f1f4`] dark:bg-[`#1a1b1f`] text-gray-900 dark:text-white border border-gray-300 dark:border-gray-700 hover:bg-gray-200 dark:hover:bg-[`#2a2b30`] transition"; | |
| <button | |
| onClick={openChainModal} | |
| type="button" | |
| className={secondaryButtonClass} | |
| > | |
| {chain.name} | |
| </button> | |
| <button | |
| onClick={openAccountModal} | |
| type="button" | |
| className={secondaryButtonClass} | |
| > | |
| {account.displayName} | |
| </button> | |
| <button | |
| onClick={() => handleCopy(account.address)} | |
| type="button" | |
| className="px-3 py-1 rounded-full bg-black text-white dark:bg-white dark:text-black hover:opacity-80 transition" | |
| title="Copy wallet address" | |
| > | |
| {copied ? 'Copied!' : 'Copy'} | |
| </button> | |
| </div> |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/components/ui/walletButton.tsx` around lines 52 - 76, Extract the
duplicated className string used by the chain and account buttons into a shared
constant (e.g., BUTTON_BASE_CLASS) at the top of the WalletButton component file
and replace the inline className for the buttons that call openChainModal and
openAccountModal with that constant; ensure the copy button remains unchanged or
optionally reuse the constant with additional classes if desired, and keep
existing handlers (openChainModal, openAccountModal, handleCopy) and render
values (chain.name, account.displayName, account.address, copied) intact.
| title="Copy wallet address" | ||
| > | ||
| {copied ? 'Copied!' : 'Copy'} |
There was a problem hiding this comment.
Additional hardcoded strings need i18n externalization.
The title attribute and button labels ("Copy", "Copied!") should also be externalized for internationalization. As per coding guidelines: "User-visible strings should be externalized to resource files (i18n)".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/components/ui/walletButton.tsx` around lines 72 - 74, The title attribute
and hardcoded button labels in WalletButton need i18n: replace the literal
title="Copy wallet address" and the labels 'Copy'/'Copied!' with calls to your
localization function (e.g., t('wallet.copy') / t('wallet.copied')) and load the
translation hook where WalletButton is defined (or import the i18n helper) so
the UI uses resource keys instead of hardcoded strings; update translation
resources with keys for wallet.copy and wallet.copied and use the component's
copied state to choose the appropriate localized string.
🚀 Add Copy Wallet Address Feature
📌 Description
This PR adds a copy-to-clipboard feature for the wallet address to improve user experience.
✅ Changes Made
navigator.clipboard🎯 Result
Users can now easily copy their wallet address with a single click.
🧪 Testing
🤖 AI Usage Disclosure
This PR was created with assistance from AI tools.
All code has been reviewed and tested by me.
Summary by CodeRabbit
New Features
Improvements