Skip to Content
Welcome to RitoSwap's documentation!
DAppPortfolio UISelection Components

Selection Components

The selection components form the configuration layer of the portfolio system, enabling users to specify which wallet addresses, blockchain networks, and token types they want to explore. These components work together to create an intuitive multi-step selection process that guides users through portfolio setup.

File Structure

    • PortfolioClient.tsx
    • page.module.css
      • SelectAccount.tsx
      • AccountDropdown.tsx
      • SelectChain.tsx
      • SelectChain.module.css
      • SelectToken.tsx
      • SelectToken.module.css

Component Overview

The selection layer consists of four primary components that handle different aspects of portfolio configuration:

Architecture

The selection components follow a unidirectional data flow pattern where each component reports its state changes upward to the parent PortfolioClient component:

This architecture ensures clean separation of concerns and predictable state management across the selection process.

PortfolioClient Component

The PortfolioClient component serves as the main orchestrator for the portfolio interface, managing the state of all selection components and passing the configured data to the ChainWrapper for display.

Component Structure

The PortfolioClient uses a two-part structure to enable testing and proper provider integration:

export default function PortfolioClient() { const [selectedAccount, setSelectedAccount] = useState<string>('') const [selectedChains, setSelectedChains] = useState<number[]>([]) const [selectedTokens, setSelectedTokens] = useState<TokenType[]>([]) return ( <ChainInfoProvider> <Content selectedAccount={selectedAccount} onAccountChange={setSelectedAccount} selectedChains={selectedChains} onChainsChange={setSelectedChains} selectedTokens={selectedTokens} onTokensChange={setSelectedTokens} /> </ChainInfoProvider> ) }

Content Component

The Content component is exported separately to facilitate unit testing of the mapping logic without provider dependencies. It transforms the selected chains and tokens into the ChainData format expected by ChainWrapper:

const chainData: ChainData[] = selectedChains.map((id: number) => ({ chainId: id, chainName: getChainDisplayName(id), tokens: selectedTokens, }))

Layout Organization

The component organizes the selection interface into three distinct sections:

  1. AccountContainer: Houses the account selection component at the top
  2. SelectionContainer: Groups chain and token selection side by side
  3. ChainContainer: Displays the portfolio based on current selections

State Management

The PortfolioClient maintains all selection state at the top level, enabling:

  • Centralized state management for all child components
  • Easy testing of state transformations
  • Clear data flow from selection to display
  • Potential for state persistence in future updates

SelectAccount Component

The SelectAccount component serves as the primary entry point for wallet interaction, managing both connection state and address selection for multi-account wallets.

Core Functionality

The component provides comprehensive wallet management features including wallet connection triggering, multiple address support for wallets with multiple accounts, automatic address synchronization when wallet state changes, and custom modal integration for wallet selection. It also handles graceful disconnection with state cleanup.

Implementation Details

interface SelectAccountProps { onAccountChange?: (address: string) => void }

The component leverages wagmi’s useAccount hook to access wallet state and maintains internal state for the selected address. It automatically synchronizes with wallet connection changes and notifies the parent component of address updates through the onAccountChange callback.

Usage Example

<SelectAccount onAccountChange={(address) => { console.log('Selected address:', address) // Update portfolio view for new address }} />

Visual States

The SelectAccount component displays different visual states based on the wallet connection status and user interaction:

Select Address button showing 'Connect Wallet' text

When no wallet is connected, the component displays “Connect Wallet” as a call-to-action button. This state serves as the initial entry point for users to begin interacting with the portfolio system.

ENS Resolution

The component automatically resolves ENS names for connected addresses through the AccountDropdown subcomponent. ENS resolution occurs on mainnet regardless of the currently connected chain, ensuring consistent name display across all networks. The interface displays shortened addresses while ENS names are being resolved.

ENS names are resolved asynchronously through wagmi’s useEnsName hook. The component displays shortened addresses (0x1234…5678) until resolution completes.

AccountDropdown Component

The AccountDropdown serves as the visual interface for address selection and wallet connection, implementing a custom dropdown design that integrates seamlessly with the portfolio’s aesthetic.

Visual States

The dropdown adapts its appearance based on connection state. When disconnected, it shows “Connect Wallet” as a call-to-action. When connected, it displays the active address or ENS name. The component includes smooth transitions between states and a rotating chevron indicator for open/closed states.

Address Display Logic

The component implements intelligent address display with ENS name priority, showing ENS names when available and falling back to shortened addresses in the format 0x1234…5678. ENS resolution happens asynchronously without explicit loading indicators:

const { data: ensName } = useEnsName({ address: addr, chainId: 1, // mainnet ENS }) // Display logic {ensName ?? shorten(addr)}

Accessibility Features

The dropdown includes comprehensive accessibility support with keyboard navigation using Tab and Enter keys, proper ARIA attributes for screen readers, focus management for dropdown states, and click-outside detection for intuitive closing behavior.

SelectChain Component

The SelectChain component provides a visual interface for selecting multiple blockchain networks simultaneously, leveraging the ChainInfoProvider for logo and name resolution.

A list of chains with empty checkmark fields next to each

Multi-Selection Interface

The component renders a grid of selectable blockchain networks, each displaying the chain logo from ChainInfoProvider, a checkbox indicator for selection state, and the human-friendly chain name. Users can select multiple chains to view assets across different networks.

Integration with Wagmi

const { chains } = useConfig()

The component automatically discovers all configured chains from wagmi’s configuration, ensuring it always reflects the current network support without manual updates.

State Management

The component maintains an internal checked state for each chain and reports changes through the onSelectionChange callback. The state structure uses a Record type for efficient lookups:

const [checkedMap, setCheckedMap] = useState<Record<number, boolean>>({})

Updates are communicated to the parent component immediately through a useEffect that fires on every state change.

Visual Feedback

Each chain item provides immediate visual feedback with checkbox animations on selection, hover states for better interactivity, and error handling for logo loading failures. Chain logos are loaded eagerly with a fallback image on error.

Chain selection operates independently of wallet connection status. Parent components must implement their own logic if they need to disable chain selection when disconnected.

SelectToken Component

The SelectToken component enables filtering portfolio assets by token standard, supporting the three primary ERC token types used on EVM chains.

A list of token types with empty checkmark fields next to each

Token Type Support

The component provides selection for three token standards. ERC-20 covers standard fungible tokens like USDC and DAI. ERC-721 includes non-fungible tokens (NFTs) such as artwork and collectibles. ERC-1155 encompasses multi-tokens that can be either fungible or non-fungible.

Simple Checkbox Interface

export type TokenType = 'ERC-20' | 'ERC-721' | 'ERC-1155' const OPTIONS: TokenType[] = ['ERC-20', 'ERC-721', 'ERC-1155']

The component uses a straightforward checkbox pattern that allows multiple simultaneous selections, maintains state internally, and reports changes immediately to the parent component through a synchronous useEffect.

Usage Patterns

Common selection patterns include viewing only fungible tokens by selecting ERC-20, exploring NFT collections with ERC-721 and ERC-1155, or comprehensive portfolio view with all types selected. The component maintains its own state without external dependencies.

Integration Patterns

The selection components work together to create a cohesive configuration experience. Understanding their integration is crucial for extending or modifying the portfolio system.

State Flow Example

function PortfolioClient() { const [selectedAccount, setSelectedAccount] = useState('') const [selectedChains, setSelectedChains] = useState<number[]>([]) const [selectedTokens, setSelectedTokens] = useState<TokenType[]>([]) // Selection handlers update parent state const handleAccountChange = (address: string) => { setSelectedAccount(address) // Could trigger data refresh here } const handleChainsChange = (chainIds: number[]) => { setSelectedChains(chainIds) // Update portfolio view for new chains } const handleTokensChange = (tokens: TokenType[]) => { setSelectedTokens(tokens) // Filter displayed assets } return ( <> <SelectAccount onAccountChange={handleAccountChange} /> <SelectChain onSelectionChange={handleChainsChange} /> <SelectToken onSelectionChange={handleTokensChange} /> {/* Portfolio display components */} </> ) }

Coordination Requirements

Since the selection components operate independently, parent components must implement coordination logic when needed. For example, if chain selection should be disabled until wallet connection, the parent must track connection state and conditionally render or disable the SelectChain component. The components themselves do not enforce these relationships.

Styling and Theming

All selection components use CSS modules for scoped styling, ensuring no global style conflicts. The components follow consistent design patterns including hover states with subtle color changes, active states with visual feedback, disabled states with reduced opacity, and smooth transitions for all interactions.

Responsive Design

The components adapt to different screen sizes with mobile-optimized touch targets, tablet-friendly grid layouts, and desktop hover interactions. The responsive behavior ensures usability across all devices.

Testing Coverage

The selection components include comprehensive test coverage to ensure reliability.

PortfolioClient Tests

The integration test verifies that all components render within the ChainInfoProvider wrapper and that the expected child components are present. The Content unit test validates the mapping logic that transforms selected chains and tokens into the ChainData format.

SelectAccount Tests

The test suite verifies disconnected state initialization, modal opening on connect click, address synchronization with wallet changes, callback invocation with correct addresses, and proper state management between connected and disconnected states.

AccountDropdown Tests

Tests ensure ENS name display when available, fallback to shortened addresses, distinct display for multiple addresses, proper click handling, and accessibility compliance. The tests validate that ENS resolution works correctly for both selected and listed addresses.

SelectChain Tests

The test coverage includes chain rendering from wagmi config, checkbox state management, callback invocation on selection, logo URL generation through ChainInfoProvider, and multi-selection behavior.

SelectToken Tests

Tests verify option rendering for all token types, toggle functionality, immediate callback updates, state persistence, and proper TypeScript typing.

All component tests use Testing Library for user-centric testing approaches, focusing on behavior rather than implementation details.

Error Handling

The selection components implement basic error handling for common scenarios.

Wallet Connection

The SelectAccount component relies on wagmi’s built-in connection handling. Connection errors are managed by the wagmi provider and the ConnectModal component. The selection components do not implement specific error UI for connection failures, timeouts, or user rejections.

Missing Data Scenarios

Components handle edge cases such as chain logo loading errors with fallback images and empty wallet scenarios by showing the “Connect Wallet” prompt. ENS resolution failures are handled gracefully by displaying shortened addresses.

Best Practices

When working with selection components, follow these guidelines for optimal results.

Development Practices

Always provide callback functions even if not immediately used, as this ensures future extensibility. Test with multiple wallet providers to ensure compatibility. Handle edge cases like empty addresses gracefully. Use TypeScript for type safety across all components.

User Experience Guidelines

Provide immediate visual feedback for all interactions to ensure users understand their actions. Enable keyboard navigation for accessibility. Maintain selection state appropriately based on your application’s needs.

Integration Guidelines

Keep selection logic in parent components to maintain separation of concerns. Use callbacks for all state changes to ensure predictable data flow. Implement any needed validation or coordination logic in parent components. Consider implementing selection persistence in localStorage for returning users if needed.