feat(ui): Implement Phosphor icons for Brand update - #35526
Conversation
Swap component-library SVG icons to Phosphor Regular paths (scaled into the 24x24 viewBox with currentColor) so the design system matches the Phosphor icon set. Co-authored-by: Cursor <cursoragent@cursor.com>
|
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. |
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #35526 +/- ##
========================================
Coverage 85.67% 85.68%
========================================
Files 6732 6746 +14
Lines 186225 186352 +127
Branches 46167 46191 +24
========================================
+ Hits 159557 159680 +123
- Misses 16221 16222 +1
- Partials 10447 10450 +3 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
georgewrmarshall
left a comment
There was a problem hiding this comment.
As a precursor to this PR, maybe we could check whether any of these icons are no longer in use. We could then create a separate PR to remove all unused legacy icons, which should reduce the size of this PR and provide some bundle size benefits.
Align the Received glyph with Phosphor's arrow-down-left so receive actions match the intended iconography. Co-authored-by: Cursor <cursoragent@cursor.com>
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 a78893d. Configure here.
|
@georgewrmarshall Removed mobile icons here: #35571. Will rebase this branch once #35571 is merged. |
## **Description** <!-- mms-check: type=text required=true --> <!-- 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? --> Removes component-library `Icon` assets that are not rendered through the local `Icon` / `IconName` path in production. Many of these names are still used in the app via `@metamask/design-system-react-native` (MMDS), which ships its own assets — so deleting the CL copies does not change those screens. **Removed (18):** Ai, Book, Candlestick, Customize, Ethereum, Expand, Flash, Menu, Minus, PieChart, Predictions, Receive, RemoveMinus, ScanBarcode, Star, UserCircleAdd, Wifi, X **Kept:** `BuySell` (and all CL icons that still render via component-library in production) Also updates Storybook / README examples that referenced removed CL icons (`Received` / `Info` / `UserCheck`). ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: null ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: Refs: MetaMask#35526 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> N/A — removes unused component-library icon assets and updates story/docs references only. Production screens that use these icon names via MMDS are unaffected. ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** N/A ### **After** N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [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. #### Performance checks (if applicable) - [x] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [x] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [x] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] 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. --------- Co-authored-by: Cursor <cursoragent@cursor.com>
…brary Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # app/component-library/components/Icons/Icon/assets/ai.svg # app/component-library/components/Icons/Icon/assets/book.svg # app/component-library/components/Icons/Icon/assets/candlestick.svg # app/component-library/components/Icons/Icon/assets/customize.svg # app/component-library/components/Icons/Icon/assets/ethereum.svg # app/component-library/components/Icons/Icon/assets/expand.svg # app/component-library/components/Icons/Icon/assets/flash.svg # app/component-library/components/Icons/Icon/assets/menu.svg # app/component-library/components/Icons/Icon/assets/minus.svg # app/component-library/components/Icons/Icon/assets/pie-chart.svg # app/component-library/components/Icons/Icon/assets/predictions.svg # app/component-library/components/Icons/Icon/assets/receive.svg # app/component-library/components/Icons/Icon/assets/remove-minus.svg # app/component-library/components/Icons/Icon/assets/scan-barcode.svg # app/component-library/components/Icons/Icon/assets/star.svg # app/component-library/components/Icons/Icon/assets/user-circle-add.svg # app/component-library/components/Icons/Icon/assets/wifi.svg # app/component-library/components/Icons/Icon/assets/x.svg
security-search and snaps-mobile were hand-built as stroke outlines (fill="none", stroke="currentColor"), but component-library Icon always spreads fill="currentColor" onto the root Svg and SVGO hoists per-element fill back onto the parent group, so the shapes can only avoid being filled by inheriting fill="none" through react-native-svg. Their shield and cube paths are open, so a filled render collapses them into blobs. Phosphor Regular has no shield-search or snaps-mobile equivalent, so keep the existing filled glyphs for these two names until design provides Phosphor artwork. Co-authored-by: Cursor <cursoragent@cursor.com>
Both glyphs were hand-built as stroke outlines, which cannot survive this pipeline: Icon spreads fill="currentColor" onto the root Svg and SVGO hoists per-element fill onto the parent group, so the shapes could only stay unfilled by inheriting fill="none" through react-native-svg. Their shield and cube paths are open, so a filled render collapsed them into solid blobs. Redraw both as filled geometry at Phosphor Regular's 16-unit weight, matching the other 100 assets: - security-search: Phosphor shield with a magnifying glass inside, sized and centred like shield-check's inner glyph, with 8-unit clearance from the shield's inner edge. - snaps-mobile: Phosphor square frame with the cube outlined as capsules and round joins, so it keeps its previous shape. Ring holes and the frame interior stay open under the default nonzero fill rule, verified after SVGO optimisation. Co-authored-by: Cursor <cursoragent@cursor.com>
The asset was a stroke outline (fill="none", stroke="currentColor"), which cannot survive this pipeline: generate-icons.ts runs SVGR with svgProps fill="currentColor" and SVGO's addAttributesToSVGElement, so the root svg always gets a fill. The shield and magnifier are open paths, so a filled render collapsed them into a solid blob. Redraw as filled geometry at Phosphor Regular's 16-unit weight, matching the other Phosphor assets: the Phosphor shield used by SecurityTick and Security, with a magnifying glass inside. The ring hole and shield interior stay open under the default nonzero fill rule, verified after SVGO optimisation. Matches MetaMask/metamask-mobile#35526, which redrew the same composite for the mobile component-library copy. Co-authored-by: Cursor <cursoragent@cursor.com>
Keep the filled Apple brand mark instead of the Phosphor outline. Co-authored-by: Cursor <cursoragent@cursor.com>
|
## **Description** ### What is the goal of this PR? - This PR updates all icons used in the Mobile client as part of the wider Brand Migration. - This isolates all changes to Mobile-used icons so the updates can be decoupled from Extension updates. These icons are the set commonly used in the Mobile codebase, so this PR in theory is not a blocker to shipping Extension-only icon changes. - Together with this [Extension update](#1482), all MMDS icons should be updated. ### What are the key improvements? - **Updated style**: All icons are now mapped to corresponding variations in [the Phosphor library](https://phosphoricons.com/) - **Backwards compatibility**: Keeps the existing `viewBox="0 0 24 24"` spec (Phosphor paths scaled via `transform`) and `currentColor` fills so existing color/size APIs continue to work. - **No consumer API change.** Icon names, `viewBox`, and `currentColor` inheritance are unchanged, so Extension and Mobile can pick up the new art without code changes. ### Details 132 icons were updated: - Activity → `pulse` - Add → `plus` - AddCircle → `plus-circle` - AfterHours → `moon` - Ai → `star-four` - Apps → `dots-nine` - Arrow2Down → `arrow-down` - Arrow2Left → `arrow-left` - Arrow2Right → `arrow-right` - Arrow2Up → `arrow-up` - Arrow2UpRight → `arrow-up-right` - ArrowDown → `arrow-down` - ArrowLeft → `arrow-left` - ArrowRight → `arrow-right` - ArrowUp → `arrow-up` - AttachMoney → `currency-dollar` - Backspace → `backspace` - Bank → `bank` - Book → `book` - Bookmark → `bookmark` - Calendar → `calendar` - Camera → `camera` - Campaign → `megaphone` - Candlestick → `candlestick` - created in the Phosphor style, no Phosphor equivalent - Card → `credit-card` - Category → `squares-four` - Chart → `chart-line` - Check → `check` - CheckBold → `check` (bold) - created in the Phosphor style, no Phosphor equivalent - CircleX → `x-circle` - Clock → `clock` - Close → `x` - Code → `code` - Coin → `coin` - Collapse → `arrows-in-simple` - Confirmation → `check-circle` - Connect → `plugs-connected` - Copy → `copy` - CopySuccess → `copy` + check - created in the Phosphor style, no Phosphor equivalent - Customize → `sliders-horizontal` - Danger → `warning` - Data → `database` - Details → `file-text` - Diagram → `tree-structure` - Download → `download` - Edit → `pencil-simple` - Error → `warning-circle` - Ethereum → `currency-eth` - Exchange → `arrows-left-right` - Expand → `arrows-out` - Explore → `compass` - Export → `export` - Extension → `puzzle-piece` - Eye → `eye` - EyeSlash → `eye-slash` - FaceId → `scan` + face - created in the Phosphor style, no Phosphor equivalent - Filter → `funnel` - Fingerprint → `fingerprint` - Fire → `fire` - Flash → `lightning` - FlashFilled → `lightning` (fill) - Gas → `gas-pump` - Gift → `gift` - Global → `globe` - Hardware → `cpu` - Hierarchy → `tree-structure` - Image → `image` - Info → `info` - Loading → `spinner` - Lock → `lock` - LockSlash → `lock-slash` - created in the Phosphor style, no Phosphor equivalent - Logout → `sign-out` - Mail → `envelope` - Menu → `list` - Merge → `git-merge` - Minus → `minus` - MinusBold → `minus` (bold) - created in the Phosphor style, no Phosphor equivalent - Mobile → `device-mobile` - MoneyBag → `money` - MoreHorizontal → `dots-three` - MoreVertical → `dots-three-vertical` - Musd → `musd` - created in the Phosphor style, no Phosphor equivalent - Notification → `bell` - People → `users` - Plant → `plant` - Predictions → `predictions` - created in the Phosphor style, no Phosphor equivalent - QrCode → `qr-code` - Question → `question` - Received → `check-circle` - Refresh → `arrows-clockwise` - RemoveMinus → `minus-circle` - Rocket → `rocket` - Scan → `scan` - ScanBarcode → `barcode` - Search → `magnifying-glass` - Security → `lock-key` - SecurityKey → `lock-key` - SecurityTick → `shield-check` - SecuritySearch - `shield-search` - created in the Phosphor style, no Phosphor equivalent - Send → `paper-plane-tilt` - Setting → `gear` - Share → `share-network` - ShieldLock → `shield-lock` - created in the Phosphor style, no Phosphor equivalent - Sms → `chat-text` - Sparkle → `sparkle` - Speed → `gauge` - Speedometer → `speedometer` - Stake → `stake` - created in the Phosphor style, no Phosphor equivalent - Star → `star` - StarFilled → `star` (fill) - SwapHorizontal → `swap` - SwapVertical → `arrows-down-up` - Tag → `tag` - Telegram → `telegram-logo` - ThumbDown → `thumbs-down` - ThumbDownFilled → `thumbs-down` (fill) - ThumbUp → `thumbs-up` - ThumbUpFilled → `thumbs-up` (fill) - Tint → `drop` - Trash → `trash` - TrendDown → `trend-down` - TrendUp → `trend-up` - Trophy → `trophy` - Usb → `usb` - UserCheck → `user-check` - UserCircle → `user-circle` - UserCircleAdd → `user-circle-plus` - VerifiedFilled → `seal-check` (fill) - Wallet → `wallet` - Warning → `warning` - WifiOff → `wifi-slash` - X → `x` ## **Related issues** Related: MetaMask/metamask-mobile#35526 Related: #1481 Related: #1482 JIRA: https://consensyssoftware.atlassian.net/browse/DSYS-1084 ## **Manual testing steps** 1. Spot-check updated icons in React Storybook (`yarn storybook`) at multiple sizes and colors 2. Spot-check the same icons in React Native Storybook (`yarn storybook:ios` / `yarn storybook:android`) 3. Confirm icons still inherit `currentColor` / theme color correctly 4. Confirm no layout regressions (especially in ButtonIcon / IconAlert / dense UI) 5. Diff a few icons against Phosphor source to confirm the correct weight/variant was used 6. Pay extra attention to remapped glyphs (Coin, Collapse, Security, Stake, Exchange, Diagram, Download, Merge, ShieldLock, Musd) Test this build: Field | Value -- | -- Source branch | preview/phosphor-icons Build name | main-rc Build commit SHA | 3392c214153905cec5dfd180f197f0a091470047 Build version | 8.11.0 Build number | 6777 TestFlight group | MetaMask BETA & Release Candidates Workflow branch ref | main ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** ### **After** https://github.com/user-attachments/assets/09281a9c-1223-4f98-a631-59170e381060 https://github.com/user-attachments/assets/eaaf4c13-6502-4d7d-bd0b-a0b7638e1b98 ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] 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] > **Low Risk** > Asset-only updates with preserved viewBox and currentColor; risk is mainly visual regression or mis-mapped glyphs, not runtime or security impact. > > **Overview** > Replaces the **Mobile-focused icon set** in `design-system-react-native` and matching **React icon components** with Phosphor-based artwork for brand migration, without changing icon names or the `Icon` API. > > Each SVG now uses **`viewBox="0 0 24 24"`**, **`fill="currentColor"`**, and Phosphor paths wrapped in **`transform="scale(0.09375)"`** so existing size and color props keep working. Legacy custom path data is swapped for Phosphor equivalents (or custom Phosphor-style glyphs where no library icon exists, e.g. candlestick, musd, stake). > > Reviewers should **spot-check visual parity** in Storybook and dense UI (buttons, alerts)—glyph weight and silhouette change even though wiring is unchanged. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 48f6596. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
georgewrmarshall
left a comment
There was a problem hiding this comment.
LGTM! Left some non-blocking comments regarding alignment on MUSD icon and some of the more severe changes
There was a problem hiding this comment.
non-blocking: May need to check this one there could be a regression here depending on how it's used
There was a problem hiding this comment.
non-blocking: is this a standard iOS icon? If so we may want to keep it as is.
There was a problem hiding this comment.
non-blocking: Hmm this seems like the incorrect icon originally by the name it should have a slash through the lock 🤔 regardless swap looks good
There was a problem hiding this comment.
non-blocking: just calling out the differences between icons is quite severe and doesn't align with the name of the icon
There was a problem hiding this comment.
non-blocking: See comment above regarding MUSD alignment





Description
What is the goal of this PR?
Iconassets used in the Mobile app as part of the wider Brand Migration.app/component-librarySVGs so it can be decoupled from the MMDS package bump. Screens that importIconfrom@metamask/design-system-react-nativeare unaffected until MMDS is published.This is an asset-only change: icon names,
Icon.types.ts,Icon.assets.ts, and theIconcomponent API are unchanged.What are the key improvements?
viewBox="0 0 24 24"spec (Phosphor 256-unit paths scaled viatransform="scale(0.09375)") andfill="currentColor"so existing color/size APIs continue to work.currentColorinheritance are unchanged, so Mobile screens can pick up the new art without code changes.strokeor on inheritingfill="none", becauseIconspreadsfill="currentColor"onto the rootSvgand SVGO hoists per-elementfillonto the parent group.Details
101 icons were updated:
pulseplus-squareplusarrow-downarrow-rightarrow-up-rightarrow-upcaret-double-rightarrow-downarrow-leftarrow-rightarrow-upcurrency-dollarbankbookmarkarrows-left-rightcalendarcameracredit-cardchart-barcheckx-circleclock(fill)clockxplugs-connectedcopywarningdatabasedots-six(now on the shared 24×24 viewBox)pencil-simplewarning-circlecompassexporteye-slasheyefunneltreecircle(fill)gas-pumpglobecputree-structurehouse(fill)houseinfokeyspinnermap-pinlocksign-outchat-circle-dotschat-circlemoneydots-threedots-three-verticalbellplantplugqr-codequestionarrow-down-left(not the previous check-in-circle glyph; MMDS still maps Received →check-circle)arrows-clockwisescanmagnifying-glasslock-keyshield-checkpaper-plane-tiltgearshare-networkpuzzle-piecesparklespeedometerstar(fill)swaparrows-down-uptelegram-logothumbs-down(fill)thumbs-downthumbs-up(fill)thumbs-uptrashtrend-downtrend-uptrophyuser-checkseal-check(fill)walletwarningThe following were redrawn in the Phosphor style and are not 1:1 originals from the Phosphor library: AfterHours, CheckBold, Confirmation, CopySuccess, Details, FaceId, LockSlash, MinusBold, Musd, MusdFilled, SecuritySearch, SnapsMobile.
SecuritySearchandSnapsMobileare composites, since Phosphor Regular has no shield-search or snaps-mobile equivalent. Both are filled geometry at Phosphor's 16-unit weight:SecuritySearch: Phosphorshieldwith a magnifying glass inside, sized and centred likeshield-check's inner glyph, with 8-unit clearance from the shield's inner edge.SnapsMobile: Phosphorsquareframe with the cube outlined as capsules and round joins, preserving its previous shape.Excluded from update:
Appleretains the original filled Apple logo (not the Phosphor outline).MetamaskFoxFilledandMetamaskFoxOutlineretain the original MetaMask fox brand art.Unused / MMDS-only component-library assets were already removed on
main(#35571).Changelog
CHANGELOG entry: Updated component-library icons to Phosphor Regular glyphs
Related issues
Refs: MetaMask/metamask-design-system#1482
Refs: MetaMask/metamask-design-system#1475
Refs: #35571
Refs: DSYS-1084
Manual testing steps
Spot-check notes (same as the MMDS PRs):
currentColor/ theme color at multiple sizesScreenshots/Recordings
Before
ScreenRecording_09-08-2026.18-15-37_1.MP4
After
Screen.Recording.2026-09-08.at.5.29.19.PM.mov
ScreenRecording_09-08-2026.18-04-40_1.MP4
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
Low Risk
Asset-only visual refresh with no API or logic changes; main risk is subtle UI/layout or glyph-recognition differences across many screens.
Overview
Replaces ~101 component-library
IconSVG assets with Phosphor Regular–style glyphs as part of the brand migration, without changing icon names,IconAPIs, or TypeScript wiring.Each file now uses a consistent pattern:
viewBox="0 0 24 24", rootfill="currentColor", and Phosphor 256-unit paths scaled viatransform="scale(0.09375)"so existing size and theme coloring keep working. Most icons are direct Phosphor mappings; a smaller set (e.g. Received, SecuritySearch, SnapsMobile, Musd) are custom or composite redraws. DragGrid moves from a narrow10×24viewBox to the shared 24×24 canvas.Apple, MetamaskFoxFilled, and MetamaskFoxOutline are untouched. Screens that import
Iconfrom@metamask/design-system-react-nativeare out of scope until MMDS is bumped.Reviewed by Cursor Bugbot for commit 45ebd88. Bugbot is set up for automated code reviews on this repo. Configure here.