Skip to Content
Welcome to RitoSwap's documentation!

TokenStatus

The TokenStatus component provides dynamic status messaging that communicates the current NFT ownership state to users through elegantly animated text transitions. This seemingly simple component plays a crucial role in maintaining user orientation by clearly articulating their current state in the NFT lifecycle. Through careful state management and transition timing, it ensures status updates feel smooth and polished rather than jarring or abrupt.

Component Architecture

TokenStatus implements a sophisticated transition system that goes beyond simple text swapping. The component maintains internal state to manage the timing and animation of text changes, ensuring that updates happen smoothly even when the underlying data changes rapidly. This approach prevents the flickering and jumpiness that often plague reactive interfaces dealing with asynchronous blockchain data.

State Display Logic

The component displays one of five possible states based on wallet connection and NFT ownership:

StateConditionsDisplay Text
LoadingInitial render, data fetching”Loading…”
Not Connected!isConnected”You are not signed in”
No NFTisConnected && !hasNFT”You don’t have a key yet”
Unused NFTisConnected && hasNFT && !hasUsedTokenGate”You have an unused key!”
Used NFTisConnected && hasNFT && hasUsedTokenGate”You have a used key…”

The punctuation choices are deliberate, with exclamation points indicating positive states and ellipses suggesting completion or waiting states.

Interactive Demo

Loading...

Props and Interface

TokenStatus is a zero-configuration component that derives all its data from hooks and stores:

export default function TokenStatus() { // No props - all data from hooks const { isConnected } = useAccount() const { hasNFT, hasUsedTokenGate, isLoading } = useNFTStore() }

This design ensures consistency across the application and prevents prop drilling.

Transition Management

The component’s defining feature is its smooth transition system that prevents jarring text changes:

Transition State Machine

const [displayText, setDisplayText] = useState("Loading...") const [isTransitioning, setIsTransitioning] = useState(false) const [hasInitialLoad, setHasInitialLoad] = useState(false) const previousTextRef = useRef<string>("Loading...")

These state variables work together to orchestrate smooth transitions:

  • displayText - The currently displayed text
  • isTransitioning - Whether a transition is in progress
  • hasInitialLoad - Prevents transitions during initial data load
  • previousTextRef - Tracks the last displayed text to prevent unnecessary transitions

Transition Timing

The transition effect implements a two-phase animation:

Phase 1: Fade Out (500ms)

The current text fades out and moves slightly upward, creating a gentle exit animation.

Phase 2: Pause and Update (50ms)

After fade out completes, there’s a 50ms pause before the new text is set.

Phase 3: Fade In (500ms)

The new text fades in from a slightly elevated position over another 500ms CSS transition.

This ~1 second total transition time (500ms + 50ms + 500ms) strikes a balance between feeling responsive and avoiding abrupt changes.

Initial Load Handling

TokenStatus implements special logic to handle the initial data loading phase gracefully:

// Wait for initial data load to complete if (isLoading && !hasInitialLoad) { return // Stay on "Loading..." until data is ready } // Mark initial load complete if (!isLoading && !hasInitialLoad) { setHasInitialLoad(true) const initialText = getText() setDisplayText(initialText) previousTextRef.current = initialText return }

This approach ensures users see “Loading…” until real data is available, then transitions directly to the appropriate state without intermediate flickers.

CSS Animation Integration

The component uses CSS classes to implement smooth transitions:

.text { opacity: 1; transform: translateY(0); transition: opacity 0.5s ease-in-out, transform 0.5s ease-in-out; animation: initialFadeIn 1s ease-in-out; } .text.transitioning { opacity: 0; transform: translateY(-5px); } @keyframes initialFadeIn { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } }

The combination of opacity and subtle vertical movement creates a sophisticated transition effect that feels polished and professional. Additionally, there’s a 1-second initial fade-in animation that runs when the component first mounts.

Store Integration

TokenStatus subscribes to specific fields from the NFT store:

Store FieldPurposeUpdate Trigger
hasNFTDetermines NFT ownership stateMint, burn, or transfer events
hasUsedTokenGateTracks token gate usageToken gate interaction
isLoadingPrevents transitions during data fetchBlockchain query state

Performance Optimizations

The component implements several strategies to ensure optimal performance:

Ref-Based Comparison - Using previousTextRef prevents unnecessary transitions when the text hasn’t actually changed, crucial during rapid re-renders.

Early Returns - The effect exits early during initial load or when text hasn’t changed, minimizing computational overhead.

CSS-Based Animation - All visual transitions use GPU-accelerated CSS properties rather than JavaScript-based animations.

Responsive Design

TokenStatus includes responsive styling for mobile devices:

@media (max-width: 768px) { .text { font-size: 2rem; /* Down from 2.5rem */ } .container { min-height: 3rem; /* Down from 3.5rem */ margin-bottom: 0rem; /* Remove bottom margin on mobile */ } }

The reserved container height prevents layout shift as text changes, maintaining visual stability across all screen sizes.

Hook Dependencies

The component relies on two primary data sources:

wagmi Hooks

  • useAccount - Provides wallet connection status

Store Hooks

  • useNFTStore - Provides NFT ownership and usage data

The effect dependency array carefully includes all relevant variables to ensure updates trigger appropriately while avoiding infinite loops:

useEffect(() => { // ... transition logic }, [isConnected, hasNFT, hasUsedTokenGate, isLoading, hasInitialLoad])

Common Integration Patterns

TokenStatus is typically used as the first element in the minting interface:

function MintPage() { return ( <div> <TokenStatus /> {/* Status at top */} <NFTScreen /> {/* Visual below */} <ButtonSection /> {/* Actions at bottom */} </div> ) }

This arrangement creates a natural reading flow from status to visualization to actions.

Customization Options

While TokenStatus works out of the box, several aspects can be customized:

Text Customization

The status messages can be modified by changing the getText() function:

const getText = () => { if (!isConnected) return "Connect your wallet" if (hasNFT && hasUsedTokenGate) return "Key already redeemed" // ... etc }

Animation Timing

Transition durations can be adjusted in both the JavaScript and CSS:

setTimeout(() => setDisplayText(newText), 500) // Adjust fade out time

Styling

The component uses CSS modules, making style customization straightforward through the TokenStatus.module.css file.

Error States

While TokenStatus doesn’t explicitly handle error states, it gracefully degrades:

  • If store data is unavailable, it shows appropriate fallback text
  • Network errors don’t crash the component due to optional chaining
  • The loading state prevents display of incorrect information during data fetches

Testing Strategies

Testing TokenStatus requires mocking both wagmi and store hooks:

// Mock wagmi vi.mock('wagmi', () => ({ useAccount: vi.fn(() => ({ isConnected: true })) })) // Mock store vi.mock('@/app/store/nftStore', () => ({ useNFTStore: vi.fn(() => ({ hasNFT: false, hasUsedTokenGate: false, isLoading: false })) }))

Key test scenarios include verifying correct text for each state combination and ensuring transitions occur smoothly without flicker.

Accessibility Considerations

TokenStatus implements several accessibility best practices:

Semantic HTML - Uses an h1 element to properly structure the page hierarchy.

High Contrast - White text on dark backgrounds ensures readability.

Animation Respect - Transitions use CSS for smooth visual changes.

The component’s animations are subtle enough to avoid triggering motion sensitivity while still providing visual polish.

Common Issues and Solutions

IssueCauseSolution
Text flickers on loadMissing initial load checkEnsure hasInitialLoad logic is implemented
Transitions feel slowLong animation durationReduce transition time in CSS and setTimeout
Text doesn’t updateMissing dependenciesCheck effect dependency array completeness

Best Practices

When working with TokenStatus or similar status components:

Maintain State Hierarchy - Always check connection status before NFT status to ensure logical message flow.

Preserve Visual Stability - Use fixed container heights to prevent layout shift during transitions.

Coordinate Timing - Ensure transition timing matches other animated components for cohesive feel.

Test State Combinations - Verify all possible state combinations display appropriate messages.

Summary

TokenStatus demonstrates how careful attention to transition timing and state management can elevate a simple text display into a polished UI element. By implementing sophisticated transition logic, handling initial load states gracefully, and maintaining visual stability through reserved space, it provides clear user feedback without the jarring updates common in blockchain applications. The component’s zero-configuration design and store integration make it a drop-in solution that enhances the user experience through thoughtful animation and clear communication of system state.