Skip to content

Conversation

@NeOMakinG
Copy link
Collaborator

@NeOMakinG NeOMakinG commented Aug 7, 2025

Description

Adds both the category page to show the full asset list and the portals tags slider

If you click on any sliders, it will use a different portals API call to filter assets, ordered by volume so the most used ones are on the top

Search input should work on the current asset list which is not 100% accurate as we might want to search on every portals assets but to avoid rate limiting it's quite convenient for now, assuming the best volume should be the most interesting assets

Issue (if applicable)

closes #10108
closes #10109

Risk

Low

High Risk PRs Require 2 approvals

What protocols, transaction types, wallets or contract interactions might be affected by this PR?

Testing

  • You should be able to click on portals tags and see the current list
  • Go back should work as expected
  • Search should work on both explore page and selected category page
  • Bonus I added other categories pages, minus the filter which will be in a follow up
  • Loader states should be good
  • Portals assets should display APY and volume instead of price changes, normal assets should display the price and price changes
  • Selected portal tag should always be visible even when coming from the explore page to a category page

Engineering

Operations

  • 🏁 My feature is behind a flag and doesn't require operations testing (yet)

Screenshots (if applicable)

image image image image image image

Summary by CodeRabbit

  • New Features

    • Introduced category and tag-based navigation in the Explore section, allowing users to filter assets by category and specific DeFi tags.
    • Added a new ExploreCategory page for category-specific asset exploration.
    • Implemented a horizontally scrollable Tags component for quick tag-based filtering.
    • Added "See More" buttons to category cards for easier navigation to detailed category views.
  • Enhancements

    • Asset lists now display loading skeletons for improved user experience during data fetching.
    • Improved styling and overflow handling in asset search results.
    • Enhanced localization with new translation keys for UI elements and DeFi tags.
    • Updated sorting in category cards to prioritize volume.
  • Bug Fixes

    • Improved navigation and UI responsiveness in the Explore section.

@NeOMakinG NeOMakinG requested a review from a team as a code owner August 7, 2025 12:54
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 7, 2025

📝 Walkthrough

Walkthrough

This change introduces category and tag-based filtering to the Explore page, including new routes for category/tag navigation, a tag selector UI, and a new category-specific asset list component with debounced search. Supporting code updates include translation keys, icon mapping, asset query enhancements, and improved loading states and navigation for the asset list and cards.

Changes

Cohort / File(s) Change Summary
Explore Page Routing and Category Feature
src/Routes/RoutesCommon.tsx, src/pages/Explore/ExploreCategory.tsx, src/pages/Explore/components/Tags.tsx, src/pages/Explore/constant.tsx
Added nested routes for category/tag navigation; introduced ExploreCategory component for category-specific asset exploration; added horizontally scrollable tag selector; defined tag constants and icon mapping.
Asset List, Search, and Tag Filtering
src/components/AssetSearch/components/AssetList.tsx, src/pages/Explore/components/AssetSearchRow.tsx, src/pages/Explore/Explore.tsx
Enhanced asset list with loading state and portals assets prop; updated row styling and overflow handling; integrated tag selector and adjusted layout in Explore page.
Category Card Enhancements
src/pages/Explore/components/CategoryCard.tsx
Added "See More" button for navigation to category pages; improved loading skeleton for horizontal layout; switched sorting to volume; localized UI labels.
Market and Portals Query Updates
src/lib/market-service/market-service-manager.ts, src/lib/portals/utils.ts, src/pages/Markets/hooks/usePortalsAssetsQuery.ts
Simplified market provider prioritization logic; added optional tag filtering to portals token fetch and query hook.
Translations
src/assets/translations/en/main.json
Added "seeMore" string and new tag translations under explore.tcy.tags.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ExplorePage
    participant TagsComponent
    participant ExploreCategory
    participant AssetList
    participant PortalsAssetsQuery

    User->>ExplorePage: Navigates to /explore
    ExplorePage->>TagsComponent: Renders tags (if not searching)
    User->>TagsComponent: Selects a tag
    TagsComponent->>ExploreCategory: Navigates to /explore/category/:category/:tag
    ExploreCategory->>PortalsAssetsQuery: Fetch assets with category/tag
    ExploreCategory->>AssetList: Render filtered assets with loading state
    User->>ExploreCategory: Types in search bar
    ExploreCategory->>AssetList: Debounced filter and update list
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Assessment against linked issues

Objective Addressed Explanation
Simple search with debounced input, empty state, category-aware filtering (#10108)
Category tag filters: only one selectable, horizontal scroll, visual highlight, auto-scroll, tag-based filtering (#10109)

Assessment against linked issues: Out-of-scope changes

No out-of-scope changes found.

Suggested reviewers

  • gomesalexandre
  • premiumjibles

Poem

In the garden of code where the tags now bloom,
Categories scroll by with a gentle zoom.
Search is debounced, results are precise,
Skeletons shimmer—loading looks nice!
A rabbit hops by, quite eager to see,
The Explore page’s new harmony.
🐇✨

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch portals-tags

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.

❤️ 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.
    • Explain this complex logic.
    • 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 explain this code block.
  • 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 explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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 generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests 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.

@NeOMakinG NeOMakinG marked this pull request as draft August 7, 2025 12:57
@NeOMakinG NeOMakinG marked this pull request as ready for review August 7, 2025 12:59
Copy link
Contributor

@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: 4

🔭 Outside diff range comments (1)
src/lib/portals/utils.ts (1)

110-112: Fix missing tags parameter in recursive call.

The recursive call for pagination is missing the tags parameter, which will cause subsequent pages to not be filtered by tags, leading to inconsistent results.

Apply this diff to fix the issue:

-      return fetchPortalsTokens({ chainIds, page: page + 1, accTokens: newTokens, limit })
+      return fetchPortalsTokens({ chainIds, page: page + 1, accTokens: newTokens, limit, tags, sortBy, sortDirection, minApy })
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 5b6d7d6 and a11cb0b.

📒 Files selected for processing (14)
  • src/Routes/RoutesCommon.tsx (2 hunks)
  • src/assets/translations/en/main.json (2 hunks)
  • src/components/AssetSearch/components/AssetList.tsx (5 hunks)
  • src/lib/market-service/market-service-manager.ts (1 hunks)
  • src/lib/portals/types.ts (1 hunks)
  • src/lib/portals/utils.ts (3 hunks)
  • src/pages/Explore/Explore.tsx (2 hunks)
  • src/pages/Explore/ExploreCategory.tsx (1 hunks)
  • src/pages/Explore/components/AssetSearchRow.tsx (5 hunks)
  • src/pages/Explore/components/CategoryCard.tsx (5 hunks)
  • src/pages/Explore/components/Tags.tsx (1 hunks)
  • src/pages/Explore/constant.tsx (1 hunks)
  • src/pages/Markets/hooks/usePortalsAssetsQuery.ts (3 hunks)
  • src/state/slices/assetsSlice/selectors.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (.cursor/rules/error-handling.mdc)

**/*.{ts,tsx}: ALWAYS use Result<T, E> pattern for error handling in swappers and APIs
ALWAYS use Ok() and Err() from @sniptt/monads for monadic error handling
ALWAYS use custom error classes from @shapeshiftoss/errors
ALWAYS provide meaningful error codes for internationalization
ALWAYS include relevant details in error objects
ALWAYS wrap async operations in try-catch blocks
ALWAYS use AsyncResultOf utility for converting promises to Results
ALWAYS provide fallback error handling
ALWAYS use timeoutMonadic for API calls
ALWAYS provide appropriate timeout values for API calls
ALWAYS handle timeout errors gracefully
ALWAYS validate inputs before processing
ALWAYS provide clear validation error messages
ALWAYS use early returns for validation failures
ALWAYS log errors for debugging
ALWAYS use structured logging for errors
ALWAYS include relevant context in error logs
Throwing errors instead of using monadic patterns is an anti-pattern
Missing try-catch blocks for async operations is an anti-pattern
Generic error messages without context are an anti-pattern
Not handling specific error types is an anti-pattern
Missing timeout handling is an anti-pattern
No input validation is an anti-pattern
Poor error logging is an anti-pattern
Using any for error types is an anti-pattern
Missing error codes for internationalization is an anti-pattern
No fallback error handling is an anti-pattern
Console.error without structured logging is an anti-pattern

**/*.{ts,tsx}: ALWAYS use camelCase for variables, functions, and methods
ALWAYS use descriptive names that explain the purpose for variables and functions
ALWAYS use verb prefixes for functions that perform actions
ALWAYS use PascalCase for types, interfaces, and enums
ALWAYS use descriptive names that indicate the structure for types, interfaces, and enums
ALWAYS use suffixes like Props, State, Config, Type when appropriate for types and interfaces
ALWAYS use UPPER_SNAKE_CASE for constants and configuration values
ALWAYS use d...

Files:

  • src/state/slices/assetsSlice/selectors.ts
  • src/pages/Explore/Explore.tsx
  • src/pages/Explore/constant.tsx
  • src/pages/Explore/components/AssetSearchRow.tsx
  • src/Routes/RoutesCommon.tsx
  • src/lib/portals/types.ts
  • src/lib/market-service/market-service-manager.ts
  • src/lib/portals/utils.ts
  • src/pages/Explore/components/Tags.tsx
  • src/pages/Explore/components/CategoryCard.tsx
  • src/pages/Markets/hooks/usePortalsAssetsQuery.ts
  • src/pages/Explore/ExploreCategory.tsx
  • src/components/AssetSearch/components/AssetList.tsx
**/*

📄 CodeRabbit Inference Engine (.cursor/rules/naming-conventions.mdc)

**/*: ALWAYS use appropriate file extensions
Flag files without kebab-case

Files:

  • src/state/slices/assetsSlice/selectors.ts
  • src/pages/Explore/Explore.tsx
  • src/pages/Explore/constant.tsx
  • src/pages/Explore/components/AssetSearchRow.tsx
  • src/Routes/RoutesCommon.tsx
  • src/lib/portals/types.ts
  • src/lib/market-service/market-service-manager.ts
  • src/lib/portals/utils.ts
  • src/pages/Explore/components/Tags.tsx
  • src/pages/Explore/components/CategoryCard.tsx
  • src/assets/translations/en/main.json
  • src/pages/Markets/hooks/usePortalsAssetsQuery.ts
  • src/pages/Explore/ExploreCategory.tsx
  • src/components/AssetSearch/components/AssetList.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit Inference Engine (.cursor/rules/react-best-practices.mdc)

USE Redux only for global state shared across multiple places

Files:

  • src/state/slices/assetsSlice/selectors.ts
  • src/pages/Explore/Explore.tsx
  • src/pages/Explore/constant.tsx
  • src/pages/Explore/components/AssetSearchRow.tsx
  • src/Routes/RoutesCommon.tsx
  • src/lib/portals/types.ts
  • src/lib/market-service/market-service-manager.ts
  • src/lib/portals/utils.ts
  • src/pages/Explore/components/Tags.tsx
  • src/pages/Explore/components/CategoryCard.tsx
  • src/pages/Markets/hooks/usePortalsAssetsQuery.ts
  • src/pages/Explore/ExploreCategory.tsx
  • src/components/AssetSearch/components/AssetList.tsx
**/*.tsx

📄 CodeRabbit Inference Engine (.cursor/rules/error-handling.mdc)

**/*.tsx: ALWAYS wrap components in error boundaries
ALWAYS provide user-friendly fallback components in error boundaries
ALWAYS log errors for debugging in error boundaries
ALWAYS use useErrorToast hook for displaying errors
ALWAYS provide translated error messages in error toasts
ALWAYS handle different error types appropriately in error toasts
Missing error boundaries in React components is an anti-pattern

**/*.tsx: ALWAYS use PascalCase for React component names
ALWAYS use descriptive names that indicate the component's purpose
ALWAYS match the component name to the file name
Flag components without PascalCase
Flag default exports for components

Files:

  • src/pages/Explore/Explore.tsx
  • src/pages/Explore/constant.tsx
  • src/pages/Explore/components/AssetSearchRow.tsx
  • src/Routes/RoutesCommon.tsx
  • src/pages/Explore/components/Tags.tsx
  • src/pages/Explore/components/CategoryCard.tsx
  • src/pages/Explore/ExploreCategory.tsx
  • src/components/AssetSearch/components/AssetList.tsx
**/*.{tsx,jsx}

📄 CodeRabbit Inference Engine (.cursor/rules/react-best-practices.mdc)

**/*.{tsx,jsx}: ALWAYS use useMemo for expensive computations, object/array creations, and filtered data
ALWAYS use useMemo for derived values and computed properties
ALWAYS use useMemo for conditional values and simple transformations
ALWAYS use useCallback for event handlers and functions passed as props
ALWAYS use useCallback for any function that could be passed as a prop or dependency
ALWAYS include all dependencies in useEffect, useMemo, useCallback dependency arrays
NEVER use // eslint-disable-next-line react-hooks/exhaustive-deps unless absolutely necessary
ALWAYS explain why dependencies are excluded if using eslint disable
ALWAYS use named exports for components
NEVER use default exports for components
KEEP component files under 200 lines when possible
BREAK DOWN large components into smaller, reusable pieces
EXTRACT complex logic into custom hooks
USE local state for component-level state
LIFT state up when needed across multiple components
USE Context for avoiding prop drilling
ALWAYS wrap components in error boundaries for production
ALWAYS handle async errors properly
ALWAYS provide user-friendly error messages
ALWAYS use virtualization for lists with 100+ items
ALWAYS implement proper key props for list items
ALWAYS lazy load heavy components
ALWAYS use React.lazy for code splitting
Components receiving props are wrapped with memo

Files:

  • src/pages/Explore/Explore.tsx
  • src/pages/Explore/constant.tsx
  • src/pages/Explore/components/AssetSearchRow.tsx
  • src/Routes/RoutesCommon.tsx
  • src/pages/Explore/components/Tags.tsx
  • src/pages/Explore/components/CategoryCard.tsx
  • src/pages/Explore/ExploreCategory.tsx
  • src/components/AssetSearch/components/AssetList.tsx
**/use*.{ts,tsx}

📄 CodeRabbit Inference Engine (.cursor/rules/naming-conventions.mdc)

**/use*.{ts,tsx}: ALWAYS use use prefix for custom hooks
ALWAYS use descriptive names that indicate the hook's purpose
ALWAYS use camelCase after the use prefix for custom hooks

Files:

  • src/pages/Markets/hooks/usePortalsAssetsQuery.ts
🧠 Learnings (59)
📓 Common learnings
Learnt from: NeOMakinG
PR: shapeshift/web#10136
File: src/lib/asset-service/service/encodedRelatedAssetIndex.json:1-1
Timestamp: 2025-07-29T10:22:27.037Z
Learning: PRs with titles starting with "feat: regenerate asset data" are routine daily asset updates that don't need detailed code analysis. Users prefer to skip automated reviews for these maintenance PRs using coderabbitai ignore.
Learnt from: NeOMakinG
PR: shapeshift/web#10191
File: src/pages/Explore/Explore.tsx:54-72
Timestamp: 2025-08-06T11:02:09.501Z
Learning: In src/pages/Explore/Explore.tsx, NeOMakinG indicated that memoizing the ExploreCard component would be unnecessary, questioning "why would we memoize that", suggesting that like CategoryCard, this component doesn't benefit from memoization despite receiving props, likely due to its specific usage patterns in the carousel with static content.
Learnt from: NeOMakinG
PR: shapeshift/web#10128
File: .cursor/rules/error-handling.mdc:266-274
Timestamp: 2025-07-29T10:35:22.059Z
Learning: NeOMakinG prefers less nitpicky suggestions on documentation and best practices files, finding overly detailed suggestions on minor implementation details (like console.error vs logger.error) too granular for cursor rules documentation.
📚 Learning: applies to packages/swapper/src/swappers/*/{*.ts,endpoints.ts} : verify chain id filtering in filter...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-07-24T09:43:11.699Z
Learning: Applies to packages/swapper/src/swappers/*/{*.ts,endpoints.ts} : Verify chain ID filtering in filterAssetIdsBySellable and filterBuyAssetsBySellAssetId methods.

Applied to files:

  • src/state/slices/assetsSlice/selectors.ts
  • src/pages/Explore/components/AssetSearchRow.tsx
  • src/lib/market-service/market-service-manager.ts
  • src/pages/Markets/hooks/usePortalsAssetsQuery.ts
  • src/components/AssetSearch/components/AssetList.tsx
📚 Learning: the assetid type from '@shapeshiftoss/caip' package is a string type alias, so it can be used direct...
Learnt from: premiumjibles
PR: shapeshift/web#10187
File: src/state/slices/preferencesSlice/selectors.ts:21-25
Timestamp: 2025-08-05T23:36:13.214Z
Learning: The AssetId type from 'shapeshiftoss/caip' package is a string type alias, so it can be used directly as a return type for cache key resolvers in re-reselect selectors without needing explicit string conversion.

Applied to files:

  • src/state/slices/assetsSlice/selectors.ts
  • src/pages/Markets/hooks/usePortalsAssetsQuery.ts
📚 Learning: applies to **/*.{ts,tsx} : flag renamed imports without good reason...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/naming-conventions.mdc:0-0
Timestamp: 2025-08-03T22:10:11.424Z
Learning: Applies to **/*.{ts,tsx} : Flag renamed imports without good reason

Applied to files:

  • src/state/slices/assetsSlice/selectors.ts
  • src/pages/Explore/Explore.tsx
  • src/Routes/RoutesCommon.tsx
📚 Learning: in the shapeshift/web codebase, component imports use direct file paths like '@/components/component...
Learnt from: premiumjibles
PR: shapeshift/web#10187
File: src/pages/Assets/Asset.tsx:1-1
Timestamp: 2025-08-05T22:41:35.473Z
Learning: In the shapeshift/web codebase, component imports use direct file paths like '@/components/ComponentName/ComponentName' rather than barrel exports. The AssetAccountDetails component should be imported as '@/components/AssetAccountDetails/AssetAccountDetails', not from a directory index.

Applied to files:

  • src/state/slices/assetsSlice/selectors.ts
  • src/pages/Explore/Explore.tsx
  • src/pages/Explore/components/AssetSearchRow.tsx
  • src/Routes/RoutesCommon.tsx
  • src/pages/Explore/components/CategoryCard.tsx
  • src/pages/Explore/ExploreCategory.tsx
  • src/components/AssetSearch/components/AssetList.tsx
📚 Learning: applies to **/*.{ts,tsx} : always use descriptive import names...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/naming-conventions.mdc:0-0
Timestamp: 2025-08-03T22:10:11.424Z
Learning: Applies to **/*.{ts,tsx} : ALWAYS use descriptive import names

Applied to files:

  • src/state/slices/assetsSlice/selectors.ts
📚 Learning: applies to **/*.{ts,tsx} : always avoid renaming imports unless necessary...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/naming-conventions.mdc:0-0
Timestamp: 2025-08-03T22:10:11.424Z
Learning: Applies to **/*.{ts,tsx} : ALWAYS avoid renaming imports unless necessary

Applied to files:

  • src/state/slices/assetsSlice/selectors.ts
📚 Learning: applies to packages/swapper/src/swappers/*/{*.ts,endpoints.ts} : avoid side effects in swap logic wi...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-07-24T09:43:11.699Z
Learning: Applies to packages/swapper/src/swappers/*/{*.ts,endpoints.ts} : Avoid side effects in swap logic within swapper implementation files.

Applied to files:

  • src/state/slices/assetsSlice/selectors.ts
📚 Learning: applies to **/*.{ts,tsx} : utility types are used for common transformations...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/typescript-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:11:30.833Z
Learning: Applies to **/*.{ts,tsx} : Utility types are used for common transformations

Applied to files:

  • src/state/slices/assetsSlice/selectors.ts
📚 Learning: applies to **/*.{ts,tsx} : always use named exports for components and functions...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/naming-conventions.mdc:0-0
Timestamp: 2025-08-03T22:10:11.424Z
Learning: Applies to **/*.{ts,tsx} : ALWAYS use named exports for components and functions

Applied to files:

  • src/state/slices/assetsSlice/selectors.ts
  • src/pages/Explore/components/Tags.tsx
📚 Learning: applies to packages/swapper/src/index.ts : export unique functions/types from packages/swapper/src/i...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-07-24T09:43:11.699Z
Learning: Applies to packages/swapper/src/index.ts : Export unique functions/types from packages/swapper/src/index.ts if needed.

Applied to files:

  • src/state/slices/assetsSlice/selectors.ts
📚 Learning: in src/state/apis/swapper/helpers/swapperapihelpers.ts, the getstate parameter in processquoteresult...
Learnt from: premiumjibles
PR: shapeshift/web#10154
File: src/state/apis/swapper/helpers/swapperApiHelpers.ts:57-60
Timestamp: 2025-07-31T03:51:48.479Z
Learning: In src/state/apis/swapper/helpers/swapperApiHelpers.ts, the getState parameter in processQuoteResultWithRatios uses `() => unknown` type instead of `() => ReduxState` to avoid type compatibility issues elsewhere in the codebase.

Applied to files:

  • src/state/slices/assetsSlice/selectors.ts
📚 Learning: in src/pages/explore/explore.tsx, neomaking prefers keeping complex height calculations inline rathe...
Learnt from: NeOMakinG
PR: shapeshift/web#10191
File: src/pages/Explore/Explore.tsx:174-178
Timestamp: 2025-08-06T09:47:29.865Z
Learning: In src/pages/Explore/Explore.tsx, NeOMakinG prefers keeping complex height calculations inline rather than extracting them to useMemo, prioritizing perceived performance/execution speed over code readability, even when the calculation would only run when the dependency (isSearching) changes.

Applied to files:

  • src/pages/Explore/Explore.tsx
  • src/pages/Explore/components/AssetSearchRow.tsx
  • src/Routes/RoutesCommon.tsx
  • src/pages/Explore/components/Tags.tsx
  • src/pages/Explore/components/CategoryCard.tsx
  • src/pages/Explore/ExploreCategory.tsx
  • src/components/AssetSearch/components/AssetList.tsx
📚 Learning: in src/pages/explore/explore.tsx, neomaking indicated that memoizing the explorecard component would...
Learnt from: NeOMakinG
PR: shapeshift/web#10191
File: src/pages/Explore/Explore.tsx:54-72
Timestamp: 2025-08-06T11:02:09.501Z
Learning: In src/pages/Explore/Explore.tsx, NeOMakinG indicated that memoizing the ExploreCard component would be unnecessary, questioning "why would we memoize that", suggesting that like CategoryCard, this component doesn't benefit from memoization despite receiving props, likely due to its specific usage patterns in the carousel with static content.

Applied to files:

  • src/pages/Explore/Explore.tsx
  • src/pages/Explore/components/AssetSearchRow.tsx
  • src/Routes/RoutesCommon.tsx
  • src/pages/Explore/components/Tags.tsx
  • src/pages/Explore/components/CategoryCard.tsx
  • src/pages/Explore/ExploreCategory.tsx
📚 Learning: in src/pages/explore/explore.tsx, neomaking questioned the suggestion to memoize a simple static car...
Learnt from: NeOMakinG
PR: shapeshift/web#10191
File: src/pages/Explore/Explore.tsx:81-83
Timestamp: 2025-08-06T11:44:30.697Z
Learning: In src/pages/Explore/Explore.tsx, NeOMakinG questioned the suggestion to memoize a simple static carouselOptions object ({ loop: true }), indicating that static objects that never change should remain as module-level constants rather than being memoized inside components, as memoization would add unnecessary overhead for truly static values.

Applied to files:

  • src/pages/Explore/Explore.tsx
  • src/pages/Explore/constant.tsx
  • src/pages/Explore/components/AssetSearchRow.tsx
  • src/Routes/RoutesCommon.tsx
  • src/pages/Explore/components/Tags.tsx
  • src/pages/Explore/components/CategoryCard.tsx
  • src/pages/Explore/ExploreCategory.tsx
📚 Learning: applies to **/*.tsx : flag default exports for components...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/naming-conventions.mdc:0-0
Timestamp: 2025-08-03T22:10:11.424Z
Learning: Applies to **/*.tsx : Flag default exports for components

Applied to files:

  • src/pages/Explore/Explore.tsx
📚 Learning: applies to **/*.{tsx,jsx} : extract complex logic into custom hooks...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:10:38.426Z
Learning: Applies to **/*.{tsx,jsx} : EXTRACT complex logic into custom hooks

Applied to files:

  • src/pages/Explore/Explore.tsx
  • src/Routes/RoutesCommon.tsx
  • src/pages/Explore/components/Tags.tsx
  • src/pages/Explore/components/CategoryCard.tsx
  • src/pages/Explore/ExploreCategory.tsx
  • src/components/AssetSearch/components/AssetList.tsx
📚 Learning: in src/pages/explore/components/categorycard.tsx, neomaking indicated that wrapping the categorycard...
Learnt from: NeOMakinG
PR: shapeshift/web#10191
File: src/pages/Explore/components/CategoryCard.tsx:27-196
Timestamp: 2025-08-06T09:46:50.860Z
Learning: In src/pages/Explore/components/CategoryCard.tsx, NeOMakinG indicated that wrapping the CategoryCard component with React.memo would be "quite useless in this case", suggesting that memoization is not beneficial for this particular component despite it receiving props, likely due to its specific usage patterns or context.

Applied to files:

  • src/pages/Explore/Explore.tsx
  • src/Routes/RoutesCommon.tsx
  • src/pages/Explore/components/Tags.tsx
  • src/pages/Explore/components/CategoryCard.tsx
  • src/pages/Explore/ExploreCategory.tsx
📚 Learning: applies to **/*.tsx : always use descriptive names that indicate the component's purpose...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/naming-conventions.mdc:0-0
Timestamp: 2025-08-03T22:10:11.424Z
Learning: Applies to **/*.tsx : ALWAYS use descriptive names that indicate the component's purpose

Applied to files:

  • src/pages/Explore/Explore.tsx
  • src/pages/Explore/components/AssetSearchRow.tsx
  • src/pages/Explore/components/Tags.tsx
  • src/pages/Explore/ExploreCategory.tsx
📚 Learning: applies to **/*.{tsx,jsx} : break down large components into smaller, reusable pieces...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:10:38.426Z
Learning: Applies to **/*.{tsx,jsx} : BREAK DOWN large components into smaller, reusable pieces

Applied to files:

  • src/pages/Explore/Explore.tsx
  • src/pages/Explore/components/AssetSearchRow.tsx
  • src/pages/Explore/components/Tags.tsx
  • src/pages/Explore/components/CategoryCard.tsx
  • src/pages/Explore/ExploreCategory.tsx
  • src/components/AssetSearch/components/AssetList.tsx
📚 Learning: applies to **/*.tsx : missing error boundaries in react components is an anti-pattern...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/error-handling.mdc:0-0
Timestamp: 2025-08-03T22:09:37.542Z
Learning: Applies to **/*.tsx : Missing error boundaries in React components is an anti-pattern

Applied to files:

  • src/pages/Explore/Explore.tsx
  • src/pages/Explore/components/Tags.tsx
  • src/pages/Explore/ExploreCategory.tsx
📚 Learning: in the shapeshift web app, css custom properties like `--safe-area-inset-top` and `--safe-area-inset...
Learnt from: NeOMakinG
PR: shapeshift/web#10133
File: src/components/MultiHopTrade/components/SharedTradeInput/SharedTradeInput.tsx:37-40
Timestamp: 2025-07-29T08:57:09.276Z
Learning: In the ShapeShift web app, CSS custom properties like `--safe-area-inset-top` and `--safe-area-inset-bottom` are centrally initialized to '0px' in src/theme/theme.tsx within the global body styles. The mobile app overrides these values when running in mobile app scope. This architectural approach eliminates the need for fallback values in var() expressions throughout the codebase, since the variables are guaranteed to be defined.

Applied to files:

  • src/pages/Explore/Explore.tsx
📚 Learning: in the shapeshift web app's mobile header architecture, the `--mobile-header-offset` css variable re...
Learnt from: NeOMakinG
PR: shapeshift/web#10079
File: src/pages/Dashboard/components/DashboardHeader/DashboardHeaderWrapper.tsx:8-11
Timestamp: 2025-07-24T11:29:00.743Z
Learning: In the ShapeShift web app's mobile header architecture, the `--mobile-header-offset` CSS variable represents the total height of the entire mobile header, while the 56px paddingTop in DashboardHeaderWrapper is specifically for spacing the top bar content area only. These serve different purposes and should not be conflated - the header offset is for positioning the entire header, while the paddingTop is for internal content spacing.

Applied to files:

  • src/pages/Explore/Explore.tsx
📚 Learning: in the shapeshift web app's mobile header implementation, dynamically calculating the top bar height...
Learnt from: NeOMakinG
PR: shapeshift/web#10079
File: src/pages/Dashboard/components/DashboardHeader/DashboardHeaderWrapper.tsx:8-11
Timestamp: 2025-07-24T11:29:49.740Z
Learning: In the ShapeShift web app's mobile header implementation, dynamically calculating the top bar height for paddingTop would introduce maintenance complexity because the measured height might include safe area padding, which would be incorrect for the spacing use case. The hardcoded 56px approach is preferred over dynamic calculations to avoid this complexity and maintain code simplicity.

Applied to files:

  • src/pages/Explore/Explore.tsx
📚 Learning: applies to **/*.{tsx,jsx} : always use virtualization for lists with 100+ items...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:10:38.426Z
Learning: Applies to **/*.{tsx,jsx} : ALWAYS use virtualization for lists with 100+ items

Applied to files:

  • src/pages/Explore/Explore.tsx
  • src/pages/Explore/components/Tags.tsx
  • src/pages/Explore/components/CategoryCard.tsx
  • src/components/AssetSearch/components/AssetList.tsx
📚 Learning: applies to **/*.{ts,tsx} : enums are used for constants...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/typescript-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:11:30.833Z
Learning: Applies to **/*.{ts,tsx} : Enums are used for constants

Applied to files:

  • src/pages/Explore/constant.tsx
📚 Learning: applies to **/*.{ts,tsx} : using strings instead of enums for constants...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/typescript-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:11:30.833Z
Learning: Applies to **/*.{ts,tsx} : Using strings instead of enums for constants

Applied to files:

  • src/pages/Explore/constant.tsx
📚 Learning: applies to packages/swapper/src/{constants,types}.ts : register new swappers in packages/swapper/src...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-07-24T09:43:11.699Z
Learning: Applies to packages/swapper/src/{constants,types}.ts : Register new swappers in packages/swapper/src/constants.ts and add them to the SwapperName enum in packages/swapper/src/types.ts.

Applied to files:

  • src/pages/Explore/constant.tsx
📚 Learning: applies to **/*.{ts,tsx} : always group related constants together...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/naming-conventions.mdc:0-0
Timestamp: 2025-08-03T22:10:11.424Z
Learning: Applies to **/*.{ts,tsx} : ALWAYS group related constants together

Applied to files:

  • src/pages/Explore/constant.tsx
📚 Learning: applies to **/*.{ts,tsx} : always use enums for constants...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/typescript-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:11:30.833Z
Learning: Applies to **/*.{ts,tsx} : ALWAYS use enums for constants

Applied to files:

  • src/pages/Explore/constant.tsx
📚 Learning: check registry entry in constants.ts during code review....
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-07-24T09:43:11.699Z
Learning: Check registry entry in constants.ts during code review.

Applied to files:

  • src/pages/Explore/constant.tsx
📚 Learning: applies to **/*.{ts,tsx} : prefer use enums for constants, especially on types, statuses, codes...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/typescript-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:11:30.833Z
Learning: Applies to **/*.{ts,tsx} : PREFER use enums for constants, especially on types, statuses, codes

Applied to files:

  • src/pages/Explore/constant.tsx
📚 Learning: applies to **/*.{ts,tsx} : always use descriptive enum names...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/typescript-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:11:30.833Z
Learning: Applies to **/*.{ts,tsx} : ALWAYS use descriptive enum names

Applied to files:

  • src/pages/Explore/constant.tsx
📚 Learning: applies to **/*.{ts,tsx} : always use descriptive names that explain the value's purpose for constan...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/naming-conventions.mdc:0-0
Timestamp: 2025-08-03T22:10:11.424Z
Learning: Applies to **/*.{ts,tsx} : ALWAYS use descriptive names that explain the value's purpose for constants

Applied to files:

  • src/pages/Explore/constant.tsx
📚 Learning: in src/components/markettablevirtualized/marketstablevirtualized.tsx, neomaking prefers keeping the ...
Learnt from: NeOMakinG
PR: shapeshift/web#10148
File: src/components/MarketTableVirtualized/MarketsTableVirtualized.tsx:88-91
Timestamp: 2025-07-30T20:57:48.176Z
Learning: In src/components/MarketTableVirtualized/MarketsTableVirtualized.tsx, NeOMakinG prefers keeping the hardcoded overscan value (40) over dynamic calculation based on viewport height, prioritizing code simplicity over precision when the current approach works effectively.

Applied to files:

  • src/pages/Explore/components/AssetSearchRow.tsx
  • src/pages/Explore/components/Tags.tsx
  • src/pages/Explore/ExploreCategory.tsx
  • src/components/AssetSearch/components/AssetList.tsx
📚 Learning: in src/components/multihoptrade/components/tradeconfirm/components/expandablesteppersteps.tsx, the c...
Learnt from: NeOMakinG
PR: shapeshift/web#10139
File: src/components/MultiHopTrade/components/TradeConfirm/components/ExpandableStepperSteps.tsx:109-115
Timestamp: 2025-07-29T15:04:28.083Z
Learning: In src/components/MultiHopTrade/components/TradeConfirm/components/ExpandableStepperSteps.tsx, the component is used under an umbrella that 100% of the time contains the quote, making the type assertion `activeTradeQuote?.steps[currentHopIndex] as TradeQuoteStep` safe. Adding conditional returns before hooks would violate React's Rules of Hooks.

Applied to files:

  • src/pages/Explore/components/AssetSearchRow.tsx
  • src/Routes/RoutesCommon.tsx
  • src/pages/Explore/components/Tags.tsx
  • src/pages/Explore/components/CategoryCard.tsx
  • src/pages/Explore/ExploreCategory.tsx
  • src/components/AssetSearch/components/AssetList.tsx
📚 Learning: applies to **/*.{ts,tsx} : always use descriptive property names...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/typescript-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:11:30.833Z
Learning: Applies to **/*.{ts,tsx} : ALWAYS use descriptive property names

Applied to files:

  • src/pages/Explore/components/AssetSearchRow.tsx
📚 Learning: applies to **/*.{ts,tsx} : function types are properly defined...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/typescript-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:11:30.833Z
Learning: Applies to **/*.{ts,tsx} : Function types are properly defined

Applied to files:

  • src/lib/portals/utils.ts
📚 Learning: applies to **/*.{ts,tsx} : optional properties are marked with `?`...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/typescript-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:11:30.833Z
Learning: Applies to **/*.{ts,tsx} : Optional properties are marked with `?`

Applied to files:

  • src/lib/portals/utils.ts
  • src/pages/Markets/hooks/usePortalsAssetsQuery.ts
📚 Learning: in src/lib/moralis.ts, gomesalexandre doesn't require explicit return type annotations for simple ut...
Learnt from: gomesalexandre
PR: shapeshift/web#10206
File: src/lib/moralis.ts:24-30
Timestamp: 2025-08-07T12:10:57.967Z
Learning: In src/lib/moralis.ts, gomesalexandre doesn't require explicit return type annotations for simple utility functions like startMoralis, preferring to keep them concise when the return type is obvious from context.

Applied to files:

  • src/lib/portals/utils.ts
📚 Learning: applies to **/*.{tsx,jsx} : always use named exports for components...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:10:38.426Z
Learning: Applies to **/*.{tsx,jsx} : ALWAYS use named exports for components

Applied to files:

  • src/pages/Explore/components/Tags.tsx
📚 Learning: applies to **/*.{tsx,jsx} : never use `// eslint-disable-next-line react-hooks/exhaustive-deps` unle...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:10:38.426Z
Learning: Applies to **/*.{tsx,jsx} : NEVER use `// eslint-disable-next-line react-hooks/exhaustive-deps` unless absolutely necessary

Applied to files:

  • src/pages/Explore/components/Tags.tsx
📚 Learning: the shapeshift team practices aggressive memoization in react components as documented in .cursor/ru...
Learnt from: NeOMakinG
PR: shapeshift/web#10128
File: .cursor/rules/react-best-practices.mdc:8-14
Timestamp: 2025-07-29T10:27:23.424Z
Learning: The ShapeShift team practices aggressive memoization in React components as documented in .cursor/rules/react-best-practices.mdc. They use useMemo for all transformations, derived values, and conditional values, and useCallback for all event handlers and functions that could be passed as props. This approach was adopted after experiencing performance issues ("had hard time") and is their current established practice, though they acknowledge it may evolve in the future.

Applied to files:

  • src/pages/Explore/components/CategoryCard.tsx
  • src/components/AssetSearch/components/AssetList.tsx
📚 Learning: applies to **/*.{tsx,jsx} : always use `usememo` for conditional values and simple transformations...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:10:38.426Z
Learning: Applies to **/*.{tsx,jsx} : ALWAYS use `useMemo` for conditional values and simple transformations

Applied to files:

  • src/pages/Explore/components/CategoryCard.tsx
📚 Learning: applies to **/*.{tsx,jsx} : always use `usememo` for expensive computations, object/array creations,...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:10:38.426Z
Learning: Applies to **/*.{tsx,jsx} : ALWAYS use `useMemo` for expensive computations, object/array creations, and filtered data

Applied to files:

  • src/pages/Explore/components/CategoryCard.tsx
📚 Learning: applies to **/*.{tsx,jsx} : lift state up when needed across multiple components...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:10:38.426Z
Learning: Applies to **/*.{tsx,jsx} : LIFT state up when needed across multiple components

Applied to files:

  • src/pages/Explore/components/CategoryCard.tsx
  • src/components/AssetSearch/components/AssetList.tsx
📚 Learning: applies to **/use*.{ts,tsx} : always use camelcase after the use prefix for custom hooks...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/naming-conventions.mdc:0-0
Timestamp: 2025-08-03T22:10:11.424Z
Learning: Applies to **/use*.{ts,tsx} : ALWAYS use camelCase after the use prefix for custom hooks

Applied to files:

  • src/pages/Explore/components/CategoryCard.tsx
  • src/pages/Markets/hooks/usePortalsAssetsQuery.ts
📚 Learning: applies to **/use*.{ts,tsx} : always use descriptive names that indicate the hook's purpose...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/naming-conventions.mdc:0-0
Timestamp: 2025-08-03T22:10:11.424Z
Learning: Applies to **/use*.{ts,tsx} : ALWAYS use descriptive names that indicate the hook's purpose

Applied to files:

  • src/pages/Explore/components/CategoryCard.tsx
  • src/pages/Markets/hooks/usePortalsAssetsQuery.ts
📚 Learning: in the shapeshift web app carousel dot buttons (src/components/carousel/dotbutton.tsx), the blue.500...
Learnt from: NeOMakinG
PR: shapeshift/web#10191
File: src/components/Carousel/DotButton.tsx:6-9
Timestamp: 2025-08-06T09:45:26.568Z
Learning: In the ShapeShift web app carousel dot buttons (src/components/Carousel/DotButton.tsx), the blue.500 color is intentionally used for both light and dark themes rather than using adaptive theming with useColorModeValue. This is a deliberate design decision to maintain consistent visual appearance for carousel navigation elements.

Applied to files:

  • src/pages/Explore/components/CategoryCard.tsx
📚 Learning: in the shapeshift web repository, translation workflow follows a two-step process: 1) first pr adds ...
Learnt from: 0xApotheosis
PR: shapeshift/web#10073
File: src/components/Layout/Header/ActionCenter/components/Details/ClaimDetails.tsx:10-11
Timestamp: 2025-07-24T21:05:13.642Z
Learning: In the ShapeShift web repository, translation workflow follows a two-step process: 1) First PR adds only English translations to src/assets/translations/en/main.json, 2) Globalization team handles follow-up PRs to add keys to remaining language files (de, es, fr, id, ja, ko, pt, ru, tr, uk, zh). Don't suggest verifying all locale files simultaneously during initial feature PRs.

Applied to files:

  • src/assets/translations/en/main.json
📚 Learning: when reviewing json diffs in translation files, distinguish between syntax-required changes (like ad...
Learnt from: gomesalexandre
PR: shapeshift/web#10154
File: src/assets/translations/en/main.json:1004-1006
Timestamp: 2025-08-04T13:33:22.878Z
Learning: When reviewing JSON diffs in translation files, distinguish between syntax-required changes (like adding commas to existing lines to accommodate new entries) versus actual content modifications. A comma addition to an existing line is often just JSON syntax infrastructure, not an intentional change to that line's content.

Applied to files:

  • src/assets/translations/en/main.json
📚 Learning: gomesalexandre considers translation key consolidation (like multiple keys for "view on explorer" fu...
Learnt from: gomesalexandre
PR: shapeshift/web#10187
File: src/assets/translations/en/main.json:205-206
Timestamp: 2025-08-06T08:58:09.096Z
Learning: gomesalexandre considers translation key consolidation (like multiple keys for "view on explorer" functionality) as nice-to-have improvements rather than critical issues. The team doesn't prioritize i18n consistency across the board currently, and they prefer to handle such consolidation suggestions at their own discretion based on other priorities.

Applied to files:

  • src/assets/translations/en/main.json
📚 Learning: applies to **/!use*.{ts,tsx} : flag custom hooks without use prefix...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/naming-conventions.mdc:0-0
Timestamp: 2025-08-03T22:10:11.424Z
Learning: Applies to **/!use*.{ts,tsx} : Flag custom hooks without use prefix

Applied to files:

  • src/pages/Markets/hooks/usePortalsAssetsQuery.ts
📚 Learning: applies to **/use*.{ts,tsx} : always use use prefix for custom hooks...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/naming-conventions.mdc:0-0
Timestamp: 2025-08-03T22:10:11.424Z
Learning: Applies to **/use*.{ts,tsx} : ALWAYS use use prefix for custom hooks

Applied to files:

  • src/pages/Markets/hooks/usePortalsAssetsQuery.ts
📚 Learning: applies to **/*.{tsx,jsx} : always implement proper key props for list items...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:10:38.426Z
Learning: Applies to **/*.{tsx,jsx} : ALWAYS implement proper key props for list items

Applied to files:

  • src/components/AssetSearch/components/AssetList.tsx
📚 Learning: applies to **/*.{tsx,jsx} : always lazy load heavy components...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:10:38.426Z
Learning: Applies to **/*.{tsx,jsx} : ALWAYS lazy load heavy components

Applied to files:

  • src/components/AssetSearch/components/AssetList.tsx
📚 Learning: applies to **/*.{tsx,jsx} : use context for avoiding prop drilling...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:10:38.426Z
Learning: Applies to **/*.{tsx,jsx} : USE Context for avoiding prop drilling

Applied to files:

  • src/components/AssetSearch/components/AssetList.tsx
📚 Learning: applies to **/*.{tsx,jsx} : components receiving props are wrapped with `memo`...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:10:38.426Z
Learning: Applies to **/*.{tsx,jsx} : Components receiving props are wrapped with `memo`

Applied to files:

  • src/components/AssetSearch/components/AssetList.tsx
📚 Learning: applies to **/*.tsx : always provide user-friendly fallback components in error boundaries...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/error-handling.mdc:0-0
Timestamp: 2025-08-03T22:09:37.542Z
Learning: Applies to **/*.tsx : ALWAYS provide user-friendly fallback components in error boundaries

Applied to files:

  • src/components/AssetSearch/components/AssetList.tsx
🧬 Code Graph Analysis (4)
src/pages/Explore/Explore.tsx (1)
src/pages/Explore/components/Tags.tsx (1)
  • Tags (18-115)
src/Routes/RoutesCommon.tsx (1)
src/pages/Explore/ExploreCategory.tsx (1)
  • ExploreCategory (34-227)
src/pages/Explore/components/Tags.tsx (1)
src/pages/Explore/constant.tsx (1)
  • exploreTagsIcons (16-24)
src/components/AssetSearch/components/AssetList.tsx (2)
src/pages/Markets/hooks/usePortalsAssetsQuery.ts (1)
  • PortalsAssets (15-19)
src/state/slices/assetsSlice/assetsSlice.ts (1)
  • assets (42-64)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Install and Cache
🔇 Additional comments (25)
src/pages/Explore/constant.tsx (1)

6-14: Well-structured enum with appropriate naming conventions.

The PortalsTags enum follows TypeScript best practices with descriptive PascalCase naming and string values suitable for URL parameters and API calls.

src/state/slices/assetsSlice/selectors.ts (1)

13-15: LGTM - Import formatting improvement.

The change from single-line to multi-line import is a formatting improvement that maintains consistency with other imports in the file.

src/pages/Explore/Explore.tsx (2)

27-27: LGTM - Clean import of the Tags component.

The import follows established patterns in the codebase and correctly adds the new Tags component.


205-205: Well-implemented conditional rendering for Tags component.

The Tags component is appropriately rendered only when not searching, which provides a clean UX by hiding category filters during search operations. This aligns well with the search-focused state management in the component.

src/pages/Markets/hooks/usePortalsAssetsQuery.ts (2)

27-28: Well-designed optional parameter addition.

The tags parameter is properly typed as optional (string[]) and maintains backward compatibility while enabling new tag-based filtering functionality.

Also applies to: 34-35


47-47: Proper cache key management and parameter propagation.

The tags parameter is correctly included in the query key to ensure cache differentiation based on tags, and properly passed through to the fetchPortalsTokens function call.

Also applies to: 60-60

src/Routes/RoutesCommon.tsx (2)

24-24: LGTM! Import follows established patterns.

The import uses the correct direct file path pattern consistent with the codebase conventions.


233-244: LGTM! Route configuration is well-structured.

The nested routes properly support the category and tag filtering functionality:

  • Both routes correctly render the ExploreCategory component
  • Routes are appropriately marked as hide: true since they're sub-routes
  • Parameter names :category and :tag align with the component's expected parameters
  • The optional tag parameter on Line 240 enables flexible navigation
src/lib/portals/utils.ts (1)

25-34: LGTM! Parameter addition follows good TypeScript practices.

The tags parameter is properly:

  • Typed as optional string[]
  • Added to the function signature and destructured parameters
  • Included in the API request parameters

Also applies to: 54-54

src/assets/translations/en/main.json (1)

133-134: seeMore key addition looks correct

Key is unique within the common block, JSON syntax is preserved, and the label matches surrounding style (title-case).
No further action required.

src/lib/market-service/market-service-manager.ts (1)

72-86: LGTM! Simplified provider lookup logic.

The removal of special prioritization for pool tokens makes the provider lookup more uniform and predictable. The method now respects the provider order defined in the constructor for all asset types.

src/pages/Explore/components/AssetSearchRow.tsx (2)

37-37: Props restructuring looks good.

The extraction of portalsAssets from the data prop aligns with the updated component usage pattern across the codebase.


169-177: Good addition of text overflow handling.

The CSS properties for handling text overflow (textOverflow, whiteSpace, maxWidth, overflow) properly constrain long symbol names and prevent layout issues.

src/pages/Explore/components/Tags.tsx (2)

31-36: Navigation uses fixed category path.

The navigation path uses a hardcoded MarketsCategories.OneClickDefi category. This is acceptable if the Tags component is specifically designed for the OneClickDefi explore page, but consider making it configurable if reusability across different categories is needed in the future.


45-68: Well-implemented auto-scroll behavior.

The auto-scroll logic properly centers the active tag button when it's outside the visible area, providing a good user experience with smooth scrolling.

src/pages/Explore/components/CategoryCard.tsx (2)

63-66: Sorting by volume aligns with PR objectives.

The change from APY to Volume sorting ensures the most actively traded assets appear first, which provides better asset discovery for users.


205-212: Good addition of navigation button.

The "See More" button is properly positioned and provides clear navigation to the full category page, improving the user experience for exploring more assets.

src/pages/Explore/ExploreCategory.tsx (2)

107-122: Well-implemented search with appropriate filtering.

The search functionality properly:

  • Filters out low market cap assets to avoid spam
  • Uses fuzzy matching for better user experience
  • Limits results to 20 for performance
  • Matches against name, symbol, and assetId fields

216-221: Comprehensive loading state management.

Good practice combining both isLoading and isFetching states from multiple queries to provide accurate loading feedback during initial load and data refetching.

src/components/AssetSearch/components/AssetList.tsx (6)

2-2: LGTM! Import additions are appropriate.

The new imports (Flex, Skeleton from Chakra UI and range from lodash) are correctly added to support the loading skeleton implementation, and the PortalsAssets type import provides proper typing.

Also applies to: 4-4, 17-17


25-26: LGTM! Optional props are properly typed.

The new optional props isLoading and portalsAssets are correctly typed with appropriate defaults and optional indicators.


42-43: LGTM! Props destructuring with proper defaults.

The component correctly destructures the new props with appropriate default values (isLoading = false and optional portalsAssets).


79-81: LGTM! Memoization dependencies are correctly updated.

The itemData useMemo correctly includes portalsAssets in the dependency array, ensuring proper memoization when portalsAssets changes. This follows the team's aggressive memoization practices.


86-106: LGTM! Loading skeleton implementation is well-structured.

The loading state implementation provides a good user experience with:

  • Three skeleton rows mimicking the actual asset row structure
  • Proper layout with icon, name/balance placeholders, and price information
  • Consistent spacing and styling
  • Early return pattern for clean conditional rendering

The skeleton structure accurately represents the actual asset row layout.


131-131: LGTM! Dependency array correctly updated.

The renderContent callback properly includes isLoading in its dependency array to ensure the component re-renders when the loading state changes.

Copy link
Contributor

@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

♻️ Duplicate comments (1)
src/pages/Explore/components/Tags.tsx (1)

89-115: ESLint suppressions indicate missing memoization - but based on previous feedback, this may be acceptable.

The inline ref callback and onClick handler have ESLint suppressions. While these could be memoized with useCallback, previous learnings from this developer suggest they prefer keeping inline handlers in some cases for simplicity.

Based on previous feedback from NeOMakinG about memoization preferences, the current approach with ESLint suppressions may be intentional for this component's usage pattern.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 5915abd and a5a6c3b.

📒 Files selected for processing (1)
  • src/pages/Explore/components/Tags.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (.cursor/rules/error-handling.mdc)

**/*.{ts,tsx}: ALWAYS use Result<T, E> pattern for error handling in swappers and APIs
ALWAYS use Ok() and Err() from @sniptt/monads for monadic error handling
ALWAYS use custom error classes from @shapeshiftoss/errors
ALWAYS provide meaningful error codes for internationalization
ALWAYS include relevant details in error objects
ALWAYS wrap async operations in try-catch blocks
ALWAYS use AsyncResultOf utility for converting promises to Results
ALWAYS provide fallback error handling
ALWAYS use timeoutMonadic for API calls
ALWAYS provide appropriate timeout values for API calls
ALWAYS handle timeout errors gracefully
ALWAYS validate inputs before processing
ALWAYS provide clear validation error messages
ALWAYS use early returns for validation failures
ALWAYS log errors for debugging
ALWAYS use structured logging for errors
ALWAYS include relevant context in error logs
Throwing errors instead of using monadic patterns is an anti-pattern
Missing try-catch blocks for async operations is an anti-pattern
Generic error messages without context are an anti-pattern
Not handling specific error types is an anti-pattern
Missing timeout handling is an anti-pattern
No input validation is an anti-pattern
Poor error logging is an anti-pattern
Using any for error types is an anti-pattern
Missing error codes for internationalization is an anti-pattern
No fallback error handling is an anti-pattern
Console.error without structured logging is an anti-pattern

**/*.{ts,tsx}: ALWAYS use camelCase for variables, functions, and methods
ALWAYS use descriptive names that explain the purpose for variables and functions
ALWAYS use verb prefixes for functions that perform actions
ALWAYS use PascalCase for types, interfaces, and enums
ALWAYS use descriptive names that indicate the structure for types, interfaces, and enums
ALWAYS use suffixes like Props, State, Config, Type when appropriate for types and interfaces
ALWAYS use UPPER_SNAKE_CASE for constants and configuration values
ALWAYS use d...

Files:

  • src/pages/Explore/components/Tags.tsx
**/*.tsx

📄 CodeRabbit Inference Engine (.cursor/rules/error-handling.mdc)

**/*.tsx: ALWAYS wrap components in error boundaries
ALWAYS provide user-friendly fallback components in error boundaries
ALWAYS log errors for debugging in error boundaries
ALWAYS use useErrorToast hook for displaying errors
ALWAYS provide translated error messages in error toasts
ALWAYS handle different error types appropriately in error toasts
Missing error boundaries in React components is an anti-pattern

**/*.tsx: ALWAYS use PascalCase for React component names
ALWAYS use descriptive names that indicate the component's purpose
ALWAYS match the component name to the file name
Flag components without PascalCase
Flag default exports for components

Files:

  • src/pages/Explore/components/Tags.tsx
**/*

📄 CodeRabbit Inference Engine (.cursor/rules/naming-conventions.mdc)

**/*: ALWAYS use appropriate file extensions
Flag files without kebab-case

Files:

  • src/pages/Explore/components/Tags.tsx
**/*.{tsx,jsx}

📄 CodeRabbit Inference Engine (.cursor/rules/react-best-practices.mdc)

**/*.{tsx,jsx}: ALWAYS use useMemo for expensive computations, object/array creations, and filtered data
ALWAYS use useMemo for derived values and computed properties
ALWAYS use useMemo for conditional values and simple transformations
ALWAYS use useCallback for event handlers and functions passed as props
ALWAYS use useCallback for any function that could be passed as a prop or dependency
ALWAYS include all dependencies in useEffect, useMemo, useCallback dependency arrays
NEVER use // eslint-disable-next-line react-hooks/exhaustive-deps unless absolutely necessary
ALWAYS explain why dependencies are excluded if using eslint disable
ALWAYS use named exports for components
NEVER use default exports for components
KEEP component files under 200 lines when possible
BREAK DOWN large components into smaller, reusable pieces
EXTRACT complex logic into custom hooks
USE local state for component-level state
LIFT state up when needed across multiple components
USE Context for avoiding prop drilling
ALWAYS wrap components in error boundaries for production
ALWAYS handle async errors properly
ALWAYS provide user-friendly error messages
ALWAYS use virtualization for lists with 100+ items
ALWAYS implement proper key props for list items
ALWAYS lazy load heavy components
ALWAYS use React.lazy for code splitting
Components receiving props are wrapped with memo

Files:

  • src/pages/Explore/components/Tags.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit Inference Engine (.cursor/rules/react-best-practices.mdc)

USE Redux only for global state shared across multiple places

Files:

  • src/pages/Explore/components/Tags.tsx
🧠 Learnings (17)
📓 Common learnings
Learnt from: NeOMakinG
PR: shapeshift/web#10136
File: src/lib/asset-service/service/encodedRelatedAssetIndex.json:1-1
Timestamp: 2025-07-29T10:22:27.037Z
Learning: PRs with titles starting with "feat: regenerate asset data" are routine daily asset updates that don't need detailed code analysis. Users prefer to skip automated reviews for these maintenance PRs using coderabbitai ignore.
Learnt from: NeOMakinG
PR: shapeshift/web#10191
File: src/pages/Explore/Explore.tsx:54-72
Timestamp: 2025-08-06T11:02:09.501Z
Learning: In src/pages/Explore/Explore.tsx, NeOMakinG indicated that memoizing the ExploreCard component would be unnecessary, questioning "why would we memoize that", suggesting that like CategoryCard, this component doesn't benefit from memoization despite receiving props, likely due to its specific usage patterns in the carousel with static content.
Learnt from: NeOMakinG
PR: shapeshift/web#10128
File: .cursor/rules/error-handling.mdc:266-274
Timestamp: 2025-07-29T10:35:22.059Z
Learning: NeOMakinG prefers less nitpicky suggestions on documentation and best practices files, finding overly detailed suggestions on minor implementation details (like console.error vs logger.error) too granular for cursor rules documentation.
📚 Learning: in src/pages/explore/explore.tsx, neomaking indicated that memoizing the explorecard component would...
Learnt from: NeOMakinG
PR: shapeshift/web#10191
File: src/pages/Explore/Explore.tsx:54-72
Timestamp: 2025-08-06T11:02:09.501Z
Learning: In src/pages/Explore/Explore.tsx, NeOMakinG indicated that memoizing the ExploreCard component would be unnecessary, questioning "why would we memoize that", suggesting that like CategoryCard, this component doesn't benefit from memoization despite receiving props, likely due to its specific usage patterns in the carousel with static content.

Applied to files:

  • src/pages/Explore/components/Tags.tsx
📚 Learning: in src/pages/explore/explore.tsx, neomaking prefers keeping complex height calculations inline rathe...
Learnt from: NeOMakinG
PR: shapeshift/web#10191
File: src/pages/Explore/Explore.tsx:174-178
Timestamp: 2025-08-06T09:47:29.865Z
Learning: In src/pages/Explore/Explore.tsx, NeOMakinG prefers keeping complex height calculations inline rather than extracting them to useMemo, prioritizing perceived performance/execution speed over code readability, even when the calculation would only run when the dependency (isSearching) changes.

Applied to files:

  • src/pages/Explore/components/Tags.tsx
📚 Learning: in src/pages/explore/components/categorycard.tsx, neomaking indicated that wrapping the categorycard...
Learnt from: NeOMakinG
PR: shapeshift/web#10191
File: src/pages/Explore/components/CategoryCard.tsx:27-196
Timestamp: 2025-08-06T09:46:50.860Z
Learning: In src/pages/Explore/components/CategoryCard.tsx, NeOMakinG indicated that wrapping the CategoryCard component with React.memo would be "quite useless in this case", suggesting that memoization is not beneficial for this particular component despite it receiving props, likely due to its specific usage patterns or context.

Applied to files:

  • src/pages/Explore/components/Tags.tsx
📚 Learning: applies to **/*.{tsx,jsx} : break down large components into smaller, reusable pieces...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:10:38.426Z
Learning: Applies to **/*.{tsx,jsx} : BREAK DOWN large components into smaller, reusable pieces

Applied to files:

  • src/pages/Explore/components/Tags.tsx
📚 Learning: applies to **/*.{tsx,jsx} : extract complex logic into custom hooks...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:10:38.426Z
Learning: Applies to **/*.{tsx,jsx} : EXTRACT complex logic into custom hooks

Applied to files:

  • src/pages/Explore/components/Tags.tsx
📚 Learning: applies to **/*.tsx : always use descriptive names that indicate the component's purpose...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/naming-conventions.mdc:0-0
Timestamp: 2025-08-03T22:10:11.424Z
Learning: Applies to **/*.tsx : ALWAYS use descriptive names that indicate the component's purpose

Applied to files:

  • src/pages/Explore/components/Tags.tsx
📚 Learning: applies to **/*.tsx : missing error boundaries in react components is an anti-pattern...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/error-handling.mdc:0-0
Timestamp: 2025-08-03T22:09:37.542Z
Learning: Applies to **/*.tsx : Missing error boundaries in React components is an anti-pattern

Applied to files:

  • src/pages/Explore/components/Tags.tsx
📚 Learning: in src/pages/explore/explore.tsx, neomaking questioned the suggestion to memoize a simple static car...
Learnt from: NeOMakinG
PR: shapeshift/web#10191
File: src/pages/Explore/Explore.tsx:81-83
Timestamp: 2025-08-06T11:44:30.697Z
Learning: In src/pages/Explore/Explore.tsx, NeOMakinG questioned the suggestion to memoize a simple static carouselOptions object ({ loop: true }), indicating that static objects that never change should remain as module-level constants rather than being memoized inside components, as memoization would add unnecessary overhead for truly static values.

Applied to files:

  • src/pages/Explore/components/Tags.tsx
📚 Learning: applies to **/*.tsx : always use pascalcase for react component names...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/naming-conventions.mdc:0-0
Timestamp: 2025-08-03T22:10:11.424Z
Learning: Applies to **/*.tsx : ALWAYS use PascalCase for React component names

Applied to files:

  • src/pages/Explore/components/Tags.tsx
📚 Learning: in src/components/multihoptrade/components/tradeconfirm/components/expandablesteppersteps.tsx, the c...
Learnt from: NeOMakinG
PR: shapeshift/web#10139
File: src/components/MultiHopTrade/components/TradeConfirm/components/ExpandableStepperSteps.tsx:109-115
Timestamp: 2025-07-29T15:04:28.083Z
Learning: In src/components/MultiHopTrade/components/TradeConfirm/components/ExpandableStepperSteps.tsx, the component is used under an umbrella that 100% of the time contains the quote, making the type assertion `activeTradeQuote?.steps[currentHopIndex] as TradeQuoteStep` safe. Adding conditional returns before hooks would violate React's Rules of Hooks.

Applied to files:

  • src/pages/Explore/components/Tags.tsx
📚 Learning: applies to **/*.{tsx,jsx} : always use `usecallback` for event handlers and functions passed as prop...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:10:38.426Z
Learning: Applies to **/*.{tsx,jsx} : ALWAYS use `useCallback` for event handlers and functions passed as props

Applied to files:

  • src/pages/Explore/components/Tags.tsx
📚 Learning: applies to **/*.{tsx,jsx} : always use `usecallback` for any function that could be passed as a prop...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:10:38.426Z
Learning: Applies to **/*.{tsx,jsx} : ALWAYS use `useCallback` for any function that could be passed as a prop or dependency

Applied to files:

  • src/pages/Explore/components/Tags.tsx
📚 Learning: applies to **/*.{tsx,jsx} : never use `// eslint-disable-next-line react-hooks/exhaustive-deps` unle...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:10:38.426Z
Learning: Applies to **/*.{tsx,jsx} : NEVER use `// eslint-disable-next-line react-hooks/exhaustive-deps` unless absolutely necessary

Applied to files:

  • src/pages/Explore/components/Tags.tsx
📚 Learning: applies to **/*.{tsx,jsx} : components receiving props are wrapped with `memo`...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:10:38.426Z
Learning: Applies to **/*.{tsx,jsx} : Components receiving props are wrapped with `memo`

Applied to files:

  • src/pages/Explore/components/Tags.tsx
📚 Learning: in src/components/markettablevirtualized/marketstablevirtualized.tsx, neomaking prefers keeping the ...
Learnt from: NeOMakinG
PR: shapeshift/web#10148
File: src/components/MarketTableVirtualized/MarketsTableVirtualized.tsx:88-91
Timestamp: 2025-07-30T20:57:48.176Z
Learning: In src/components/MarketTableVirtualized/MarketsTableVirtualized.tsx, NeOMakinG prefers keeping the hardcoded overscan value (40) over dynamic calculation based on viewport height, prioritizing code simplicity over precision when the current approach works effectively.

Applied to files:

  • src/pages/Explore/components/Tags.tsx
📚 Learning: applies to **/*.{tsx,jsx} : always use virtualization for lists with 100+ items...
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:10:38.426Z
Learning: Applies to **/*.{tsx,jsx} : ALWAYS use virtualization for lists with 100+ items

Applied to files:

  • src/pages/Explore/components/Tags.tsx
🧬 Code Graph Analysis (1)
src/pages/Explore/components/Tags.tsx (1)
src/pages/Explore/constant.tsx (1)
  • exploreTagsIcons (16-24)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Install and Cache
🔇 Additional comments (8)
src/pages/Explore/components/Tags.tsx (8)

1-9: LGTM! Clean imports and proper organization.

The imports are well-organized and follow proper naming conventions. All necessary dependencies are imported appropriately.


10-16: Good use of CSS-in-JS for scrollbar hiding.

The containerSx object properly hides scrollbars across different browsers while maintaining functionality.


31-36: LGTM! Proper use of useCallback for navigation handler.

The handleClick function is correctly memoized with useCallback and includes the navigate dependency.


38-43: LGTM! Proper memoization of style object.

The activeStyle object is correctly memoized to prevent unnecessary re-renders.


45-71: LGTM! Well-implemented auto-scroll functionality.

The useEffect properly handles scrolling the active tag into view with smooth behavior. The dependency array is correct and the logic handles edge cases well.


73-75: LGTM! Proper ref callback implementation.

The handleButtonRef function is correctly memoized with useCallback and has the right dependencies.


77-118: LGTM! Well-structured JSX with proper styling and accessibility.

The JSX structure is clean and follows good practices:

  • Proper use of Chakra UI components and styling
  • Accessible button implementation
  • Good use of flexbox for layout
  • Proper state management for active/inactive styles
  • Translation integration works correctly

18-29: Component needs memoization and proper TypeScript types.

The component receives no props but should be wrapped with memo per coding guidelines. Additionally, explicit return type should be added.

Apply this diff to add proper memoization and typing:

-export const Tags = () => {
+export const Tags = memo((): JSX.Element => {

Don't forget to add the import:

-import { useCallback, useEffect, useMemo, useRef } from 'react'
+import { memo, useCallback, useEffect, useMemo, useRef } from 'react'
⛔ Skipped due to learnings
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:10:38.426Z
Learning: Applies to **/*.{tsx,jsx} : Components receiving props are wrapped with `memo`
Learnt from: NeOMakinG
PR: shapeshift/web#10191
File: src/pages/Explore/components/CategoryCard.tsx:27-196
Timestamp: 2025-08-06T09:46:50.860Z
Learning: In src/pages/Explore/components/CategoryCard.tsx, NeOMakinG indicated that wrapping the CategoryCard component with React.memo would be "quite useless in this case", suggesting that memoization is not beneficial for this particular component despite it receiving props, likely due to its specific usage patterns or context.
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:10:38.426Z
Learning: Applies to **/*.{tsx,jsx} : ALWAYS use `useMemo` for conditional values and simple transformations
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:10:38.426Z
Learning: Applies to **/*.{tsx,jsx} : ALWAYS use `useMemo` for expensive computations, object/array creations, and filtered data
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:10:38.426Z
Learning: Applies to **/*.{tsx,jsx} : ALWAYS use `useMemo` for derived values and computed properties
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:10:38.426Z
Learning: Applies to **/*.{tsx,jsx} : ALWAYS use `useCallback` for any function that could be passed as a prop or dependency
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:10:38.426Z
Learning: Applies to **/*.{tsx,jsx} : EXTRACT complex logic into custom hooks
Learnt from: NeOMakinG
PR: shapeshift/web#10191
File: src/pages/Explore/Explore.tsx:54-72
Timestamp: 2025-08-06T11:02:09.501Z
Learning: In src/pages/Explore/Explore.tsx, NeOMakinG indicated that memoizing the ExploreCard component would be unnecessary, questioning "why would we memoize that", suggesting that like CategoryCard, this component doesn't benefit from memoization despite receiving props, likely due to its specific usage patterns in the carousel with static content.
Learnt from: NeOMakinG
PR: shapeshift/web#10128
File: .cursor/rules/react-best-practices.mdc:8-14
Timestamp: 2025-07-29T10:27:23.424Z
Learning: The ShapeShift team practices aggressive memoization in React components as documented in .cursor/rules/react-best-practices.mdc. They use useMemo for all transformations, derived values, and conditional values, and useCallback for all event handlers and functions that could be passed as props. This approach was adopted after experiencing performance issues ("had hard time") and is their current established practice, though they acknowledge it may evolve in the future.
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:10:38.426Z
Learning: Applies to **/*.{tsx,jsx} : ALWAYS include all dependencies in `useEffect`, `useMemo`, `useCallback` dependency arrays
Learnt from: NeOMakinG
PR: shapeshift/web#10191
File: src/pages/Explore/Explore.tsx:174-178
Timestamp: 2025-08-06T09:47:29.865Z
Learning: In src/pages/Explore/Explore.tsx, NeOMakinG prefers keeping complex height calculations inline rather than extracting them to useMemo, prioritizing perceived performance/execution speed over code readability, even when the calculation would only run when the dependency (isSearching) changes.

@gomesalexandre gomesalexandre self-requested a review August 7, 2025 14:08
Copy link
Contributor

@gomesalexandre gomesalexandre left a comment

Choose a reason for hiding this comment

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

Conceptually looks sane to me - runtime test to follow

Copy link
Contributor

@gomesalexandre gomesalexandre left a comment

Choose a reason for hiding this comment

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

LGTM!

https://jam.dev/c/c592e28a-8cca-4eb3-802e-45e634aad076

Bit weird to have lending and liquid staking as discussed, as just holding those tokens doesn't make you have a lending position/liquid staking position in and by itself, but product concern which will take a few lines to nuke after

@NeOMakinG
Copy link
Collaborator Author

LGTM!

https://jam.dev/c/c592e28a-8cca-4eb3-802e-45e634aad076

Bit weird to have lending and liquid staking as discussed, as just holding those tokens doesn't make you have a lending position/liquid staking position in and by itself, but product concern which will take a few lines to nuke after

@shapeshift/product FYI, if we want to remove liquid staking and lending!

@NeOMakinG NeOMakinG enabled auto-merge (squash) August 7, 2025 16:38
Copy link
Contributor

@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: 1

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 9910f9c and b432e02.

📒 Files selected for processing (1)
  • src/assets/translations/en/main.json (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*

📄 CodeRabbit Inference Engine (.cursor/rules/naming-conventions.mdc)

**/*: ALWAYS use appropriate file extensions
Flag files without kebab-case

Files:

  • src/assets/translations/en/main.json
🧠 Learnings (16)
📓 Common learnings
Learnt from: NeOMakinG
PR: shapeshift/web#10136
File: src/lib/asset-service/service/encodedRelatedAssetIndex.json:1-1
Timestamp: 2025-07-29T10:22:27.037Z
Learning: PRs with titles starting with "feat: regenerate asset data" are routine daily asset updates that don't need detailed code analysis. Users prefer to skip automated reviews for these maintenance PRs using coderabbitai ignore.
Learnt from: NeOMakinG
PR: shapeshift/web#10191
File: src/pages/Explore/Explore.tsx:54-72
Timestamp: 2025-08-06T11:02:09.501Z
Learning: In src/pages/Explore/Explore.tsx, NeOMakinG indicated that memoizing the ExploreCard component would be unnecessary, questioning "why would we memoize that", suggesting that like CategoryCard, this component doesn't benefit from memoization despite receiving props, likely due to its specific usage patterns in the carousel with static content.
Learnt from: NeOMakinG
PR: shapeshift/web#10128
File: .cursor/rules/error-handling.mdc:266-274
Timestamp: 2025-07-29T10:35:22.059Z
Learning: NeOMakinG prefers less nitpicky suggestions on documentation and best practices files, finding overly detailed suggestions on minor implementation details (like console.error vs logger.error) too granular for cursor rules documentation.
📚 Learning: 2025-07-24T21:05:13.642Z
Learnt from: 0xApotheosis
PR: shapeshift/web#10073
File: src/components/Layout/Header/ActionCenter/components/Details/ClaimDetails.tsx:10-11
Timestamp: 2025-07-24T21:05:13.642Z
Learning: In the ShapeShift web repository, translation workflow follows a two-step process: 1) First PR adds only English translations to src/assets/translations/en/main.json, 2) Globalization team handles follow-up PRs to add keys to remaining language files (de, es, fr, id, ja, ko, pt, ru, tr, uk, zh). Don't suggest verifying all locale files simultaneously during initial feature PRs.

Applied to files:

  • src/assets/translations/en/main.json
📚 Learning: 2025-08-04T13:33:22.878Z
Learnt from: gomesalexandre
PR: shapeshift/web#10154
File: src/assets/translations/en/main.json:1004-1006
Timestamp: 2025-08-04T13:33:22.878Z
Learning: When reviewing JSON diffs in translation files, distinguish between syntax-required changes (like adding commas to existing lines to accommodate new entries) versus actual content modifications. A comma addition to an existing line is often just JSON syntax infrastructure, not an intentional change to that line's content.

Applied to files:

  • src/assets/translations/en/main.json
📚 Learning: 2025-08-06T08:58:09.096Z
Learnt from: gomesalexandre
PR: shapeshift/web#10187
File: src/assets/translations/en/main.json:205-206
Timestamp: 2025-08-06T08:58:09.096Z
Learning: gomesalexandre considers translation key consolidation (like multiple keys for "view on explorer" functionality) as nice-to-have improvements rather than critical issues. The team doesn't prioritize i18n consistency across the board currently, and they prefer to handle such consolidation suggestions at their own discretion based on other priorities.

Applied to files:

  • src/assets/translations/en/main.json
📚 Learning: 2025-07-24T13:49:39.586Z
Learnt from: firebomb1
PR: shapeshift/web#0
File: :0-0
Timestamp: 2025-07-24T13:49:39.586Z
Learning: Translation-only PRs that sync localization files (like biweekly translation updates) typically don't benefit from detailed code analysis suggestions, and users may prefer to use coderabbitai ignore for such routine maintenance PRs.

Applied to files:

  • src/assets/translations/en/main.json
📚 Learning: 2025-08-03T22:11:30.833Z
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/typescript-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:11:30.833Z
Learning: Applies to **/*.{ts,tsx} : ALWAYS use descriptive enum names

Applied to files:

  • src/assets/translations/en/main.json
📚 Learning: 2025-07-24T09:43:11.699Z
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-07-24T09:43:11.699Z
Learning: Check registry entry in constants.ts during code review.

Applied to files:

  • src/assets/translations/en/main.json
📚 Learning: 2025-07-24T09:43:11.699Z
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-07-24T09:43:11.699Z
Learning: Applies to packages/swapper/src/swappers/*/{*.ts,endpoints.ts} : Verify chain ID filtering in filterAssetIdsBySellable and filterBuyAssetsBySellAssetId methods.

Applied to files:

  • src/assets/translations/en/main.json
📚 Learning: 2025-08-03T22:11:30.833Z
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/typescript-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:11:30.833Z
Learning: Applies to **/*.{ts,tsx} : String enums are used for better debugging

Applied to files:

  • src/assets/translations/en/main.json
📚 Learning: 2025-08-03T22:11:30.833Z
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/typescript-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:11:30.833Z
Learning: Applies to **/*.{ts,tsx} : ALWAYS use string enums for better debugging

Applied to files:

  • src/assets/translations/en/main.json
📚 Learning: 2025-08-03T22:09:37.542Z
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/error-handling.mdc:0-0
Timestamp: 2025-08-03T22:09:37.542Z
Learning: Applies to **/*.{ts,tsx} : Missing error codes for internationalization is an anti-pattern

Applied to files:

  • src/assets/translations/en/main.json
📚 Learning: 2025-08-03T22:10:11.424Z
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/naming-conventions.mdc:0-0
Timestamp: 2025-08-03T22:10:11.424Z
Learning: Applies to **/*.{ts,tsx} : Flag abbreviations that aren't widely understood

Applied to files:

  • src/assets/translations/en/main.json
📚 Learning: 2025-08-03T22:09:37.542Z
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/error-handling.mdc:0-0
Timestamp: 2025-08-03T22:09:37.542Z
Learning: Applies to **/swapper/**/*.{ts,tsx} : ALWAYS use TradeQuoteError enum for error codes in swapper errors

Applied to files:

  • src/assets/translations/en/main.json
📚 Learning: 2025-08-03T22:11:30.833Z
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/typescript-best-practices.mdc:0-0
Timestamp: 2025-08-03T22:11:30.833Z
Learning: Applies to **/*.{ts,tsx} : PREFER use enums for constants, especially on types, statuses, codes

Applied to files:

  • src/assets/translations/en/main.json
📚 Learning: 2025-07-29T10:22:27.037Z
Learnt from: NeOMakinG
PR: shapeshift/web#10136
File: src/lib/asset-service/service/encodedRelatedAssetIndex.json:1-1
Timestamp: 2025-07-29T10:22:27.037Z
Learning: PRs with titles starting with "feat: regenerate asset data" are routine daily asset updates that don't need detailed code analysis. Users prefer to skip automated reviews for these maintenance PRs using coderabbitai ignore.

Applied to files:

  • src/assets/translations/en/main.json
📚 Learning: 2025-07-24T09:43:11.699Z
Learnt from: CR
PR: shapeshift/web#0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-07-24T09:43:11.699Z
Learning: Applies to packages/swapper/src/swappers/*/{*.ts,endpoints.ts} : Include comments explaining swap logic in swapper implementation files.

Applied to files:

  • src/assets/translations/en/main.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Install and Cache
🔇 Additional comments (1)
src/assets/translations/en/main.json (1)

133-133: "seeMore" key looks good

Key/value pair added correctly; no further issues spotted.

Comment on lines +2662 to +2670
},
"tags": {
"liquid-staking": "Liquid Staking",
"yield": "Yield",
"lending": "Lending",
"rwa": "RWA",
"yield-aggregator": "Yield Aggregator",
"pool": "Pool",
"clp": "CLP"
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Potential duplicate explore.tags block – please verify

A tags object for the Explore page already existed in previous commits. Adding the same object again will silently override earlier keys at load time or, depending on the JSON loader, even break parsing.

Please confirm there is only a single "tags" object under "explore" in the final file.

If multiple occurrences appear, remove the redundant block or merge the entries.


🏁 Script executed:

#!/bin/bash
# Show all occurrences of "explore.tags" to detect duplicates
rg -n '"explore"\s*:\s*\{' -A15 src/assets/translations/en/main.json | grep -n '"tags"' -C2

Length of output: 93


🏁 Script executed:

#!/bin/bash
# Locate every "explore" key and list any "tags" entries within the next 30 lines
rg -n '"explore"' src/assets/translations/en/main.json | cut -d: -f1 | while read -r ln; do
  echo "→ explore block at line $ln:"
  sed -n "${ln},$((ln+30))p" src/assets/translations/en/main.json | grep -n '"tags"'
done

Length of output: 412


Consolidate explore translations into a single block

Our inspection shows two separate "explore" objects in src/assets/translations/en/main.json (at lines ~612 and ~2647), but only the second contains your new "tags" section. Having duplicate top-level keys will either override earlier entries or break parsing.

Please merge the new "tags" entries into the existing "explore" block (around line 612) and remove the redundant block at line 2647:

• File: src/assets/translations/en/main.json
– Existing explore block starts at ~612
– Redundant explore block (with "tags") starts at ~2647

Action items:

  1. Cut the "tags": { … } object from the second block.
  2. Paste it under the first "explore" object.
  3. Delete the now-empty second "explore" block.

This will ensure there’s only one "explore" key and prevent silently dropped or overridden translations.

🤖 Prompt for AI Agents
In src/assets/translations/en/main.json around lines 612 and 2647, there are two
separate "explore" objects causing duplicate keys. To fix this, cut the "tags"
object from the second "explore" block at line 2647, paste it inside the first
"explore" block near line 612, and then delete the entire second "explore" block
to ensure only one consolidated "explore" key remains.

@0xApotheosis 0xApotheosis disabled auto-merge August 8, 2025 01:17
@0xApotheosis 0xApotheosis merged commit e686911 into develop Aug 8, 2025
4 checks passed
@0xApotheosis 0xApotheosis deleted the portals-tags branch August 8, 2025 01:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement category tag filters functionality Add Simple Search

4 participants