Skip to content

Commit a065a3b

Browse files
feat: Update In-App Browser UX (#24444)
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> Jira Ticket: https://consensyssoftware.atlassian.net/browse/MCWP-216 # Description ## What Changed This PR improves the browser experience by implementing three major UI updates: ### 1. Hide App Navigation Tab Bar in Browser - Removed the app navigation tab bar when viewing browser content - Previously only hidden in fullscreen mode; now always hidden when browser is active - Provides a cleaner, more immersive browsing experience ### 2. Refactor Browser Bottom Bar - **Removed**: Kebab menu (more options), tabs button, fullscreen toggle, home button, search button - **Added**: Reload button, bookmark/favorite toggle button, new tab button - **Kept**: Back and forward navigation buttons (migrated to design system) - **Migrated** bookmark functionality from Options modal to bottom bar for quicker access - **Updated** to use `@metamask/design-system-react-native` components (ButtonIcon, Box, Tailwind) ### 3. Update Browser URL Bar - **Replaced** conditional back arrow with always-visible close "X" button - **Added** tabs button with count badge to URL bar area (between URL bar and account button) - **Removed** feature flag dependency - close button now always visible - **Fixed** navigation logic to handle both trending enabled/disabled states - Tabs button provides quick access to tab management ## Why These Changes **User Experience**: - Faster access to common actions (reload, bookmark, new tab) without opening menus - Always-accessible close and tabs buttons in URL bar - Less visual clutter in browser view - More intuitive bookmark management with visible star icon toggle - Matches Figma design specifications **Technical Improvements**: - Migrated from legacy icon libraries to design system components - Replaced StyleSheet with Tailwind CSS classes per UI guidelines - Reduced component complexity by removing Options modal dependency ## Trade-offs - **Options menu removed**: All essential functionality preserved in bottom bar or removed as non-essential - **Home button removed**: Users navigate via close button instead - **Fullscreen removed** ## Implementation Details ### Files Modified **Navigation**: - `app/components/Nav/Main/MainNavigator.js` - Updated `renderTabBar` to hide tab bar when in browser **Browser Components**: - `app/components/UI/BrowserBottomBar/index.tsx` - Complete refactor with design system components - `app/components/UI/BrowserUrlBar/BrowserUrlBar.tsx` - Added tabs button functionality - `app/components/UI/BrowserUrlBar/BrowserUrlBar.types.ts` - Added `showTabs` prop - `app/components/UI/BrowserUrlBar/BrowserUrlBar.styles.ts` - Added tabs button styles - `app/components/Views/BrowserTab/BrowserTab.tsx` - Removed Options component, updated close button, added tabs functionality - `app/components/Views/DiscoveryTab/DiscoveryTab.tsx` - Fixed to pass showTabs prop to BrowserUrlBar **Test Updates**: - `app/components/UI/BrowserBottomBar/index.test.tsx` - NEW: 21 comprehensive unit tests - `app/components/UI/BrowserUrlBar/BrowserUrlBar.test.tsx` - Added 4 tests for tabs button functionality - `app/components/Views/DiscoveryTab/DiscoveryTab.test.tsx` - NEW: 7 comprehensive unit tests - `app/components/Nav/Main/MainNavigator.test.tsx` - Added tab bar visibility tests - `e2e/selectors/Browser/BrowserView.selectors.ts` - Updated test selectors - `e2e/pages/Browser/BrowserView.ts` - Updated page object methods for new buttons ### Key Technical Changes **Bookmark Functionality Migration**: - Moved `isBookmark()` logic from Options to BrowserBottomBar - Moved `navigateToAddBookmark()` from Options to BrowserBottomBar - Integrated bookmark add/remove with star icon toggle (StarFilled ↔ Star) - Preserved iOS Spotlight integration - Maintained analytics tracking (`BROWSER_ADD_FAVORITES`, `DAPP_ADD_TO_FAVORITE`) **Close Button Enhancement**: - Changed from `IconName.ArrowLeft` to `IconName.Close` - Removed feature flag dependency (`isAssetsTrendingTokensEnabled`) - Added fallback navigation when trending is disabled (navigates to wallet home) - Renamed `handleBackPress` to `handleClosePress` **Tabs Button Addition**: - Re-added tabs button to URL bar area (previously removed from bottom bar) - Uses existing `TabCountIcon` component connected to Redux - Shows dynamic tab count - Positioned between URL bar and account button - Consistent height styling with account button **Design System Compliance**: - Migrated from `View` → `Box` component - Migrated from `StyleSheet.create()` → Tailwind classes with `twClassName` - Added `useTailwind()` hook for dynamic styles - Using `ButtonIcon` with `IconName` enum for all buttons - Fixed disabled state: `disabled` → `isDisabled` prop - Design system props: `BoxFlexDirection`, `BoxAlignItems`, `BoxJustifyContent` **Analytics Preserved**: - `BROWSER_NAVIGATION` - Back/Forward button presses - `BROWSER_RELOAD` - Reload button press - `BROWSER_NEW_TAB` - New tab button press - `BROWSER_ADD_FAVORITES` - Adding bookmark - `DAPP_ADD_TO_FAVORITE` - Adding bookmark (secondary event) - `BROWSER_OPENED` - Browser/tabs opening # Changelog CHANGELOG entry: Improved browser experience by hiding the app navigation bar when browsing and redesigned the browser controls with quick-access buttons for reloading pages, managing bookmarks, and opening new tabs, plus added close and tabs buttons to the URL bar # Related Issues Refs: [Issue number if applicable] # Manual Testing Steps ## Prerequisites - Device with MetaMask Mobile installed - Access to browser functionality - Test with both `isAssetsTrendingTokensEnabled` ON and OFF ### Scenario 1: App Tab Bar Hidden in Browser ### Scenario 2: Browser Navigation Controls Given I am viewing a website in the browser When I press the back button Then I should navigate to the previous page And the back button should be disabled when no history exists And the back button should show 50% opacity when disabled When I press the forward button Then I should navigate to the next page And the forward button should be disabled when no forward history exists When I press the reload button Then the current page should reload ### Scenario 3: Bokmark Functionality Given I am viewing a non-bookmarked website When I look at the bookmark button Then I should see an outline star icon When I press the bookmark button Then the AddBookmarkView modal should open And I should be able to edit the bookmark name When I save the bookmark Then the star icon should change to filled And the bookmark should appear in my favorites list When I press the filled star button Then the bookmark should be removed immediately And the star icon should change to outline ### Scenario 4: New Tab Creation Given I am viewing any website When I press the new tab button (+ icon) Then a new browser tab should open And I should be navigated to the new tab ### Scenario 5: Close Button Given I am viewing a website in the browser When I press the close "X" button in the URL bar Then I should navigate out of the browser Scenario 5a: When trending is enabled Then I should navigate to the trending view Scenario 5b: When trending is disabled Then I should navigate to the wallet home ### Scenario 6: Tabs Button Given I am viewing a website in the browser When I look at the URL bar Then I should see the tabs button with the current tab count (e.g., "4") When I press the tabs button Then the tabs view should open And I should see all my open tabs When I have 0 tabs open Then the tabs button should show "0" ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> <img width="301" height="620" alt="Screenshot 2026-01-12 at 16 31 08" src="https://github.com/user-attachments/assets/673b42a5-86ed-42f2-81fa-8f22c48b869a" /> ### **After** <img width="360" height="734" alt="Screenshot 2026-01-13 at 00 52 19" src="https://github.com/user-attachments/assets/64b03e8f-585d-4c5e-8922-9691a4745f4e" /> <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I’ve followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Modernizes the in-app browser UI and behavior. > > - Always hide app navigation tab bar when in `Routes.BROWSER.HOME`; removed fullscreen dependency in `MainNavigator` > - Replace `BrowserBottomBar` with design-system `Box`/`ButtonIcon` controls: keep back/forward, add `reload`, `bookmark` toggle (add/remove with `AddBookmarkView`), and `new tab`; remove home/options/fullscreen/search > - Migrate bookmark logic into `BrowserBottomBar`, including iOS Spotlight indexing via `@metamask/react-native-search-api` and Redux actions (`addBookmark`/`removeBookmark`); add `BROWSER_NAVIGATION`, `BROWSER_RELOAD`, `BROWSER_NEW_TAB`, `BROWSER_ADD_FAVORITES`, `DAPP_ADD_TO_FAVORITE` analytics > - Add tabs button to `BrowserUrlBar` (`showTabs` prop, new styles); shows count via `TabCountIcon` > - Improve `Tabs` footer spacing (safe-area aware) and snapshots > - Add/expand tests: `MainNavigator` tab bar visibility, comprehensive `BrowserBottomBar` unit tests, `BrowserUrlBar` tabs button tests, `Tabs` rendering tests, and new `Browser.components.test.tsx` coverage > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 57a05c4. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: sethkfman <10342624+sethkfman@users.noreply.github.com>
1 parent 224f104 commit a065a3b

41 files changed

Lines changed: 7406 additions & 3685 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

app/components/Nav/Main/MainNavigator.js

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ import { MetaMetricsEvents } from '../../../core/Analytics';
7474
import { TabBarIconKey } from '../../../component-library/components/Navigation/TabBar/TabBar.types';
7575
import { selectProviderConfig } from '../../../selectors/networkController';
7676
import { selectAccountsLength } from '../../../selectors/accountTrackerController';
77-
import { selectBrowserFullscreen } from '../../../selectors/browser';
7877
import SDKSessionsManager from '../../Views/SDK/SDKSessionsManager/SDKSessionsManager';
7978
import PermissionsManager from '../../Views/Settings/PermissionsSettings/PermissionsManager';
8079
import { getDecimalChainId } from '../../../util/networks';
@@ -570,8 +569,6 @@ const HomeTabs = () => {
570569
(state) => state.browser.tabs.length,
571570
);
572571

573-
const isBrowserFullscreen = useSelector(selectBrowserFullscreen);
574-
575572
const options = {
576573
home: {
577574
tabBarIconKey: TabBarIconKey.Wallet,
@@ -682,13 +679,13 @@ const HomeTabs = () => {
682679
return null;
683680
}
684681

685-
// Hide tab bar when browser is in fullscreen mode
682+
// Hide tab bar when in browser
686683
const currentStackRouteName =
687684
currentRoute?.state?.routes?.[currentRoute?.state?.index]?.name;
688685
const isInBrowser =
689686
currentRoute.name?.startsWith(Routes.BROWSER.HOME) ||
690687
currentStackRouteName?.startsWith(Routes.BROWSER.HOME);
691-
if (isBrowserFullscreen && isInBrowser) {
688+
if (isInBrowser) {
692689
return null;
693690
}
694691

app/components/Nav/Main/MainNavigator.test.tsx

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,48 @@ describe('MainNavigator', () => {
3434
expect(toJSON()).toMatchSnapshot();
3535
});
3636

37+
describe('Tab Bar Visibility', () => {
38+
it('hides tab bar when browser is active', () => {
39+
// Given a state where browser is the active route
40+
const stateWithBrowserActive = {
41+
...initialRootState,
42+
browser: {
43+
...initialRootState.browser,
44+
activeTab: 0,
45+
tabs: [{ url: 'https://example.com', id: 0 }],
46+
},
47+
};
48+
49+
// When rendering the MainNavigator
50+
const { toJSON } = renderWithProvider(<MainNavigator />, {
51+
state: stateWithBrowserActive,
52+
});
53+
54+
// Then the tab bar should be hidden (returns null in renderTabBar)
55+
expect(toJSON()).toMatchSnapshot();
56+
});
57+
58+
it('shows tab bar when not in browser', () => {
59+
// Given a state where wallet is the active route
60+
const stateWithWalletActive = {
61+
...initialRootState,
62+
browser: {
63+
...initialRootState.browser,
64+
activeTab: null,
65+
tabs: [],
66+
},
67+
};
68+
69+
// When rendering the MainNavigator
70+
const { toJSON } = renderWithProvider(<MainNavigator />, {
71+
state: stateWithWalletActive,
72+
});
73+
74+
// Then the tab bar should be visible
75+
expect(toJSON()).toMatchSnapshot();
76+
});
77+
});
78+
3779
it('includes SampleFeature screen in the navigation stack', () => {
3880
// Given the initial app state
3981
// When rendering the MainNavigator

0 commit comments

Comments
 (0)