mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 01:39:44 +01:00
Address various UI styling issues (#6744)
* Add loading spinner to pending tx status label. * Add border around account icon in top right * Change style of settings toggle buttons; wrap with local components * Eliminate large space after settings labels when no description * Remove network form from advanced tab of settings * Keep new account container height to contents when in full screen
This commit is contained in:
parent
6df65069a2
commit
32a3f5ad7b
@ -237,9 +237,15 @@
|
||||
"bytes": {
|
||||
"message": "Bytes"
|
||||
},
|
||||
"off": {
|
||||
"message": "Off"
|
||||
},
|
||||
"ok": {
|
||||
"message": "Ok"
|
||||
},
|
||||
"on": {
|
||||
"message": "On"
|
||||
},
|
||||
"optionalBlockExplorerUrl": {
|
||||
"message": "Block Explorer URL (optional)"
|
||||
},
|
||||
|
@ -463,13 +463,13 @@ describe('MetaMask', function () {
|
||||
await advancedTab.click()
|
||||
await delay(regularDelayMs)
|
||||
|
||||
const showConversionToggle = await findElement(driver, By.css('.settings-page__content-row:nth-of-type(7) .settings-page__content-item-col > div'))
|
||||
const showConversionToggle = await findElement(driver, By.css('.settings-page__content-row:nth-of-type(6) .settings-page__content-item-col > div > div'))
|
||||
await showConversionToggle.click()
|
||||
|
||||
const advancedGasTitle = await findElement(driver, By.xpath(`//span[contains(text(), 'Advanced gas controls')]`))
|
||||
await driver.executeScript('arguments[0].scrollIntoView(true)', advancedGasTitle)
|
||||
|
||||
const advancedGasToggle = await findElement(driver, By.css('.settings-page__content-row:nth-of-type(5) .settings-page__content-item-col > div'))
|
||||
const advancedGasToggle = await findElement(driver, By.css('.settings-page__content-row:nth-of-type(4) .settings-page__content-item-col > div > div'))
|
||||
await advancedGasToggle.click()
|
||||
windowHandles = await driver.getAllWindowHandles()
|
||||
extension = windowHandles[0]
|
||||
|
@ -70,6 +70,7 @@ export default class AppHeader extends PureComponent {
|
||||
<Identicon
|
||||
address={selectedAddress}
|
||||
diameter={32}
|
||||
addBorder={true}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
@ -77,3 +77,5 @@
|
||||
@import 'gas-customization/index';
|
||||
|
||||
@import 'gas-customization/gas-price-button-group/index';
|
||||
|
||||
@import '../ui/toggle-button/index';
|
||||
|
@ -43,4 +43,10 @@
|
||||
border: 1px solid $monzo;
|
||||
}
|
||||
}
|
||||
|
||||
&__pending-spinner {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
margin-right: 6px;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ import React, { PureComponent } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import classnames from 'classnames'
|
||||
import Tooltip from '../../ui/tooltip-v2'
|
||||
import Spinner from '../../ui/spinner'
|
||||
|
||||
import {
|
||||
UNAPPROVED_STATUS,
|
||||
REJECTED_STATUS,
|
||||
@ -51,6 +53,7 @@ export default class TransactionStatus extends PureComponent {
|
||||
|
||||
return (
|
||||
<div className={classnames('transaction-status', className, statusToClassNameHash[statusKey])}>
|
||||
{ statusToTextHash[statusKey] === 'pending' ? <Spinner className="transaction-status__pending-spinner" /> : null }
|
||||
<Tooltip
|
||||
position="top"
|
||||
title={title}
|
||||
|
@ -16,6 +16,7 @@ const getStyles = diameter => (
|
||||
|
||||
export default class Identicon extends PureComponent {
|
||||
static propTypes = {
|
||||
addBorder: PropTypes.bool,
|
||||
address: PropTypes.string,
|
||||
className: PropTypes.string,
|
||||
diameter: PropTypes.number,
|
||||
@ -70,7 +71,7 @@ export default class Identicon extends PureComponent {
|
||||
}
|
||||
|
||||
render () {
|
||||
const { className, address, image, diameter, useBlockie } = this.props
|
||||
const { className, address, image, diameter, useBlockie, addBorder } = this.props
|
||||
|
||||
if (image) {
|
||||
return this.renderImage()
|
||||
@ -83,9 +84,11 @@ export default class Identicon extends PureComponent {
|
||||
return this.renderJazzicon()
|
||||
}
|
||||
|
||||
return useBlockie
|
||||
? this.renderBlockie()
|
||||
: this.renderJazzicon()
|
||||
return (
|
||||
<div className={classnames({ 'identicon__address-wrapper': addBorder })}>
|
||||
{ useBlockie ? this.renderBlockie() : this.renderJazzicon() }
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -4,4 +4,17 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
|
||||
&__address-wrapper {
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
border-radius: 18px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-style: solid;
|
||||
border-radius: 50%;
|
||||
border-width: 2px;
|
||||
border-color: $curious-blue;
|
||||
}
|
||||
}
|
||||
|
2
ui/app/components/ui/toggle-button/index.js
Normal file
2
ui/app/components/ui/toggle-button/index.js
Normal file
@ -0,0 +1,2 @@
|
||||
import ToggleButton from './toggle-button.component'
|
||||
module.exports = ToggleButton
|
14
ui/app/components/ui/toggle-button/index.scss
Normal file
14
ui/app/components/ui/toggle-button/index.scss
Normal file
@ -0,0 +1,14 @@
|
||||
.toggle-button {
|
||||
display: flex;
|
||||
|
||||
&__status-label {
|
||||
font-family: Roboto;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-size: 16px;
|
||||
line-height: 23px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import ReactToggleButton from 'react-toggle-button'
|
||||
|
||||
const trackStyle = {
|
||||
width: '40px',
|
||||
height: '24px',
|
||||
padding: '0px',
|
||||
borderRadius: '26px',
|
||||
border: '2px solid rgb(3, 125, 214)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}
|
||||
|
||||
const offTrackStyle = {
|
||||
...trackStyle,
|
||||
border: '2px solid #8E8E8E',
|
||||
}
|
||||
|
||||
const thumbStyle = {
|
||||
width: '18px',
|
||||
height: '18px',
|
||||
display: 'flex',
|
||||
boxShadow: 'none',
|
||||
alignSelf: 'center',
|
||||
borderRadius: '50%',
|
||||
position: 'relative',
|
||||
}
|
||||
|
||||
const colors = {
|
||||
activeThumb: {
|
||||
base: '#037DD6',
|
||||
},
|
||||
inactiveThumb: {
|
||||
base: '#037DD6',
|
||||
},
|
||||
active: {
|
||||
base: '#ffffff',
|
||||
hover: '#ffffff',
|
||||
},
|
||||
inactive: {
|
||||
base: '#DADADA',
|
||||
hover: '#DADADA',
|
||||
},
|
||||
}
|
||||
|
||||
const ToggleButton = props => {
|
||||
const { value, onToggle, offLabel, onLabel } = props
|
||||
|
||||
return (
|
||||
<div className="toggle-button">
|
||||
<ReactToggleButton
|
||||
value={value}
|
||||
onToggle={onToggle}
|
||||
activeLabel=""
|
||||
inactiveLabel=""
|
||||
trackStyle={value ? trackStyle : offTrackStyle}
|
||||
thumbStyle={thumbStyle}
|
||||
thumbAnimateRange={[3, 18]}
|
||||
colors={colors}
|
||||
/>
|
||||
<div className="toggle-button__status-label">{ value ? onLabel : offLabel }</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
ToggleButton.propTypes = {
|
||||
value: PropTypes.bool,
|
||||
onToggle: PropTypes.func,
|
||||
offLabel: PropTypes.string,
|
||||
onLabel: PropTypes.string,
|
||||
}
|
||||
|
||||
export default ToggleButton
|
@ -3,7 +3,11 @@
|
||||
background-color: #FFFFFF;
|
||||
box-shadow: 0 0 7px 0 rgba(0,0,0,0.08);
|
||||
z-index: 25;
|
||||
height: 100%;
|
||||
height: unset;
|
||||
|
||||
@media screen and (min-width: 576px) {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
|
@ -1,8 +1,7 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import validUrl from 'valid-url'
|
||||
import { exportAsFile } from '../../../helpers/utils/util'
|
||||
import ToggleButton from 'react-toggle-button'
|
||||
import ToggleButton from '../../../components/ui/toggle-button'
|
||||
import TextField from '../../../components/ui/text-field'
|
||||
import Button from '../../../components/ui/button'
|
||||
import { MOBILE_SYNC_ROUTE } from '../../../helpers/constants/routes'
|
||||
@ -29,155 +28,7 @@ export default class AdvancedTab extends PureComponent {
|
||||
setShowFiatConversionOnTestnetsPreference: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
state = {
|
||||
newRpc: '',
|
||||
chainId: '',
|
||||
showOptions: false,
|
||||
ticker: '',
|
||||
nickname: '',
|
||||
}
|
||||
|
||||
renderNewRpcUrl () {
|
||||
const { t } = this.context
|
||||
const { newRpc, chainId, ticker, nickname } = this.state
|
||||
|
||||
return (
|
||||
<div className="settings-page__content-row">
|
||||
<div className="settings-page__content-item">
|
||||
<span>{ t('newNetwork') }</span>
|
||||
</div>
|
||||
<div className="settings-page__content-item">
|
||||
<div className="settings-page__content-item-col">
|
||||
<TextField
|
||||
type="text"
|
||||
id="new-rpc"
|
||||
placeholder={t('rpcUrl')}
|
||||
value={newRpc}
|
||||
onChange={e => this.setState({ newRpc: e.target.value })}
|
||||
onKeyPress={e => {
|
||||
if (e.key === 'Enter') {
|
||||
this.validateRpc(newRpc, chainId, ticker, nickname)
|
||||
}
|
||||
}}
|
||||
fullWidth
|
||||
margin="dense"
|
||||
/>
|
||||
<TextField
|
||||
type="text"
|
||||
id="chainid"
|
||||
placeholder={t('optionalChainId')}
|
||||
value={chainId}
|
||||
onChange={e => this.setState({ chainId: e.target.value })}
|
||||
onKeyPress={e => {
|
||||
if (e.key === 'Enter') {
|
||||
this.validateRpc(newRpc, chainId, ticker, nickname)
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
display: this.state.showOptions ? null : 'none',
|
||||
}}
|
||||
fullWidth
|
||||
margin="dense"
|
||||
/>
|
||||
<TextField
|
||||
type="text"
|
||||
id="ticker"
|
||||
placeholder={t('optionalSymbol')}
|
||||
value={ticker}
|
||||
onChange={e => this.setState({ ticker: e.target.value })}
|
||||
onKeyPress={e => {
|
||||
if (e.key === 'Enter') {
|
||||
this.validateRpc(newRpc, chainId, ticker, nickname)
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
display: this.state.showOptions ? null : 'none',
|
||||
}}
|
||||
fullWidth
|
||||
margin="dense"
|
||||
/>
|
||||
<TextField
|
||||
type="text"
|
||||
id="nickname"
|
||||
placeholder={t('optionalNickname')}
|
||||
value={nickname}
|
||||
onChange={e => this.setState({ nickname: e.target.value })}
|
||||
onKeyPress={e => {
|
||||
if (e.key === 'Enter') {
|
||||
this.validateRpc(newRpc, chainId, ticker, nickname)
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
display: this.state.showOptions ? null : 'none',
|
||||
}}
|
||||
fullWidth
|
||||
margin="dense"
|
||||
/>
|
||||
<div className="flex-row flex-align-center space-between">
|
||||
<span className="settings-tab__advanced-link"
|
||||
onClick={e => {
|
||||
e.preventDefault()
|
||||
this.setState({ showOptions: !this.state.showOptions })
|
||||
}}
|
||||
>
|
||||
{ t(this.state.showOptions ? 'hideAdvancedOptions' : 'showAdvancedOptions') }
|
||||
</span>
|
||||
<button
|
||||
className="button btn-primary settings-tab__rpc-save-button"
|
||||
onClick={e => {
|
||||
e.preventDefault()
|
||||
this.validateRpc(newRpc, chainId, ticker, nickname)
|
||||
}}
|
||||
>
|
||||
{ t('save') }
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
validateRpc (newRpc, chainId, ticker = 'ETH', nickname) {
|
||||
const { setRpcTarget, displayWarning } = this.props
|
||||
if (validUrl.isWebUri(newRpc)) {
|
||||
this.context.metricsEvent({
|
||||
eventOpts: {
|
||||
category: 'Settings',
|
||||
action: 'Custom RPC',
|
||||
name: 'Success',
|
||||
},
|
||||
customVariables: {
|
||||
networkId: newRpc,
|
||||
chainId,
|
||||
},
|
||||
})
|
||||
if (!!chainId && Number.isNaN(parseInt(chainId))) {
|
||||
return displayWarning(`${this.context.t('invalidInput')} chainId`)
|
||||
}
|
||||
|
||||
setRpcTarget(newRpc, chainId, ticker, nickname)
|
||||
} else {
|
||||
this.context.metricsEvent({
|
||||
eventOpts: {
|
||||
category: 'Settings',
|
||||
action: 'Custom RPC',
|
||||
name: 'Error',
|
||||
},
|
||||
customVariables: {
|
||||
networkId: newRpc,
|
||||
chainId,
|
||||
},
|
||||
})
|
||||
const appendedRpc = `http://${newRpc}`
|
||||
|
||||
if (validUrl.isWebUri(appendedRpc)) {
|
||||
displayWarning(this.context.t('uriErrorMsg'))
|
||||
} else {
|
||||
displayWarning(this.context.t('invalidRPC'))
|
||||
}
|
||||
}
|
||||
}
|
||||
state = { autoLogoutTimeLimit: this.props.autoLogoutTimeLimit }
|
||||
|
||||
renderMobileSync () {
|
||||
const { t } = this.context
|
||||
@ -293,8 +144,8 @@ export default class AdvancedTab extends PureComponent {
|
||||
<ToggleButton
|
||||
value={sendHexData}
|
||||
onToggle={value => setHexDataFeatureFlag(!value)}
|
||||
activeLabel=""
|
||||
inactiveLabel=""
|
||||
offLabel={t('off')}
|
||||
onLabel={t('on')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -319,8 +170,8 @@ export default class AdvancedTab extends PureComponent {
|
||||
<ToggleButton
|
||||
value={advancedInlineGas}
|
||||
onToggle={value => setAdvancedInlineGasFeatureFlag(!value)}
|
||||
activeLabel=""
|
||||
inactiveLabel=""
|
||||
offLabel={t('off')}
|
||||
onLabel={t('on')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -348,8 +199,8 @@ export default class AdvancedTab extends PureComponent {
|
||||
<ToggleButton
|
||||
value={showFiatInTestnets}
|
||||
onToggle={value => setShowFiatConversionOnTestnetsPreference(!value)}
|
||||
activeLabel=""
|
||||
inactiveLabel=""
|
||||
offLabel={t('off')}
|
||||
onLabel={t('on')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -407,7 +258,6 @@ export default class AdvancedTab extends PureComponent {
|
||||
{ warning && <div className="settings-tab__error">{ warning }</div> }
|
||||
{ this.renderStateLogs() }
|
||||
{ this.renderMobileSync() }
|
||||
{ this.renderNewRpcUrl() }
|
||||
{ this.renderResetAccount() }
|
||||
{ this.renderAdvancedGasInputInline() }
|
||||
{ this.renderHexDataOptIn() }
|
||||
|
@ -16,7 +16,7 @@ describe('AdvancedTab Component', () => {
|
||||
}
|
||||
)
|
||||
|
||||
assert.equal(root.find('.settings-page__content-row').length, 8)
|
||||
assert.equal(root.find('.settings-page__content-row').length, 7)
|
||||
})
|
||||
|
||||
it('should update autoLogoutTimeLimit', () => {
|
||||
|
@ -142,7 +142,7 @@
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 71px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
@media screen and (max-width: 575px) {
|
||||
height: initial;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { exportAsFile } from '../../../helpers/utils/util'
|
||||
import ToggleButton from 'react-toggle-button'
|
||||
import ToggleButton from '../../../components/ui/toggle-button'
|
||||
import { REVEAL_SEED_ROUTE } from '../../../helpers/constants/routes'
|
||||
import Button from '../../../components/ui/button'
|
||||
|
||||
@ -140,8 +140,8 @@ export default class SecurityTab extends PureComponent {
|
||||
<ToggleButton
|
||||
value={privacyMode}
|
||||
onToggle={value => setPrivacyMode(!value)}
|
||||
activeLabel=""
|
||||
inactiveLabel=""
|
||||
offLabel={t('off')}
|
||||
onLabel={t('on')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -166,8 +166,8 @@ export default class SecurityTab extends PureComponent {
|
||||
<ToggleButton
|
||||
value={participateInMetaMetrics}
|
||||
onToggle={value => setParticipateInMetaMetrics(!value)}
|
||||
activeLabel=""
|
||||
inactiveLabel=""
|
||||
offLabel={t('off')}
|
||||
onLabel={t('on')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -2,7 +2,7 @@ import React, { PureComponent } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import infuraCurrencies from '../../../helpers/constants/infura-conversion.json'
|
||||
import SimpleDropdown from '../../../components/app/dropdowns/simple-dropdown'
|
||||
import ToggleButton from 'react-toggle-button'
|
||||
import ToggleButton from '../../../components/ui/toggle-button'
|
||||
import locales from '../../../../../app/_locales/index.json'
|
||||
|
||||
const sortedCurrencies = infuraCurrencies.objects.sort((a, b) => {
|
||||
@ -105,6 +105,7 @@ export default class SettingsTab extends PureComponent {
|
||||
|
||||
|
||||
renderBlockieOptIn () {
|
||||
const { t } = this.context
|
||||
const { useBlockie, setUseBlockie } = this.props
|
||||
|
||||
return (
|
||||
@ -117,8 +118,8 @@ export default class SettingsTab extends PureComponent {
|
||||
<ToggleButton
|
||||
value={useBlockie}
|
||||
onToggle={value => setUseBlockie(!value)}
|
||||
activeLabel=""
|
||||
inactiveLabel=""
|
||||
offLabel={t('off')}
|
||||
onLabel={t('on')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user