Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add clickable token address #5462

Merged
merged 12 commits into from
Mar 4, 2025
Merged

Add clickable token address #5462

merged 12 commits into from
Mar 4, 2025

Conversation

cowdan
Copy link
Contributor

@cowdan cowdan commented Feb 27, 2025

Summary

Add to a token contract address a link (at the moment only Etherscan is supported) and a copy to clipboard icon

Screenshot 2025-02-27 at 15 15 36 Screenshot 2025-02-27 at 15 16 07 Screenshot 2025-02-27 at 15 16 17

To Test

  1. Go to the token list selector
  • Next to the token ticker, there is a shortened contract address. The copy icon should not be displayed
  • On mouse over the address, it should be darkened and underlined. Also, the copy icon should be displayed.
  • On address link click, it should open the contract on Etherscan in a new tab. The token list should still be there (no going back to the main swap screen). Also, the selected token shouldn't change.
  • On copy icon click, it should display, after very short delay, the text "Copied!" and then going back to show the copy icon. The token address should be available on the clipboard memory.

Background

The disabled attribute on TokenListItem stopped propagating a click event generated by the CopyToClipboard component, so I had to remove it and replicate the behaviour (styling and click propagation)

Summary by CodeRabbit

  • New Features

    • Introduced an interactive address display that shows a shortened blockchain address with tooltip details and copy-to-clipboard functionality.
    • Integrated this clickable address into token information views for quick access to blockchain explorer links.
  • Enhancements

    • Improved token selection behavior with refined click handling for a smoother user experience.
  • Style

    • Added new styled components for better layout and hover effects, enhancing visual cues for interactive and selected states.
  • Documentation

    • Minor punctuation corrections made to enhance clarity.

Copy link

coderabbitai bot commented Feb 27, 2025

Walkthrough

This pull request introduces a new React component, ClickableAddress, along with its styled counterparts to present blockchain addresses in a user-friendly manner. Utility functions handle URL generation, title creation, and token detection. The TokenInfo component now integrates this clickable address, and a new styled wrapper for the token symbol is added. Additionally, modifications in TokenListItem update the click handling logic and styling, ensuring proper event propagation when selecting tokens. A minor punctuation fix is applied in the README, and the CopyHelper component is refactored to use a new interface for clearer prop definitions.

Changes

File(s) Change Summary
apps/cowswap-frontend/src/common/pure/ClickableAddress/index.tsx, apps/cowswap-frontend/src/common/pure/ClickableAddress/styled.ts Added new ClickableAddress component with URL, tooltip, and copy functionalities along with corresponding styled components.
apps/cowswap-frontend/src/modules/tokensList/pure/TokenInfo/index.tsx, apps/cowswap-frontend/src/modules/tokensList/pure/TokenInfo/styled.ts Integrated ClickableAddress in TokenInfo; introduced TokenSymbolWrapper for improved token symbol layout.
apps/cowswap-frontend/src/modules/tokensList/pure/TokenListItem/index.tsx, apps/cowswap-frontend/src/modules/tokensList/pure/TokenListItem/styled.ts Updated click handling via a new handleClick function and revised styling with a .token-item-selected class for visual feedback.
README.md Fixed punctuation by adding a missing period.
apps/cowswap-frontend/src/legacy/components/Copy/CopyMod.tsx Refactored CopyHelper component by defining a new CopyHelperProps interface and removing deprecated code.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ClickableAddress
    participant HoverTooltip
    participant CopyHelper

    User->>ClickableAddress: Hover/Click on address
    ClickableAddress->>HoverTooltip: Display title tooltip
    ClickableAddress->>CopyHelper: Enable address copying
    User->>Browser: Opens target URL in new tab
Loading
sequenceDiagram
    participant User
    participant TokenListItem
    participant onSelectToken

    User->>TokenListItem: Click on token item
    TokenListItem->>TokenListItem: Execute handleClick()
    alt Token is selected
        TokenListItem->>User: Stop event propagation
    else Token is not selected
        TokenListItem->>onSelectToken: Invoke onSelectToken(token)
    end
Loading

Suggested reviewers

  • elena-zh

Poem

I’m a little rabbit, hopping with cheer,
Code paths transformed so the clicks are clear.
Addresses now shine with a twitch and a blink,
Copy and explore with a single swift link.
In the garden of code, each change brings a spring!
🐇🌸

✨ Finishing Touches
  • 📝 Generate Docstrings

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

github-actions bot commented Feb 27, 2025

CLA Assistant Lite bot All contributors have signed the CLA ✍️ ✅

Copy link

socket-security bot commented Feb 27, 2025

No dependency changes detected. Learn more about Socket for GitHub ↗︎

👍 No dependency changes detected in pull request

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (4)
apps/cowswap-frontend/src/common/pure/CopyToClipboard/index.tsx (2)

36-42: Improve accessibility by adding keyboard support.

The component currently only responds to click events, but keyboard users should also be able to copy the text.

    <styledEl.CopyWrapper>
      {copied ? (
        <styledEl.CopyMessage>{copiedMessage}</styledEl.CopyMessage>
      ) : (
        <styledEl.CopyIcon 
          className={iconClassName} 
          onClick={copyToClipboard}
+         onKeyDown={(e) => e.key === 'Enter' && copyToClipboard(e as unknown as MouseEvent<HTMLDivElement>)}
+         tabIndex={0}
+         role="button"
+         aria-label="Copy to clipboard"
        />
      )}
    </styledEl.CopyWrapper>

11-44: Consider adding browser compatibility check for Clipboard API.

The Clipboard API is not supported in all browsers. Consider adding a fallback mechanism for older browsers.

export const CopyToClipboard = ({ text, copiedMessage = 'Copied!', iconClassName }: CopyToClipboardProps) => {
  const [copied, setCopied] = useState(false)
+  const [clipboardSupported] = useState(() => !!navigator.clipboard);

  const copyToClipboard = async (event: MouseEvent<HTMLDivElement>) => {
    event.preventDefault()
    event.stopPropagation()
    try {
+     if (clipboardSupported) {
        await navigator.clipboard.writeText(text)
+     } else {
+       // Fallback for browsers without Clipboard API
+       const textArea = document.createElement('textarea');
+       textArea.value = text;
+       textArea.style.position = 'fixed';
+       document.body.appendChild(textArea);
+       textArea.focus();
+       textArea.select();
+       document.execCommand('copy');
+       document.body.removeChild(textArea);
+     }
      setCopied(true)
    } catch (error) {
      console.error('Failed to copy:', error)
    }
  }
apps/cowswap-frontend/src/common/pure/ClickableAddress/index.tsx (2)

14-18: Prepare for multi-chain support with a more robust explorer mapping.

The TODO comment indicates plans for more chains, but the current implementation has a few limitations:

  1. No error handling if a chainId doesn't match any known explorer
  2. Limited to just two networks currently
// TODO: once we have more chains, we should use the chainId to get the correct explorer
-const mapChainIdToExplorer: { [key: string]: { name: string; url: string } } = {
+type ExplorerInfo = { name: string; url: string }
+
+const mapChainIdToExplorer: Record<string, ExplorerInfo> = {
}
+
+// Default to Ethereum mainnet if chain is not supported
+const getExplorerForChain = (chainId?: number): ExplorerInfo => {
+  const chainKey = chainId?.toString() || '1'
+  return mapChainIdToExplorer[chainKey] || mapChainIdToExplorer['1']
+}

20-28: Refactor explorer utilities to use the safer lookup function.

There's duplicate code for getting the explorer information and no error handling if the chainId doesn't match.

const getTarget = (address: string, chainId?: number) => {
-  const explorer = chainId ? mapChainIdToExplorer[chainId.toString()] : mapChainIdToExplorer['1']
+  const explorer = getExplorerForChain(chainId)
  return `${explorer.url}/${address}`
}

const getTitle = (address: string, chainId?: number) => {
-  const explorer = chainId ? mapChainIdToExplorer[chainId.toString()] : mapChainIdToExplorer['1']
+  const explorer = getExplorerForChain(chainId)
  return `View ${address} on ${explorer.name}`
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a02c626 and d3abb93.

⛔ Files ignored due to path filters (2)
  • apps/cowswap-frontend/public/images/click-to-copy.svg is excluded by !**/*.svg
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (8)
  • apps/cowswap-frontend/src/common/pure/ClickableAddress/index.tsx (1 hunks)
  • apps/cowswap-frontend/src/common/pure/ClickableAddress/styled.ts (1 hunks)
  • apps/cowswap-frontend/src/common/pure/CopyToClipboard/index.tsx (1 hunks)
  • apps/cowswap-frontend/src/common/pure/CopyToClipboard/styled.ts (1 hunks)
  • apps/cowswap-frontend/src/modules/tokensList/pure/TokenInfo/index.tsx (2 hunks)
  • apps/cowswap-frontend/src/modules/tokensList/pure/TokenInfo/styled.ts (1 hunks)
  • apps/cowswap-frontend/src/modules/tokensList/pure/TokenListItem/index.tsx (1 hunks)
  • apps/cowswap-frontend/src/modules/tokensList/pure/TokenListItem/styled.ts (2 hunks)
✅ Files skipped from review due to trivial changes (2)
  • apps/cowswap-frontend/src/common/pure/CopyToClipboard/styled.ts
  • apps/cowswap-frontend/src/common/pure/ClickableAddress/styled.ts
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Cypress
  • GitHub Check: Setup
🔇 Additional comments (9)
apps/cowswap-frontend/src/modules/tokensList/pure/TokenInfo/styled.ts (1)

30-35: Good addition of a flex container for the token symbol and address.

The TokenSymbolWrapper component creates a clean horizontal layout with proper spacing (4px gap) for the token symbol and clickable address components.

apps/cowswap-frontend/src/modules/tokensList/pure/TokenInfo/index.tsx (2)

5-5: Good import of the ClickableAddress component.

This import brings in the new functionality for displaying and interacting with token addresses.


21-24: Well implemented token info layout with clickable address.

The token symbol and clickable address are properly wrapped in the new TokenSymbolWrapper component, maintaining a clean layout. The ClickableAddress component receives the necessary props for displaying and linking to the token's address on the blockchain explorer.

apps/cowswap-frontend/src/modules/tokensList/pure/TokenListItem/index.tsx (2)

30-37: Good implementation of the click handler logic.

This approach elegantly solves the issue mentioned in the PR by preventing event propagation only when the token is already selected. For unselected tokens, it properly calls onSelectToken to select the token.


46-47: Good update to use the new click handler and CSS class.

Replacing the disabled attribute with a CSS class and the new click handler ensures that click events can propagate correctly to child components like CopyToClipboard while maintaining the visual distinction for selected tokens.

apps/cowswap-frontend/src/modules/tokensList/pure/TokenListItem/styled.ts (3)

25-25: Setting default opacity to 1 ensures visibility by default.

This change supports the removal of the disabled attribute by ensuring tokens are fully visible by default.


30-32: Good use of CSS class for selected tokens.

Using a CSS class instead of the disabled attribute for styling selected tokens allows click events to propagate while maintaining visual differentiation.


47-49: Prevents background change on hover for selected tokens.

This ensures consistent visual feedback by preventing hover effects on already selected tokens.

apps/cowswap-frontend/src/common/pure/ClickableAddress/index.tsx (1)

53-53:

❓ Verification inconclusive

Verify if the copy icon meets the requirement to appear only on hover.

According to the PR objectives, the copy icon should appear only when hovering over the address. Ensure the styled components are set up correctly to handle this behavior.


🏁 Script executed:

#!/bin/bash
# Look for hover-related styling in the styled components
fd "styled.ts" --exec grep -l "hover" {} \;
fd "styled.ts" --exec grep -l "clickable-address-copy-to-clipboard" {} \;

Length of output: 6532


Hover Behavior Verification for Copy Icon

  • The styled component file at apps/cowswap-frontend/src/common/pure/ClickableAddress/styled.ts contains both hover-related styling and the identifier clickable-address-copy-to-clipboard, which suggests that the hover behavior was addressed.
  • However, the grep results alone don’t confirm that the copy icon is hidden by default and only becomes visible on hover. Please manually inspect the hover styles in the styled file to ensure that the icon is correctly set to appear exclusively when the user hovers over the address.

@cowdan
Copy link
Contributor Author

cowdan commented Feb 27, 2025

recheck

@cowdan
Copy link
Contributor Author

cowdan commented Feb 27, 2025

I have read the CLA Document and I hereby sign the CLA

recheck

Copy link

vercel bot commented Feb 27, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
cowfi ✅ Ready (Inspect) Visit Preview Mar 4, 2025 10:44am
explorer-dev ✅ Ready (Inspect) Visit Preview Mar 4, 2025 10:44am
swap-dev ✅ Ready (Inspect) Visit Preview Mar 4, 2025 10:44am
widget-configurator ✅ Ready (Inspect) Visit Preview Mar 4, 2025 10:44am
2 Skipped Deployments
Name Status Preview Updated (UTC)
cosmos ⬜️ Ignored (Inspect) Visit Preview Mar 4, 2025 10:44am
sdk-tools ⬜️ Ignored (Inspect) Visit Preview Mar 4, 2025 10:44am

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
README.md (1)

292-293: Refine Typographical Punctuation and Wording.

The updated line contains two consecutive periods ("..") at the end and a minor typo ("bellow" should be "below"), along with a slightly awkward phrasing ("only a PR is labeled" could be clearer as "only when a PR is labeled"). Consider addressing these issues for consistency and clarity.

- Some apps (see the list bellow) are not required to be built on each PR so we run them only a PR is labeled with a specific label..
+ Some apps (see the list below) are not required to be built on each PR, so we run them only when a PR is labeled with a specific label.
🧰 Tools
🪛 LanguageTool

[typographical] ~292-~292: Two consecutive dots
Context: ...ly a PR is labeled with a specific label.. This label is defined in the project se...

(DOUBLE_PUNCTUATION)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d3abb93 and 94389be.

📒 Files selected for processing (1)
  • README.md (1 hunks)
🧰 Additional context used
🪛 LanguageTool
README.md

[typographical] ~292-~292: Two consecutive dots
Context: ...ly a PR is labeled with a specific label.. This label is defined in the project se...

(DOUBLE_PUNCTUATION)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Setup
  • GitHub Check: Cypress

Copy link
Contributor

@anxolin anxolin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great to see your first contribution.

I added a few comments.

I think the color of the button is not right for dark mode:
image

Also, are we using this tooltip?
image

Wouldn't we want to use our normal tooltips?
image

margin-left: 4px;
max-width: 20px;
background-color: transparent;
background-image: url('images/click-to-copy.svg');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we use import { Copy } from 'react-feather' on this cowswap-frontend app specifically.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, I've used the CopyHelper

}

// TODO: once we have more chains, we should use the chainId to get the correct explorer
const mapChainIdToExplorer: { [key: string]: { name: string; url: string } } = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be good to already move this to a shared const in our libs folder

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have CHAIN_INFO in libs/common-consts

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p.s. for such type of maps we use Record<SupportedChainId, ValueType> type in order to be safe with adding new networks. With this type If we add a new network we will see compilation errors for all necessary maps.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, used getChainInfo method

align-items: center;

&:hover {
.clickable-address-copy-to-clipboard {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hard coded class name required?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right, removed

@fairlighteth
Copy link
Contributor

  • I think adding a new click to copy is probably redundant here? We already have apps/cowswap-frontend/src/legacy/components/Copy/CopyMod.tsx in this app. E.g used in apps/cowswap-frontend/src/pages/Account/Balances.tsx L257.

I'd suggest to use that and/or take this as an opportunity to refactor (move away from 'legacy' and/or make it somehow a shared lib if appropriate).

Screenshot 2025-02-27 at 17 52 24
  • Darkmode needs the same text color as in light mode Screenshot 2025-02-27 at 17 59 50

  • Hover background color is gone now. This PR:

Screenshot 2025-02-27 at 18 01 27

Develop:

Screenshot 2025-02-27 at 18 01 59


const shortAddress = shortenAddress(address)

const target = useMemo(() => getTarget(address, chainId), [address, chainId])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useMemo is not necessary here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

Copy link
Contributor

@elena-zh elena-zh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @cowdan , great job. thank you!!
However, some issues from my side:

  1. When I open a token list in another chain, the app is crashed
    crash
    To reproduce:
  • No need to connect to a wallet
  • Change a chain using network selector
  • Open a token list in the sell/buy field
  1. WDYT about changing a chain name to a more generic word like 'block explorer'? If we decide to show addresses in other chains, there will no need to change this word for every chain
    image
  2. In the dark mode 'copy' icon is barely visible:
    image
  3. It is impossible to copy an address in a mobile view: when I press on the coly button (on a real device), a token is picked. @fairlighteth , should we still have a copy button in a mobile view?
    image

Thanks!

@cowdan
Copy link
Contributor Author

cowdan commented Feb 28, 2025

Great to see your first contribution.

I added a few comments.

I think the color of the button is not right for dark mode:`

Fixed

Also, are we using this tooltip?

It was the anchor element title attribute

Wouldn't we want to use our normal tooltips?
Right, done

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
README.md (1)

292-292: Fixed punctuation and possible grammar issue.

The period at the end of the sentence is a good addition for correct punctuation. However, there appears to be a grammatical issue in "we run them only a PR is labeled" - consider revising to "we run them only when a PR is labeled" for clarity.

-Some apps (see the list bellow) are not required to be built on each PR so we run them only a PR is labeled with a specific label.
+Some apps (see the list bellow) are not required to be built on each PR so we run them only when a PR is labeled with a specific label.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~292-~292: Possible missing comma found.
Context: ...w) are not required to be built on each PR so we run them only a PR is labeled wit...

(AI_HYDRA_LEO_MISSING_COMMA)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 94389be and 31a598f.

📒 Files selected for processing (5)
  • README.md (1 hunks)
  • apps/cowswap-frontend/src/common/pure/ClickableAddress/index.tsx (1 hunks)
  • apps/cowswap-frontend/src/common/pure/ClickableAddress/styled.ts (1 hunks)
  • apps/cowswap-frontend/src/legacy/components/Copy/CopyMod.tsx (1 hunks)
  • apps/cowswap-frontend/src/modules/tokensList/pure/TokenListItem/styled.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/cowswap-frontend/src/common/pure/ClickableAddress/index.tsx
  • apps/cowswap-frontend/src/common/pure/ClickableAddress/styled.ts
🧰 Additional context used
🪛 LanguageTool
README.md

[uncategorized] ~292-~292: Possible missing comma found.
Context: ...w) are not required to be built on each PR so we run them only a PR is labeled wit...

(AI_HYDRA_LEO_MISSING_COMMA)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Cypress
  • GitHub Check: Setup
🔇 Additional comments (6)
apps/cowswap-frontend/src/legacy/components/Copy/CopyMod.tsx (2)

36-40: Good refactoring of props into a dedicated interface.

Extracting the props into a named interface improves code readability and maintainability. This will make it easier to reuse and extend these props in the future.


42-42: Props type updated to use the new interface.

The function signature now uses the newly defined interface, which is more maintainable than the previous inline type definition.

apps/cowswap-frontend/src/modules/tokensList/pure/TokenListItem/styled.ts (4)

25-25: Simplified opacity handling improves event propagation.

Setting a default opacity of 1 and removing the conditional opacity based on the disabled prop helps address the issue where click events weren't propagating to the CopyToClipboard component.


30-32: New class for selected token items with reduced opacity.

The .token-item-selected class with opacity 0.5 provides visual feedback for selected tokens without using the disabled attribute, which ensures click events can properly propagate through the component.


48-50: Selected tokens don't change background on hover.

This ensures that selected tokens maintain their visual state without additional highlighting on hover, providing a clear distinction between selected and non-selected states.


45-46:

❓ Verification inconclusive

Verify hover background color consistency.

The hover background color has been set to var(${UI.COLOR_PAPER_DARKER}). Based on the PR feedback, please ensure this matches the previous implementation in the develop branch and works consistently in both light and dark modes.


🏁 Script executed:

#!/bin/bash
# Check if the color variable is defined consistently
rg "COLOR_PAPER_DARKER" apps/cowswap-frontend/src --type ts --type tsx

Length of output: 98


I'm seeing that the original command failed with an error because the file type "tsx" isn't recognized. To address this, please re-run the search using a corrected command that adds a custom file type for tsx files. For example:

This should list all instances of COLOR_PAPER_DARKER in both .ts and .tsx files, helping verify that the hover background color (set as var(${UI.COLOR_PAPER_DARKER})) is implemented consistently across light and dark modes as per the develop branch. Please run this updated script and manually verify that the color variable is defined and used consistently.


🏁 Script executed:

#!/bin/bash
# Correctly search for COLOR_PAPER_DARKER usage by defining the tsx file type
rg "COLOR_PAPER_DARKER" apps/cowswap-frontend/src --type-add 'tsx:*.tsx' --type ts --type tsx

Length of output: 17430


Hover background color consistency appears in order.

Our search confirms that var(${UI.COLOR_PAPER_DARKER}) is used consistently across the codebase—including in apps/cowswap-frontend/src/modules/tokensList/pure/TokenListItem/styled.ts (lines 45–46) and multiple other components. This consistency suggests that the hover background color should behave as intended relative to the develop branch implementation.

Please verify manually that the hover state renders correctly in both light and dark modes.

Copy link
Contributor

@elena-zh elena-zh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @cowdan , great job!!!
I have only 2 tiny nitpicks to report:

  1. WDYT about adding 'Sepolia' to the Etherscan in the tooltip when a user is connected to this network?
    sepolia Etherscan
  2. Sometime I face difficulties to press on the copy button even in a desktop view: instead of copying, the token is picked into the field. See the video . Might it be possible to fix this somehow? E.g. increase the 'copy' tap area or so?

Thank you!

@cowdan cowdan requested a review from elena-zh March 3, 2025 16:49
@cowdan
Copy link
Contributor Author

cowdan commented Mar 3, 2025

Hey @cowdan , great job!!! I have only 2 tiny nitpicks to report:

  1. WDYT about adding 'Sepolia' to the Etherscan in the tooltip when a user is connected to this network?
    Yes, done
  1. Sometime I face difficulties to press on the copy button even in a desktop view: instead of copying, the token is picked into the field. See the video . Might it be possible to fix this somehow? E.g. increase the 'copy' tap area or so?
    I now changed the tooltip position to the bottom of the address

@elena-zh
Copy link
Contributor

elena-zh commented Mar 4, 2025

Hey @cowdan , the 1st case LGTM, thank you!
WDYT about removing brackets from 'Sepolia' word there?
image

As for the 2nd issue, I still can face it: each time I click on the copy button, a token is picked into the field. See the video: https://www.loom.com/share/60b6f9e029d741e9b73de07c03e84b32

@cowdan
Copy link
Contributor Author

cowdan commented Mar 4, 2025

Hey @cowdan , the 1st case LGTM, thank you! WDYT about removing brackets from 'Sepolia' word there?

Done

As for the 2nd issue, I still can face it: each time I click on the copy button, a token is picked into the field. See the video:

This is fixed now!

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
apps/cowswap-frontend/src/common/pure/ClickableAddress/index.tsx (3)

11-14: Effective URL generation, but consider handling when chainInfo is undefined

The target URL generation works well using the chain info explorer URL. However, there's no specific error handling or fallback for cases when chainInfo might be undefined.

Consider adding a more graceful fallback or logging when chainInfo is undefined:

const getTarget = (address: string, chainId: number) => {
  const chainInfo = getChainInfo(chainId)
-  return chainInfo ? `${chainInfo.explorer}/address/${address}` : undefined
+  if (!chainInfo) {
+    console.warn(`Chain info not found for chainId: ${chainId}`)
+    return undefined
+  }
+  return `${chainInfo.explorer}/address/${address}`
}

31-34: Consider using typed chainId for better type safety

Based on previous feedback, the team prefers using a specific type for chainId rather than just number.

- export type ClickableAddressProps = {
-   address: string
-   chainId: number
- }
+ import { SupportedChainId } from '@cowprotocol/common-const'
+ 
+ export type ClickableAddressProps = {
+   address: string
+   chainId: SupportedChainId
+ }

This would enforce type safety and align with the team's practice mentioned in previous comments.


53-57: Tooltip implementation with excessive props spreading

The tooltip is implemented correctly, but there's unnecessary props spreading which could pass irrelevant props to the HoverTooltip component.

- <HoverTooltip {...props} placement="bottom" content={title} wrapInContainer>
+ <HoverTooltip placement="bottom" content={title} wrapInContainer>

Since you're not using any other props from props in the HoverTooltip, it's cleaner to avoid spreading all props.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1a101a1 and d2a5862.

📒 Files selected for processing (2)
  • apps/cowswap-frontend/src/common/pure/ClickableAddress/index.tsx (1 hunks)
  • apps/cowswap-frontend/src/legacy/components/Copy/CopyMod.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/cowswap-frontend/src/legacy/components/Copy/CopyMod.tsx
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Lint
  • GitHub Check: Test
  • GitHub Check: Cypress
🔇 Additional comments (6)
apps/cowswap-frontend/src/common/pure/ClickableAddress/index.tsx (6)

16-24: Well-structured title generation with good UX considerations

The title generation logic nicely handles the special case for non-mainnet Etherscan explorers. This provides users with clearer context about which network they're viewing.


26-29: Native token detection is correctly implemented

This aligns with the feedback about not showing addresses for native tokens like ETH since they might lead to unrelated addresses.


44-44: Good UX decision to hide native token addresses

The condition to hide the native token address is well-implemented and aligns with the feedback to omit token addresses for native tokens like ETH.


46-48: Click handler correctly prevents event propagation

This satisfies the PR objective to maintain the current token list view without redirecting to the main swap screen when clicking the address link.


58-60: Correctly using existing CopyHelper component

Following the feedback, you've used the existing CopyHelper component from the legacy codebase rather than creating a duplicate. Setting clickableLink={false} is appropriate to avoid conflicts with the address link.


52-61:

✅ Verification successful

Verify hover state styling in styled components

Make sure the styled components implement the hover state appropriately according to the PR objectives. The address should be visually highlighted (darkened and underlined) on hover, and the copy icon should appear only when hovering.


🏁 Script executed:

#!/bin/bash
# Check if the styled components implement the hover effects properly

# Find the styled.ts file
cat apps/cowswap-frontend/src/common/pure/ClickableAddress/styled.ts

# Look for hover styles in other files referencing ClickableAddress
rg -A 5 -B 5 "ClickableAddress" --type ts --type tsx | grep -i "hover\|transform\|transition\|css"

Length of output: 747


Hover styling verified for ClickableAddress components

The styled components in apps/cowswap-frontend/src/common/pure/ClickableAddress/styled.ts implement the required hover behavior:

  • The AddressWrapper darkens (opacity changes to 0.9) and applies an underline on hover.
  • The Wrapper ensures that child buttons (e.g., the copy icon) are hidden by default and become visible (opacity 0.9) on hover.

Based on the verification, the hover state styling aligns with the PR objectives.

Copy link
Contributor

@elena-zh elena-zh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job, thank you!

@cowdan cowdan merged commit c4e2c13 into develop Mar 4, 2025
13 of 14 checks passed
@cowdan cowdan deleted the add-clickable-token-address branch March 4, 2025 14:13
@github-actions github-actions bot locked and limited conversation to collaborators Mar 4, 2025
@anxolin
Copy link
Contributor

anxolin commented Mar 4, 2025

Congratulation on your first PR getting merged

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants