1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-22 09:57:02 +01:00

account & network dropdown tweaks

This commit is contained in:
Matthias Kretschmann 2023-04-20 17:19:24 +01:00
parent 4584bb3fe9
commit dba5bb01a0
Signed by: m
GPG Key ID: 606EEEF3C479A91F
8 changed files with 70 additions and 366 deletions

View File

@ -2,6 +2,10 @@
> 🦊 Minimalized version of MetaMask for my own personal use without the myriad of banners & buttons I will never use, and without that terrible Roboto typeface.
<img align="left" width="250" alt="Screenshot 2023-04-20 at 17 04 11" src="https://user-images.githubusercontent.com/90316/233423656-d8e29bdd-f2ba-4723-b8c1-7349bd17bd14.png">
<img width="250" alt="Screenshot 2023-04-20 at 17 04 26" src="https://user-images.githubusercontent.com/90316/233423678-d59cce20-72de-4331-ac9a-09e6b882dca9.png">
<img width="250" alt="Screenshot 2023-04-05 at 19 58 35" src="https://user-images.githubusercontent.com/90316/230178834-31b92326-70d8-4ff0-82d3-c0c03f53f1e9.png">
**Don't blindly trust me and double check the changes before installing this in your own browser.**

View File

@ -1,41 +1,26 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { debounce } from 'lodash';
import Fuse from 'fuse.js';
import InputAdornment from '@material-ui/core/InputAdornment';
import classnames from 'classnames';
import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app';
import {
MetaMetricsContextProp,
MetaMetricsEventAccountType,
MetaMetricsEventCategory,
MetaMetricsEventName,
} from '../../../../shared/constants/metametrics';
import { getEnvironmentType } from '../../../../app/scripts/lib/util';
import Identicon from '../../ui/identicon';
import SiteIcon from '../../ui/site-icon';
import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display';
import {
PRIMARY,
///: BEGIN:ONLY_INCLUDE_IN(beta,flask)
SUPPORT_REQUEST_LINK,
///: END:ONLY_INCLUDE_IN
} from '../../../helpers/constants/common';
import { PRIMARY } from '../../../helpers/constants/common';
import {
SETTINGS_ROUTE,
NEW_ACCOUNT_ROUTE,
IMPORT_ACCOUNT_ROUTE,
CONNECT_HARDWARE_ROUTE,
DEFAULT_ROUTE,
///: BEGIN:ONLY_INCLUDE_IN(flask)
NOTIFICATIONS_ROUTE,
///: END:ONLY_INCLUDE_IN
} from '../../../helpers/constants/routes';
import TextField from '../../ui/text-field';
import Button from '../../ui/button';
import SearchIcon from '../../ui/icon/search-icon';
import { SUPPORT_LINK } from '../../../../shared/lib/ui-utils';
import { IconColor } from '../../../helpers/constants/design-system';
import { Icon, IconName, IconSize } from '../../component-library';
import KeyRingLabel from './keyring-label';
@ -82,7 +67,6 @@ export default class AccountMenu extends Component {
history: PropTypes.object,
isAccountMenuOpen: PropTypes.bool,
keyrings: PropTypes.array,
lockMetamask: PropTypes.func,
selectedAddress: PropTypes.string,
setSelectedAccount: PropTypes.func,
toggleAccountMenu: PropTypes.func,
@ -96,7 +80,6 @@ export default class AccountMenu extends Component {
accountsRef;
state = {
shouldShowScrollButton: false,
searchQuery: '',
};
@ -113,22 +96,13 @@ export default class AccountMenu extends Component {
],
});
componentDidUpdate(prevProps, prevState) {
componentDidUpdate(prevProps) {
const { isAccountMenuOpen: prevIsAccountMenuOpen } = prevProps;
const { searchQuery: prevSearchQuery } = prevState;
const { isAccountMenuOpen } = this.props;
const { searchQuery } = this.state;
if (!prevIsAccountMenuOpen && isAccountMenuOpen) {
this.setShouldShowScrollButton();
this.resetSearchQuery();
}
// recalculate on each search query change
// whether we can show scroll down button
if (isAccountMenuOpen && prevSearchQuery !== searchQuery) {
this.setShouldShowScrollButton();
}
}
renderAccountsSearch() {
@ -208,16 +182,7 @@ export default class AccountMenu extends Component {
return (
<button
className="account-menu__account account-menu__item--clickable"
onClick={() => {
this.context.trackEvent({
category: MetaMetricsEventCategory.Navigation,
event: MetaMetricsEventName.NavAccountSwitched,
properties: {
location: 'Main Menu',
},
});
setSelectedAccount(identity.address);
}}
onClick={() => setSelectedAccount(identity.address)}
key={identity.address}
data-testid="account-menu__account"
>
@ -263,52 +228,12 @@ export default class AccountMenu extends Component {
this.setState({ searchQuery });
}
setShouldShowScrollButton = () => {
if (!this.accountsRef) {
return;
}
const { scrollTop, offsetHeight, scrollHeight } = this.accountsRef;
const canScroll = scrollHeight > offsetHeight;
const atAccountListBottom = scrollTop + offsetHeight >= scrollHeight;
const shouldShowScrollButton = canScroll && !atAccountListBottom;
this.setState({ shouldShowScrollButton });
};
onScroll = debounce(this.setShouldShowScrollButton, 25);
handleScrollDown = (e) => {
e.stopPropagation();
const { scrollHeight } = this.accountsRef;
this.accountsRef.scroll({ left: 0, top: scrollHeight, behavior: 'smooth' });
this.setShouldShowScrollButton();
};
renderScrollButton() {
if (!this.state.shouldShowScrollButton) {
return null;
}
return (
<div
className="account-menu__scroll-button"
onClick={this.handleScrollDown}
>
<i className="fa fa-arrow-down" title={this.context.t('scrollDown')} />
</div>
);
}
render() {
const { t, trackEvent } = this.context;
const { t } = this.context;
const {
shouldShowAccountsSearch,
isAccountMenuOpen,
toggleAccountMenu,
lockMetamask,
history,
///: BEGIN:ONLY_INCLUDE_IN(flask)
unreadNotificationsCount,
@ -319,55 +244,24 @@ export default class AccountMenu extends Component {
return null;
}
let supportText = t('support');
let supportLink = SUPPORT_LINK;
///: BEGIN:ONLY_INCLUDE_IN(beta,flask)
supportText = t('needHelpSubmitTicket');
supportLink = SUPPORT_REQUEST_LINK;
///: END:ONLY_INCLUDE_IN
return (
<div className="account-menu">
<div className="account-menu__close-area" onClick={toggleAccountMenu} />
<AccountMenuItem className="account-menu__header">
{t('myAccounts')}
<Button
className="account-menu__lock-button"
type="secondary"
onClick={() => {
lockMetamask();
history.push(DEFAULT_ROUTE);
}}
>
{t('lock')}
</Button>
</AccountMenuItem>
<div className="account-menu__divider" />
<div className="account-menu__accounts-container">
{shouldShowAccountsSearch ? this.renderAccountsSearch() : null}
<div
className="account-menu__accounts"
onScroll={this.onScroll}
ref={(ref) => {
this.accountsRef = ref;
}}
>
{this.renderAccounts()}
</div>
{this.renderScrollButton()}
</div>
<div className="account-menu__divider" />
<AccountMenuItem
onClick={() => {
toggleAccountMenu();
trackEvent({
category: MetaMetricsEventCategory.Navigation,
event: MetaMetricsEventName.AccountAddSelected,
properties: {
account_type: MetaMetricsEventAccountType.Default,
location: 'Main Menu',
},
});
history.push(NEW_ACCOUNT_ROUTE);
}}
icon={<Icon name={IconName.Add} color={IconColor.iconAlternative} />}
@ -376,14 +270,6 @@ export default class AccountMenu extends Component {
<AccountMenuItem
onClick={() => {
toggleAccountMenu();
trackEvent({
category: MetaMetricsEventCategory.Navigation,
event: MetaMetricsEventName.AccountAddSelected,
properties: {
account_type: MetaMetricsEventAccountType.Imported,
location: 'Main Menu',
},
});
history.push(IMPORT_ACCOUNT_ROUTE);
}}
icon={
@ -394,14 +280,6 @@ export default class AccountMenu extends Component {
<AccountMenuItem
onClick={() => {
toggleAccountMenu();
trackEvent({
category: MetaMetricsEventCategory.Navigation,
event: MetaMetricsEventName.AccountAddSelected,
properties: {
account_type: MetaMetricsEventAccountType.Hardware,
location: 'Main Menu',
},
});
if (getEnvironmentType() === ENVIRONMENT_TYPE_POPUP) {
global.platform.openExtensionInBrowser(CONNECT_HARDWARE_ROUTE);
} else {
@ -413,10 +291,8 @@ export default class AccountMenu extends Component {
}
text={t('connectHardwareWallet')}
/>
<div className="account-menu__divider" />
{
///: BEGIN:ONLY_INCLUDE_IN(flask)
<>
<AccountMenuItem
onClick={() => {
toggleAccountMenu();
@ -434,45 +310,13 @@ export default class AccountMenu extends Component {
}
text={t('notifications')}
/>
<div className="account-menu__divider" />
</>
///: END:ONLY_INCLUDE_IN
}
<AccountMenuItem
onClick={() => {
trackEvent(
{
category: MetaMetricsEventCategory.Navigation,
event: MetaMetricsEventName.SupportLinkClicked,
properties: {
url: supportLink,
},
},
{
contextPropsIntoEventProperties: [
MetaMetricsContextProp.PageTitle,
],
},
);
global.platform.openTab({ url: supportLink });
}}
icon={
<Icon name={IconName.Messages} color={IconColor.iconAlternative} />
}
text={supportText}
/>
<AccountMenuItem
onClick={() => {
toggleAccountMenu();
history.push(SETTINGS_ROUTE);
this.context.trackEvent({
category: MetaMetricsEventCategory.Navigation,
event: MetaMetricsEventName.NavSettingsOpened,
properties: {
location: 'Main Menu',
},
});
}}
icon={
<Icon

View File

@ -6,7 +6,6 @@
border-radius: 4px;
background: var(--color-background-default);
box-shadow: var(--shadow-size-sm) var(--color-shadow-default);
min-width: 150px;
color: var(--color-text-default);
@include screen-sm-max {
@ -26,7 +25,7 @@
}
&__item {
padding: 18px;
padding: 8px 16px;
display: flex;
flex-flow: row wrap;
align-items: center;
@ -36,11 +35,6 @@
background: none;
width: 100%;
@include screen-sm-max {
padding: 0 14px;
height: 40px;
}
&--clickable {
cursor: pointer;
@ -184,18 +178,17 @@
&__no-accounts {
@include H6;
padding: 16px 14px;
padding: 16px;
}
&__account {
display: flex;
flex-flow: row nowrap;
padding: 14px;
padding: 8px 16px;
flex: 0 0 auto;
background: none;
border: 0;
width: 100%;
border-bottom: 1px solid var(--color-border-muted);
.remove-account-icon {
width: 15px;
@ -233,7 +226,7 @@
}
&__name {
@include Paragraph;
@include H6;
color: var(--color-text-default);
text-overflow: ellipsis;
@ -246,37 +239,16 @@
&__balance {
@include H6;
font-weight: 400;
color: var(--color-text-alternative);
}
&__action {
@include Paragraph;
@include H6;
cursor: pointer;
}
&__scroll-button {
position: absolute;
bottom: 12px;
right: 12px;
height: 28px;
width: 28px;
border-radius: 14px;
border: 1px solid var(--color-border-default);
background: var(--color-background-alternative);
color: var(--color-icon-default);
z-index: 201;
cursor: pointer;
opacity: 0.8;
display: flex;
justify-content: center;
align-items: center;
&:hover {
opacity: 1;
}
}
&__icon-list {
display: flex;
}

View File

@ -4,7 +4,7 @@ import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import { compose } from 'redux';
import { pickBy } from 'lodash';
import Button from '../../ui/button';
import { Button } from '../../component-library/button';
import * as actions from '../../../store/actions';
import { openAlert as displayInvalidCustomNetworkAlert } from '../../../ducks/alerts/invalid-custom-network';
import {
@ -18,22 +18,17 @@ import {
} from '../../../../shared/constants/network';
import { isPrefixedFormattedHexString } from '../../../../shared/modules/network.utils';
import ColorIndicator from '../../ui/color-indicator';
import { IconColor, Size } from '../../../helpers/constants/design-system';
import {
IconColor,
Color,
FontWeight,
} from '../../../helpers/constants/design-system';
import { getShowTestNetworks } from '../../../selectors';
import { getEnvironmentType } from '../../../../app/scripts/lib/util';
import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app';
import {
MetaMetricsEventCategory,
MetaMetricsEventName,
MetaMetricsNetworkEventSource,
} from '../../../../shared/constants/metametrics';
import {
ADD_POPULAR_CUSTOM_NETWORK,
ADVANCED_ROUTE,
} from '../../../helpers/constants/routes';
import { MetaMetricsNetworkEventSource } from '../../../../shared/constants/metametrics';
import { ADD_POPULAR_CUSTOM_NETWORK } from '../../../helpers/constants/routes';
import { Icon, IconName } from '../../component-library';
import { Dropdown, DropdownMenuItem } from './dropdown';
// classes from nodes of the toggle element.
@ -47,9 +42,8 @@ const notToggleElementClassnames = [
];
const DROP_DOWN_MENU_ITEM_STYLE = {
fontSize: '16px',
lineHeight: '20px',
padding: '16px',
fontSize: '0.875rem', // h6 size from SCSS design system
padding: '12px',
};
function mapStateToProps(state) {
@ -109,31 +103,14 @@ class NetworkDropdown extends Component {
shouldShowTestNetworks: PropTypes.bool,
networkDropdownOpen: PropTypes.bool.isRequired,
displayInvalidCustomNetworkAlert: PropTypes.func.isRequired,
// showConfirmDeleteNetworkModal: PropTypes.func.isRequired,
showTestnetMessageInDropdown: PropTypes.bool.isRequired,
hideTestNetMessage: PropTypes.func.isRequired,
history: PropTypes.object,
dropdownStyles: PropTypes.object,
hideElementsForOnboarding: PropTypes.bool,
onAddClick: PropTypes.func,
upsertNetworkConfiguration: PropTypes.func.isRequired,
};
handleClick(newProviderType) {
const {
provider: { type: providerType },
setProviderType,
} = this.props;
const { trackEvent } = this.context;
trackEvent({
category: MetaMetricsEventCategory.Navigation,
event: MetaMetricsEventName.NavNetworkSwitched,
properties: {
from_network: providerType,
to_network: newProviderType,
},
});
const { setProviderType } = this.props;
setProviderType(newProviderType);
}
@ -142,7 +119,9 @@ class NetworkDropdown extends Component {
return (
<div className="network__add-network-button">
<Button
type="secondary"
type="link"
startIconName={IconName.Add}
color={Color.primaryDefault}
onClick={() => {
if (onAddClick) {
onAddClick();
@ -162,7 +141,7 @@ class NetworkDropdown extends Component {
);
}
renderCustomRpcList(networkConfigurations, provider, opts = {}) {
renderCustomRpcList(networkConfigurations, provider) {
return Object.entries(networkConfigurations).map(
([networkConfigurationId, networkConfiguration]) => {
const { rpcUrl, chainId, nickname = '' } = networkConfiguration;
@ -179,29 +158,19 @@ class NetworkDropdown extends Component {
this.props.displayInvalidCustomNetworkAlert(nickname || rpcUrl);
}
}}
style={{
fontSize: '16px',
lineHeight: '20px',
padding: '16px',
}}
style={DROP_DOWN_MENU_ITEM_STYLE}
>
{isCurrentRpcTarget ? (
<Icon name={IconName.Check} color={IconColor.successDefault} />
) : (
<div className="network-check__transparent"></div>
)}
<ColorIndicator
color={opts.isLocalHost ? 'localhost' : IconColor.iconMuted}
size={Size.LG}
type={ColorIndicator.TYPES.FILLED}
/>
<span
className="network-name-item"
data-testid={`${nickname}-network-item`}
style={{
color: isCurrentRpcTarget
? 'var(--color-text-default)'
: 'var(--color-text-alternative)',
fontWeight: isCurrentRpcTarget ? FontWeight.Bold : null,
marginLeft: '8px',
}}
>
{nickname || rpcUrl}
@ -249,19 +218,12 @@ class NetworkDropdown extends Component {
) : (
<div className="network-check__transparent"></div>
)}
<ColorIndicator
color={network}
size={Size.LG}
type={ColorIndicator.TYPES.FILLED}
/>
<span
className="network-name-item"
data-testid={`${network}-network-item`}
style={{
color:
providerType === network
? 'var(--color-text-default)'
: 'var(--color-text-alternative)',
fontWeight: providerType === network ? FontWeight.Bold : null,
marginLeft: '8px',
}}
>
{this.context.t(network)}
@ -318,19 +280,12 @@ class NetworkDropdown extends Component {
) : (
<div className="network-check__transparent"></div>
)}
<ColorIndicator
color={network}
size={Size.LG}
type={ColorIndicator.TYPES.FILLED}
/>
<span
className="network-name-item"
data-testid={`${network}-network-item`}
style={{
color:
provider.type === network
? 'var(--color-text-default)'
: 'var(--color-text-alternative)',
fontWeight: provider.type === network ? FontWeight.Bold : null,
marginLeft: '8px',
}}
>
{this.context.t(network)}
@ -341,12 +296,8 @@ class NetworkDropdown extends Component {
render() {
const {
history,
hideElementsForOnboarding,
hideNetworkDropdown,
shouldShowTestNetworks,
showTestnetMessageInDropdown,
hideTestNetMessage,
networkConfigurations,
} = this.props;
@ -362,7 +313,6 @@ class NetworkDropdown extends Component {
);
const isOpen = this.props.networkDropdownOpen;
const { t } = this.context;
return (
<Dropdown
@ -384,47 +334,12 @@ class NetworkDropdown extends Component {
this.props.dropdownStyles || {
position: 'absolute',
top: '58px',
width: '309px',
width: '250px',
zIndex: '55',
}
}
innerStyle={{
padding: '16px 0',
}}
innerStyle={{ padding: '0 0 16px 0' }}
>
<div className="network-dropdown-header">
{hideElementsForOnboarding ? null : (
<div className="network-dropdown-title">{t('networks')}</div>
)}
{hideElementsForOnboarding ? null : (
<div className="network-dropdown-divider" />
)}
{showTestnetMessageInDropdown && !hideElementsForOnboarding ? (
<div className="network-dropdown-content">
{t('toggleTestNetworks', [
<a
href="#"
key="advancedSettingsLink"
className="network-dropdown-content--link"
onClick={(e) => {
e.preventDefault();
hideNetworkDropdown();
history.push(`${ADVANCED_ROUTE}#show-testnets`);
}}
>
{t('showHide')}
</a>,
])}
<Button
onClick={hideTestNetMessage}
className="network-dropdown-content--dismiss"
>
{t('dismiss')}
</Button>
</div>
) : null}
</div>
<div className="network-dropdown-list">
{this.renderNetworkEntry(NETWORK_TYPES.MAINNET)}

View File

@ -2,9 +2,6 @@
display: flex;
align-items: center;
justify-content: flex-start;
padding: 0 10px;
border-radius: 4px;
min-height: 25px;
user-select: none;
&--disabled {

View File

@ -8,12 +8,10 @@ import {
} from '../../../../shared/constants/network';
import LoadingIndicator from '../../ui/loading-indicator';
import ColorIndicator from '../../ui/color-indicator';
import {
BorderColor,
IconColor,
Size,
TypographyVariant,
FontWeight,
Color,
} from '../../../helpers/constants/design-system';
import Chip from '../../ui/chip/chip';
import { useI18nContext } from '../../../hooks/useI18nContext';
@ -21,7 +19,6 @@ import { isNetworkLoading } from '../../../selectors';
import { Icon, IconName, IconSize } from '../../component-library';
export default function NetworkDisplay({
indicatorSize,
disabled,
labelProps,
targetNetwork,
@ -39,31 +36,14 @@ export default function NetworkDisplay({
return (
<Chip
dataTestId="network-display"
borderColor={
onClick ? BorderColor.borderDefault : BorderColor.borderMuted
}
borderColor={BorderColor.transparent}
onClick={onClick}
leftIcon={
<LoadingIndicator
alt={t('attemptingConnect')}
title={t('attemptingConnect')}
isLoading={networkIsLoading}
>
<ColorIndicator
color={
networkType === NETWORK_TYPES.RPC
? IconColor.iconMuted
: networkType
}
size={indicatorSize}
type={ColorIndicator.TYPES.FILLED}
iconClassName={
networkType === NETWORK_TYPES.RPC && indicatorSize !== Size.XS
? 'fa fa-question'
: undefined
}
/>
</LoadingIndicator>
}
rightIcon={
onClick ? <Icon name={IconName.ArrowDown} size={IconSize.Xs} /> : null
@ -78,17 +58,14 @@ export default function NetworkDisplay({
'network-display--clickable': typeof onClick === 'function',
})}
labelProps={{
variant: TypographyVariant.H7,
fontWeight: FontWeight.Medium,
color: Color.textDefault,
...labelProps,
}}
/>
);
}
NetworkDisplay.propTypes = {
/**
* The size of the indicator
*/
indicatorSize: PropTypes.oneOf(Object.values(Size)),
/**
* The label props of the label can use most of the Typography props
*/
@ -115,7 +92,3 @@ NetworkDisplay.propTypes = {
*/
onClick: PropTypes.func,
};
NetworkDisplay.defaultProps = {
indicatorSize: Size.LG,
};

View File

@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { omit } from 'lodash';
import Typography from '../typography';
import { Text } from '../../component-library/text';
import UrlIcon from '../url-icon';
import {
BackgroundColor,
@ -57,15 +57,14 @@ export default function Chip({
<UrlIcon className="chip__left-url-icon" url={leftIconUrl} />
) : null}
{children ?? (
<Typography
<Text
className="chip__label"
variant={TypographyVariant.H6}
as="span"
color={TextColor.textAlternative}
{...labelProps}
>
{label}
</Typography>
</Text>
)}
{rightIcon ? <div className="chip__right-icon">{rightIcon}</div> : null}
</div>

View File

@ -331,15 +331,15 @@ export const TEXT_TRANSFORM = {
};
export enum FontWeight {
Bold = 'bold',
Medium = 'medium',
Normal = 'normal',
Bold = '600',
Medium = '500',
Normal = '400',
}
export const FONT_WEIGHT = {
BOLD: 'bold',
MEDIUM: 'medium',
NORMAL: 'normal',
BOLD: '600',
MEDIUM: '500',
NORMAL: '400',
};
export enum OverflowWrap {