-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
feat(predict): add skeleton loaders for improved loading UX #22486
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+1,921
−194
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- Create PredictMarketSkeleton component with updated design - Update avatar from rounded square to circle (rounded-full) - Adjust content area height from 158px to 180px - Update spacing and border radius to match Figma specs - Replace old skeleton implementation in MarketListContent - Add unit tests for new skeleton component
- Reduce height from 180px to 150px for better proportions - Update comment to reflect prediction options area instead of chart
- Remove chart skeleton from content skeleton (chart has its own loading) - Create PredictDetailsButtonsSkeleton component for action buttons - Update PredictDetailsContentSkeleton to show outcome cards with proper structure * Avatar (48x48), title/subtitle lines, and value columns * Map through 2 outcome cards for consistent skeleton layout - Move skeleton button logic into renderActionButtons function - Show skeleton buttons only when loading and market data not available - Update all tests to reflect new skeleton structure - Chart data comes from usePredictPriceHistory (independent from market data)
- Create skeleton loader for market details header - Shows skeleton for back arrow, avatar, title, and subtitle - Used when title is not available from route params - Includes functional back button during loading state - Add comprehensive unit tests
- Add skeleton for Available Balance value during loading - Add skeleton for Unrealized P&L value during loading - Show header card during loading instead of hiding completely - Hide arrow icon during balance loading - Disable TouchableOpacity when balance is loading - Update visibility logic to show card when any section is loading or has data - Remove early return check for isBalanceLoading condition
- Create PredictPositionSkeleton component matching real position card structure * Left: Avatar (40x40 rounded) * Middle: Title and subtitle lines * Right: Value and P&L lines - Replace centered ActivityIndicator with 4 skeleton items during loading - Show skeletons during initial load and refresh with no cached data - Hide 'New' button during loading - Remove unused ActivityIndicator, IconColor, useTailwind, and isHomepageRedesignV1Enabled imports - Add comprehensive unit tests for skeleton component
- Update PredictDetailsContentSkeleton tests to match new value-1/value-2 testIDs - Add NavigationContainer wrapper to PredictDetailsHeaderSkeleton tests - Replace activity-indicator checks with skeleton loader checks in PredictPositions tests - Update test assertions to expect 4 skeleton position items during loading - Fix eslint errors in feature flag selector (remove unused imports)
- Add SafeAreaProvider to PredictDetailsHeaderSkeleton tests for useSafeAreaInsets - Fix feature flag selector to properly read from state instead of hardcoding true - Selector now returns flag value from remoteFlags or falls back to OVERRIDE_PREDICT_ENABLED_VALUE
- SafeAreaProvider requires initialMetrics prop to properly render children in tests - Set default metrics with zero insets for test environment
- Replace NavigationContainer wrapper with jest.mock for useNavigation - Mock useSafeAreaInsets to return zero insets for tests - Simplify test rendering by using direct render() calls - Follow standard pattern used across Predict component tests
✨ New Components Created: - PredictMarketSkeleton: Market card skeleton for feed loading - PredictPositionSkeleton: Position card skeleton for positions list - PredictDetailsHeaderSkeleton: Market details header with functional back button - PredictDetailsContentSkeleton: Market details content (outcome cards) - PredictDetailsButtonsSkeleton: Market details action buttons 🔄 Components Updated: - MarketListContent: Use PredictMarketSkeleton for loading states - PredictPositions: Replace ActivityIndicator with 4 position skeletons - PredictMarketDetails: Conditionally render header/content/button skeletons - PredictPositionsHeader: Add inline skeletons for balance and P&L values ✅ Test Results: - All 1840 tests passing - Fixed all skeleton-related test failures - Updated snapshots for new components - Properly mocked navigation and safe area contexts 🎨 UX Improvements: - Users now see content-aware loading states instead of spinners - Loading skeletons match actual content structure - Smoother perceived performance during data fetching - Consistent loading experience across all views 📝 Implementation Details: - Early return removed from components - show skeletons during loading - Conditional rendering based on loading state and data availability - Skeletons use proper design system tokens and Tailwind styling - All components follow MetaMask design system guidelines
- Extract isCalculating from usePredictOrderPreview hook - Track value changes using previousValueRef and isCalculating state - Show skeleton only when value changes AND preview is calculating - Clear skeleton and reset tracking when calculation completes or value is 0 - Auto-refresh updates happen silently without skeleton flashing - Depend on both currentValue and isCalculating for proper tracking - Fix eslint unused variable warning in feature flag selector
- Split 'To win $120.00' assertion into separate 'To win' and '$120.00' checks - Update test expectations to match component structure where label and value are separate Text components - All 1840 tests now passing in Predict folder
caieu
approved these changes
Nov 11, 2025
Contributor
caieu
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
|
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Labels
INVALID-PR-TEMPLATE
PR's body doesn't match template
release-7.60.0
Issue or pull request that will be included in release 7.60.0
size-XL
team-mobile-platform
Mobile Platform team
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.



Description
This PR significantly improves the loading experience across the Predict feature by implementing skeleton loaders in place of generic loading indicators. Skeleton loaders provide visual placeholders that mimic the actual content structure, reducing perceived loading time and creating a smoother user experience.
CHANGELOG entry: null
Simulator.Screen.Recording.-.iPhone.16.Pro.-.2025-11-11.at.12.59.33.mov
What Changed
Market List
PredictMarketSkeletoncomponent to show placeholder cards during market list loadingMarket Details Page
PredictDetailsHeaderSkeletonfor header section (back arrow, avatar, title)PredictDetailsContentSkeletonfor outcome options areaPredictDetailsButtonsSkeletonfor action buttons (Buy Yes/No)Home Screen - Positions Tab
PredictPositionsHeaderPredictPositionsHeaderPredictPositionSkeletoncomponent for individual position itemsActivityIndicatorwith 4 skeleton position cards inPredictPositionsBuy/Trade Preview Screen
previousValueRefto track actual value changesWhy These Changes
Technical Approach
Design Alignment
All skeleton implementations were created based on Figma SVG designs provided by the design team, ensuring pixel-perfect alignment with design specifications.
Changelog
Added
Changed
Related Issues
Refs: [Add issue number if applicable]
Manual Testing Steps
Market List Skeleton
Market Details Skeleton
Home Screen Positions Skeleton
Buy Preview Skeleton
Screenshots/Recordings
Pre-merge Checklist
yarn jest app/components/UI/Predict)Components Created
New Files
app/components/UI/Predict/components/PredictMarketSkeleton/PredictMarketSkeleton.tsx- Skeleton for market list cardsPredictMarketSkeleton.test.tsx- Unit testsindex.ts- Barrel exportapp/components/UI/Predict/components/PredictDetailsHeaderSkeleton/PredictDetailsHeaderSkeleton.tsx- Skeleton for details page headerPredictDetailsHeaderSkeleton.test.tsx- Unit testsindex.ts- Barrel exportapp/components/UI/Predict/components/PredictDetailsContentSkeleton/PredictDetailsContentSkeleton.tsx- Skeleton for details page contentPredictDetailsContentSkeleton.test.tsx- Unit testsindex.ts- Barrel exportapp/components/UI/Predict/components/PredictDetailsButtonsSkeleton/PredictDetailsButtonsSkeleton.tsx- Skeleton for action buttonsPredictDetailsButtonsSkeleton.test.tsx- Unit testsindex.ts- Barrel exportapp/components/UI/Predict/components/PredictPositionSkeleton/PredictPositionSkeleton.tsx- Skeleton for position list itemsPredictPositionSkeleton.test.tsx- Unit testsindex.ts- Barrel exportModified Files
app/components/UI/Predict/components/MarketListContent/MarketListContent.tsxPredictMarketSkeletonfor loading statesapp/components/UI/Predict/views/PredictMarketDetails/PredictMarketDetails.tsxapp/components/UI/Predict/views/PredictMarketDetails/PredictMarketDetails.test.tsxapp/components/UI/Predict/components/PredictPositionsHeader/PredictPositionsHeader.tsxapp/components/UI/Predict/components/PredictPositionsHeader/PredictPositionsHeader.test.tsxapp/components/UI/Predict/components/PredictPositions/PredictPositions.tsxapp/components/UI/Predict/components/PredictPositions/PredictPositions.test.tsxapp/components/UI/Predict/views/PredictBuyPreview/PredictBuyPreview.tsxapp/components/UI/Predict/hooks/usePredictOrderPreview.tsisCalculatingstate for skeleton logicTechnical Notes
Design System Compliance
Boxcomponent from@metamask/design-system-react-nativeuseTailwind()hook andtwClassNamepropbg-muted,bg-section, etc.)Testing Strategy
Performance Considerations
Review Focus Areas
Note
Adds dedicated skeleton loaders for market lists, market details, positions, and buy preview, replacing spinners and refining loading logic.
MarketListContent.tsx): Replace generic loading/footer placeholders withPredictMarketSkeletoncards for initial load and pagination.PredictMarketDetails.tsx): AddPredictDetailsHeaderSkeleton,PredictDetailsContentSkeleton, andPredictDetailsButtonsSkeleton; render skeletons during initial fetch; keep chart loading independent; refine header rendering when route params missing.PredictPositionsHeader.tsx): Inline skeletons for Available Balance and Unrealized P&L; always render card while loading; disable arrow while loading.PredictPositions.tsx): ReplaceActivityIndicatorwith 4PredictPositionSkeletonrows during initial/refresh loads; gatePredictNewButtonwhen loading.PredictBuyPreview.tsx): Show smart skeleton for "To win" value only while recalculating due to user input; keep balance skeleton.PredictMarketSkeleton,PredictDetailsHeaderSkeleton,PredictDetailsContentSkeleton,PredictDetailsButtonsSkeleton,PredictPositionSkeleton(+ index files).selectPredictEnabledFlagproperty check; update tests and snapshots to assert skeletons.Written by Cursor Bugbot for commit 118502a. This will update automatically on new commits. Configure here.