Skip to content

Commit 7a9cb7e

Browse files
authored
[UX] Disable portfolio in overlay for incompatible wallet providers (#1150)
* disable portfolio in overlay and show tooltip if non mm wallet connected * run yarn * rm debug log * run yarn setup
1 parent 9bb76b4 commit 7a9cb7e

File tree

4 files changed

+164
-105
lines changed

4 files changed

+164
-105
lines changed

public/locales/en/translation.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,12 @@
10801080
"manageStore": "Manage stores",
10811081
"quit": "Quit"
10821082
},
1083+
"wallet": {
1084+
"portfolio": {
1085+
"onlyExtension": "MetaMask Portfolio is only available when connected with MetaMask."
1086+
},
1087+
"unsupported": "Unsupported Wallet Connection"
1088+
},
10831089
"webview": {
10841090
"controls": {
10851091
"back": "Go back",

src/frontend/OverlayManager/Overlay/NavBarOverlayWrapper/PortfolioNavItem/index.tsx

Lines changed: 113 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -3,74 +3,122 @@ import styles from '../index.module.scss'
33
import { NavItem, Images, SubLink } from '@hyperplay/ui'
44
import { Link, useLocation } from 'react-router-dom'
55
import { useTranslation } from 'react-i18next'
6+
import { observer } from 'mobx-react-lite'
7+
import walletState from 'frontend/state/WalletState'
8+
import { PROVIDERS } from '@hyperplay/utils'
9+
import classNames from 'classnames'
10+
import { Popover } from '@mantine/core'
11+
import { useDisclosure } from '@mantine/hooks'
612

713
export interface PortfolioNavItemProps {
814
collapsed: boolean
915
}
1016

11-
export function PortfolioNavItem({ collapsed }: PortfolioNavItemProps) {
12-
const location = useLocation()
13-
const { pathname } = location
14-
const [mmCollapsed, mmSetCollapsed] = useState(false)
15-
const { t } = useTranslation()
17+
export const PortfolioNavItem = observer(
18+
({ collapsed }: PortfolioNavItemProps) => {
19+
const location = useLocation()
20+
const { pathname } = location
21+
const [mmCollapsed, mmSetCollapsed] = useState(false)
22+
const { t } = useTranslation()
23+
const [opened, { close, open }] = useDisclosure(false)
1624

17-
return (
18-
<NavItem
19-
title={t('overlay.links.portfolio', 'Portfolio')}
20-
icon={<Images.MetaMaskColored fill="none" width={22} height={36} />}
21-
key={'/portfolio'}
22-
collapsed={collapsed}
23-
selected={pathname.startsWith('/portfolio')}
24-
onClick={() => mmSetCollapsed(!mmCollapsed)}
25-
subLinksCollapsed={mmCollapsed}
26-
setSubLinksCollapsed={() => mmSetCollapsed(!mmCollapsed)}
27-
subLinks={[
28-
<SubLink
29-
key={'Portfolio'}
30-
component={Link}
31-
to={'/portfolio'}
32-
selected={pathname === '/portfolio'}
33-
className={styles.sublink}
34-
>
35-
{t('overlay.links.portfolio', 'Portfolio')}
36-
</SubLink>,
37-
<SubLink
38-
key={'Swap'}
39-
component={Link}
40-
to={'/portfolio/swap'}
41-
selected={pathname === '/portfolio/swap'}
42-
className={styles.sublink}
43-
>
44-
{t('overlay.links.swap', 'Swap')}
45-
</SubLink>,
46-
<SubLink
47-
key={'Bridge'}
48-
component={Link}
49-
to={'/portfolio/bridge'}
50-
selected={pathname === '/portfolio/bridge'}
51-
className={styles.sublink}
52-
>
53-
{t('overlay.links.bridge', 'Bridge')}
54-
</SubLink>,
55-
<SubLink
56-
key={'Buy'}
57-
component={Link}
58-
to={'/portfolio/buy'}
59-
selected={pathname === '/portfolio/buy'}
60-
className={styles.sublink}
61-
>
62-
{t('overlay.links.buy', 'Buy')}
63-
</SubLink>,
64-
<SubLink
65-
key={'Sell'}
66-
component={Link}
67-
to={'/portfolio/sell'}
68-
selected={pathname === '/portfolio/sell'}
69-
className={styles.sublink}
70-
>
71-
{t('overlay.links.sell', 'Sell')}
72-
</SubLink>
73-
]}
74-
/>
75-
)
76-
}
25+
const enablePortfolioNavItem =
26+
walletState.isConnected &&
27+
(walletState.provider === PROVIDERS.METAMASK_EXTENSION ||
28+
walletState.provider === PROVIDERS.METAMASK_MOBILE)
29+
30+
const navItemClasses: Record<string, boolean> = {}
31+
navItemClasses[styles.disabled] = !enablePortfolioNavItem
32+
33+
return (
34+
<Popover
35+
opened={opened && !enablePortfolioNavItem}
36+
unstyled
37+
classNames={{ dropdown: styles.popoverDropdown, arrow: styles.arrow }}
38+
position="bottom-start"
39+
offset={0}
40+
withArrow
41+
arrowPosition="side"
42+
arrowOffset={16}
43+
>
44+
<Popover.Target>
45+
<div>
46+
<NavItem
47+
onMouseEnter={open}
48+
onMouseLeave={close}
49+
title={t('overlay.links.portfolio', 'Portfolio')}
50+
icon={
51+
<Images.MetaMaskColored fill="none" width={22} height={36} />
52+
}
53+
key={'/portfolio'}
54+
collapsed={collapsed}
55+
selected={pathname.startsWith('/portfolio')}
56+
onClick={() => mmSetCollapsed(!mmCollapsed)}
57+
subLinksCollapsed={mmCollapsed || !enablePortfolioNavItem}
58+
setSubLinksCollapsed={() => mmSetCollapsed(!mmCollapsed)}
59+
classNames={{ link: classNames(navItemClasses) }}
60+
subLinks={[
61+
<SubLink
62+
key={'Portfolio'}
63+
component={Link}
64+
to={'/portfolio'}
65+
selected={pathname === '/portfolio'}
66+
className={styles.sublink}
67+
>
68+
{t('overlay.links.portfolio', 'Portfolio')}
69+
</SubLink>,
70+
<SubLink
71+
key={'Swap'}
72+
component={Link}
73+
to={'/portfolio/swap'}
74+
selected={pathname === '/portfolio/swap'}
75+
className={styles.sublink}
76+
>
77+
{t('overlay.links.swap', 'Swap')}
78+
</SubLink>,
79+
<SubLink
80+
key={'Bridge'}
81+
component={Link}
82+
to={'/portfolio/bridge'}
83+
selected={pathname === '/portfolio/bridge'}
84+
className={styles.sublink}
85+
>
86+
{t('overlay.links.bridge', 'Bridge')}
87+
</SubLink>,
88+
<SubLink
89+
key={'Buy'}
90+
component={Link}
91+
to={'/portfolio/buy'}
92+
selected={pathname === '/portfolio/buy'}
93+
className={styles.sublink}
94+
>
95+
{t('overlay.links.buy', 'Buy')}
96+
</SubLink>,
97+
<SubLink
98+
key={'Sell'}
99+
component={Link}
100+
to={'/portfolio/sell'}
101+
selected={pathname === '/portfolio/sell'}
102+
className={styles.sublink}
103+
>
104+
{t('overlay.links.sell', 'Sell')}
105+
</SubLink>
106+
]}
107+
/>
108+
</div>
109+
</Popover.Target>
110+
<Popover.Dropdown>
111+
<div className={classNames('caption', styles.unsupportedModalTitle)}>
112+
{t('wallet.unsupported', 'Unsupported Wallet Connection')}
113+
</div>
114+
<div className="caption-sm color-neutral-400">
115+
{t(
116+
'wallet.portfolio.onlyExtension',
117+
'MetaMask Portfolio is only available when connected with MetaMask.'
118+
)}
119+
</div>
120+
</Popover.Dropdown>
121+
</Popover>
122+
)
123+
}
124+
)
Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,38 @@
1-
.disabled {
1+
$modalBgColor: var(--color-neutral-600);
2+
3+
@mixin disable {
24
cursor: not-allowed !important;
35
opacity: 50%;
46
}
57

8+
.disabled {
9+
@include disable;
10+
11+
button {
12+
@include disable;
13+
}
14+
}
15+
616
.sublink {
717
display: block;
818
}
19+
20+
.popoverDropdown {
21+
border: 'none';
22+
display: flex;
23+
flex-direction: column;
24+
background-color: $modalBgColor;
25+
border-radius: var(--space-xs-fixed);
26+
padding: var(--space-sm);
27+
color: var(--color-neutral-100);
28+
position: absolute;
29+
max-width: 280px;
30+
}
31+
32+
.arrow {
33+
background-color: $modalBgColor;
34+
}
35+
36+
.unsupportedModalTitle {
37+
margin-bottom: var(--space-sm);
38+
}

yarn.lock

Lines changed: 14 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2993,16 +2993,16 @@
29932993
dependencies:
29942994
defer-to-connect "^2.0.0"
29952995

2996-
"@tanstack/[email protected]", "@tanstack/query-core@^5.59.13":
2996+
"@tanstack/[email protected]":
2997+
version "5.59.20"
2998+
resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-5.59.20.tgz#356718976536727b9af0ad1163a21fd6a44ee0a9"
2999+
integrity sha512-e8vw0lf7KwfGe1if4uPFhvZRWULqHjFcz3K8AebtieXvnMOz5FSzlZe3mTLlPuUBcydCnBRqYs2YJ5ys68wwLg==
3000+
3001+
"@tanstack/query-core@^5.59.13":
29973002
version "5.59.13"
29983003
resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-5.59.13.tgz#8c962980af174bbd446b7e9b9999f7432897df80"
29993004
integrity sha512-Oou0bBu/P8+oYjXsJQ11j+gcpLAMpqW42UlokQYEz4dE7+hOtVO9rVuolJKgEccqzvyFzqX4/zZWY+R/v1wVsQ==
30003005

3001-
"@tanstack/query-core@^5.59.0":
3002-
version "5.59.0"
3003-
resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-5.59.0.tgz#d8323f1c6eb0e573ab0aa85a7b7690d0c263818a"
3004-
integrity sha512-WGD8uIhX6/deH/tkZqPNcRyAhDUqs729bWKoByYHSogcshXfFbppOdTER5+qY7mFvu8KEFJwT0nxr8RfPTVh0Q==
3005-
30063006
"@tanstack/[email protected]":
30073007
version "5.59.20"
30083008
resolved "https://registry.yarnpkg.com/@tanstack/query-devtools/-/query-devtools-5.59.20.tgz#a827ac682ec1268fc9c99e7b6eb739f35b5606aa"
@@ -3015,12 +3015,12 @@
30153015
dependencies:
30163016
"@tanstack/query-devtools" "5.59.20"
30173017

3018-
"@tanstack/react-query@^5.51.23":
3019-
version "5.52.2"
3020-
resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-5.52.2.tgz#3fffbc86351edcaeec335bc8958bcab4204bd169"
3021-
integrity sha512-d4OwmobpP+6+SvuAxW1RzAY95Pv87Gu+0GjtErzFOUXo+n0FGcwxKvzhswCsXKxsgnAr3bU2eJ2u+GXQAutkCQ==
3018+
"@tanstack/react-query@^5.59.15":
3019+
version "5.60.2"
3020+
resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-5.60.2.tgz#a65db96702c11f3f868c40372ce66f05c2a77cc6"
3021+
integrity sha512-JhpJNxIAPuE0YCpP1Py4zAsgx+zY0V531McRMtQbwVlJF8+mlZwcOPrzGmPV248K8IP+mPbsfxXToVNMNwjUcw==
30223022
dependencies:
3023-
"@tanstack/query-core" "5.59.13"
3023+
"@tanstack/query-core" "5.59.20"
30243024

30253025
"@testing-library/dom@^7.31.2":
30263026
version "7.31.2"
@@ -12735,16 +12735,7 @@ string-length@^4.0.1:
1273512735
char-regex "^1.0.2"
1273612736
strip-ansi "^6.0.0"
1273712737

12738-
"string-width-cjs@npm:string-width@^4.2.0":
12739-
version "4.2.3"
12740-
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
12741-
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
12742-
dependencies:
12743-
emoji-regex "^8.0.0"
12744-
is-fullwidth-code-point "^3.0.0"
12745-
strip-ansi "^6.0.1"
12746-
12747-
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
12738+
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
1274812739
version "4.2.3"
1274912740
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
1275012741
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -12838,14 +12829,7 @@ stringify-entities@^4.0.0:
1283812829
character-entities-html4 "^2.0.0"
1283912830
character-entities-legacy "^3.0.0"
1284012831

12841-
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
12842-
version "6.0.1"
12843-
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
12844-
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
12845-
dependencies:
12846-
ansi-regex "^5.0.1"
12847-
12848-
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
12832+
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
1284912833
version "6.0.1"
1285012834
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
1285112835
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -14100,7 +14084,7 @@ word-wrap@^1.2.5:
1410014084
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34"
1410114085
integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==
1410214086

14103-
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
14087+
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
1410414088
version "7.0.0"
1410514089
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
1410614090
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@@ -14118,15 +14102,6 @@ wrap-ansi@^6.2.0:
1411814102
string-width "^4.1.0"
1411914103
strip-ansi "^6.0.0"
1412014104

14121-
wrap-ansi@^7.0.0:
14122-
version "7.0.0"
14123-
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
14124-
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
14125-
dependencies:
14126-
ansi-styles "^4.0.0"
14127-
string-width "^4.1.0"
14128-
strip-ansi "^6.0.0"
14129-
1413014105
wrap-ansi@^8.1.0:
1413114106
version "8.1.0"
1413214107
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"

0 commit comments

Comments
 (0)