feat: add TabsIcon component family with icon tabs, scroll overflow detection, and collapse animation#29684
Conversation
Adds Tab, TabsBar, and TabsList to components-temp with animated underline, scrollable overflow detection, icon support, and height collapse animation. Adds Candlestick, Portfolio, and Predict icons.
|
CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes. |
…nges to Tab family
… fix style override and sparse array reset
5c05f84 to
3fecb5b
Compare
3fecb5b to
7d69b3d
Compare
🔍 Smart E2E Test Selection
click to see 🤖 AI reasoning detailsE2E Test Selection:
Since none of the changed code is integrated into any production user flows, no E2E tests are needed. The changes cannot break any existing test flows because:
No performance tests are needed either — the changes are additive SVG assets and isolated component library code with no impact on rendering pipelines, data loading, or critical user flows. Performance Test Selection: |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit ffa57ba. Configure here.
| if (activeIndex >= 0 && layoutsReady) { | ||
| animateToTab(activeIndex); | ||
| } | ||
| }, [activeIndex, layoutsReady, animateToTab]); |
There was a problem hiding this comment.
Double animation fires on initialization due to dependency cycle
Medium Severity
The animateToTab callback includes isInitialized in its useCallback dependency array, and animateToTab itself is a dependency of the effect at line 156. When animateToTab is first called during initialization, it calls setIsInitialized(true) (line 136), which triggers a re-render, recreating animateToTab with a new closure. This new reference causes the effect to re-fire, calling animateToTab(activeIndex) a second time — now with isFirstTime = false, starting an unnecessary Animated.timing animation to the same position that was just set via setValue. In TabsIconBar, this also redundantly calls setUnderlineWidth and invokes the native animation bridge for a zero-delta animation.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit ffa57ba. Configure here.
|




Description
Adds new
TabsIconcomponents tocomponents-tempand new icons to the component library as part of the hub page discovery tabs A/B test. Extracted into its own PR so it can be reviewed and merged independently before the feature PR lands.TabsIconComponent FamilyTabsIconTabTab item that renders an icon above a label. Icon and label have active/disabled color states. Supports a
fillWidthprop for equal-width layouts and animated icon collapse viaTabsIconAnimationContext.TabsIconBarTab bar built for icon+label tabs. Features:
ScrollViewfillWidthmode for equal-width tabsTabsIconListLazy-mounting tab list that manages active state, swipe gestures, and
InteractionManager-based content loading. Per-tabkeepMountedprop controls whether inactive tab content stays mounted or is unmounted when the tab loses focus.TabsIconAnimationContextReact context that carries an
Animated.Value(0= icons expanded,1= collapsed) from a parent provider down toTabsIconTabwithout prop drilling.Icons
Adds three new SVG icons and registers them in
Icon.assets.ts/Icon.types.ts:IconNameIconName.PortfolioIconName.PredictIconName.CandlestickChangelog
CHANGELOG entry: null
Related issues
Fixes: https://consensyssoftware.atlassian.net/browse/TMCU-591
Manual testing steps
Screenshots/Recordings
Take from the feature branch using these components here
iOS
Dark Mode
dark_mode_ios.mov
Light Mode (No Gradient)
light_mode_ios.mov
Android
Dark Mode
dark_mode_android.mov
Light Mode (No Gradient)
light_mode_android.mov
Before
~After
~Pre-merge author checklist
Performance checks (if applicable)
trace()for usage andaddTokenfor an exampleFor performance guidelines and tooling, see the Performance Guide.
Pre-merge reviewer checklist
Note
Medium Risk
Adds new tab UI components plus shared layout/list hooks involving animations, gesture handling, and InteractionManager-based lazy loading; regressions would primarily impact navigation/UX in screens adopting these new components. Also extends the global
IconNameenum/assets, which can affect consumers if mis-registered.Overview
Adds a new
TabsIconcomponent family undercomponents-temp:TabsIconTabrenders icon+label tabs with active/disabled states and optional icon collapse viaTabIconAnimationContext,TabsIconBarmanages underline animation plus auto scroll overflow detection and optional height collapse, andTabsIconListcomposes the bar with lazy-mounted tab content, disabled-tab handling, swipe gestures, and a small imperative ref API.Introduces reusable hooks
useTabsBarLayout(measures tab/container layouts, toggles scroll mode, drives underline animations, and resets/cleans up on layout/tab changes) anduseTabsList(active index normalization, InteractionManager-backed lazy loading with timeout fallback, key-preserving tab updates, and swipe-to-switch).Extends the icon library by registering new SVGs and
IconNameentries (Group,Portfolio,Predictions) and updates thecandlestick.svgasset. Comprehensive unit tests are added for the new components and hooks.Reviewed by Cursor Bugbot for commit ffa57ba. Bugbot is set up for automated code reviews on this repo. Configure here.