aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChi Kei Chan <chikeichan@gmail.com>2017-09-22 09:44:52 +0800
committerChi Kei Chan <chikeichan@gmail.com>2017-09-22 09:44:52 +0800
commit3ec2f534632426876c28b22c58cbbf14b4904d97 (patch)
treeed84f2703e86a29a7db43a4ecabac308a0cbe7bb
parent24fd16b1bee31352ef7f364804eb5f06c08c3bf6 (diff)
downloadtangerine-wallet-browser-3ec2f534632426876c28b22c58cbbf14b4904d97.tar.gz
tangerine-wallet-browser-3ec2f534632426876c28b22c58cbbf14b4904d97.tar.zst
tangerine-wallet-browser-3ec2f534632426876c28b22c58cbbf14b4904d97.zip
Integrate Add Token
-rw-r--r--ui/app/actions.js39
-rw-r--r--ui/app/add-token.js428
-rw-r--r--ui/app/components/token-balance.js14
-rw-r--r--ui/app/components/tx-list.js2
-rw-r--r--ui/app/css/itcss/components/add-token.scss95
-rw-r--r--ui/app/css/itcss/components/buttons.scss10
6 files changed, 333 insertions, 255 deletions
diff --git a/ui/app/actions.js b/ui/app/actions.js
index 678c68a6a..1231fc296 100644
--- a/ui/app/actions.js
+++ b/ui/app/actions.js
@@ -147,6 +147,7 @@ var actions = {
SHOW_ADD_TOKEN_PAGE: 'SHOW_ADD_TOKEN_PAGE',
showAddTokenPage,
addToken,
+ addTokens,
setRpcTarget: setRpcTarget,
setDefaultRpcTarget: setDefaultRpcTarget,
setProviderType: setProviderType,
@@ -700,18 +701,40 @@ function showAddTokenPage () {
function addToken (address, symbol, decimals) {
return (dispatch) => {
dispatch(actions.showLoadingIndication())
- background.addToken(address, symbol, decimals, (err) => {
- dispatch(actions.hideLoadingIndication())
- if (err) {
- return dispatch(actions.displayWarning(err.message))
- }
- setTimeout(() => {
- dispatch(actions.goHome())
- }, 250)
+ return new Promise((resolve, reject) => {
+ background.addToken(address, symbol, decimals, (err) => {
+ dispatch(actions.hideLoadingIndication())
+ if (err) {
+ dispatch(actions.displayWarning(err.message))
+ reject(err)
+ }
+ resolve()
+ // setTimeout(() => {
+ // dispatch(actions.goHome())
+ // }, 250)
+ })
})
}
}
+function addTokens (tokens) {
+ return dispatch => {
+ if (Array.isArray(tokens)) {
+ return Promise.all(tokens.map(({ address, symbol, decimals }) => (
+ dispatch(addToken(address, symbol, decimals))
+ )))
+ } else {
+ return Promise.all(
+ Object
+ .entries(tokens)
+ .map(([_, { address, symbol, decimals }]) => (
+ dispatch(addToken(address, symbol, decimals))
+ ))
+ )
+ }
+ }
+}
+
function goBackToInitView () {
return {
type: actions.BACK_TO_INIT_MENU,
diff --git a/ui/app/add-token.js b/ui/app/add-token.js
index 622cf2bc2..f723ff07c 100644
--- a/ui/app/add-token.js
+++ b/ui/app/add-token.js
@@ -5,6 +5,8 @@ const h = require('react-hyperscript')
const connect = require('react-redux').connect
const Fuse = require('fuse.js')
const contractMap = require('eth-contract-metadata')
+const TokenBalance = require('./components/token-balance')
+const Identicon = require('./components/identicon')
const contractList = Object.entries(contractMap).map(([ _, tokenData]) => tokenData)
const fuse = new Fuse(contractList, {
shouldSort: true,
@@ -16,9 +18,6 @@ const fuse = new Fuse(contractList, {
keys: ['address', 'name', 'symbol'],
})
const actions = require('./actions')
-// const Tooltip = require('./components/tooltip.js')
-
-
const ethUtil = require('ethereumjs-util')
const abi = require('human-standard-token-abi')
const Eth = require('ethjs-query')
@@ -37,86 +36,193 @@ function mapStateToProps (state) {
function mapDispatchToProps (dispatch) {
return {
goHome: () => dispatch(actions.goHome()),
+ addTokens: tokens => dispatch(actions.addTokens(tokens)),
}
}
inherits(AddTokenScreen, Component)
function AddTokenScreen () {
this.state = {
- // warning: null,
- // address: null,
- // symbol: 'TOKEN',
- // decimals: 18,
+ isShowingConfirmation: false,
customAddress: '',
customSymbol: '',
customDecimals: 0,
searchQuery: '',
isCollapsed: true,
- selectedToken: {},
+ selectedTokens: {},
+ errors: {},
}
this.tokenAddressDidChange = this.tokenAddressDidChange.bind(this)
+ this.onNext = this.onNext.bind(this)
Component.call(this)
}
-AddTokenScreen.prototype.toggleToken = function (symbol) {
- const { selectedToken } = this.state
- const { [symbol]: isSelected } = selectedToken
+AddTokenScreen.prototype.componentWillMount = function () {
+ if (typeof global.ethereumProvider === 'undefined') return
+
+ this.eth = new Eth(global.ethereumProvider)
+ this.contract = new EthContract(this.eth)
+ this.TokenContract = this.contract(abi)
+}
+
+AddTokenScreen.prototype.toggleToken = function (address, token) {
+ const { selectedTokens, errors } = this.state
+ const { [address]: selectedToken } = selectedTokens
this.setState({
- selectedToken: {
- ...selectedToken,
- [symbol]: !isSelected,
+ selectedTokens: {
+ ...selectedTokens,
+ [address]: selectedToken ? null : token,
+ },
+ errors: {
+ ...errors,
+ tokenSelector: null,
},
})
}
+AddTokenScreen.prototype.onNext = function () {
+ const { isValid, errors } = this.validate()
+
+ return !isValid
+ ? this.setState({ errors })
+ : this.setState({ isShowingConfirmation: true })
+}
+
+AddTokenScreen.prototype.tokenAddressDidChange = function (e) {
+ const customAddress = e.target.value.trim()
+ this.setState({ customAddress })
+ if (ethUtil.isValidAddress(customAddress) && customAddress !== emptyAddr) {
+ this.attemptToAutoFillTokenParams(customAddress)
+ } else {
+ this.setState({
+ customSymbol: '',
+ customDecimals: 0,
+ })
+ }
+}
+
+AddTokenScreen.prototype.validate = function () {
+ const errors = {}
+ const identitiesList = Object.keys(this.props.identities)
+ const { customAddress, customSymbol, customDecimals, selectedTokens } = this.state
+ const standardAddress = ethUtil.addHexPrefix(customAddress).toLowerCase()
+
+ if (customAddress) {
+ const validAddress = ethUtil.isValidAddress(customAddress)
+ if (!validAddress) {
+ errors.customAddress = 'Address is invalid. '
+ }
+
+ const validDecimals = customDecimals >= 0 && customDecimals < 36
+ if (!validDecimals) {
+ errors.customDecimals = 'Decimals must be at least 0, and not over 36.'
+ }
+
+ const symbolLen = customSymbol.trim().length
+ const validSymbol = symbolLen > 0 && symbolLen < 10
+ if (!validSymbol) {
+ errors.customSymbol = 'Symbol must be between 0 and 10 characters.'
+ }
+
+ const ownAddress = identitiesList.includes(standardAddress)
+ if (ownAddress) {
+ errors.customAddress = 'Personal address detected. Input the token contract address.'
+ }
+ } else if (
+ Object.entries(selectedTokens)
+ .reduce((isEmpty, [ symbol, isSelected ]) => (
+ isEmpty && !isSelected
+ ), true)
+ ) {
+ errors.tokenSelector = 'Must select at least 1 token.'
+ }
+
+ return {
+ isValid: !Object.keys(errors).length,
+ errors,
+ }
+}
+
+AddTokenScreen.prototype.attemptToAutoFillTokenParams = async function (address) {
+ const contract = this.TokenContract.at(address)
+
+ const results = await Promise.all([
+ contract.symbol(),
+ contract.decimals(),
+ ])
+
+ const [ symbol, decimals ] = results
+ if (symbol && decimals) {
+ this.setState({
+ customSymbol: symbol[0],
+ customDecimals: decimals[0].toString(),
+ })
+ }
+}
+
AddTokenScreen.prototype.renderCustomForm = function () {
- const { customAddress, customSymbol, customDecimals } = this.state
+ const { customAddress, customSymbol, customDecimals, errors } = this.state
return !this.state.isCollapsed && (
h('div.add-token__add-custom-form', [
- h('div.add-token__add-custom-field', [
+ h('div', {
+ className: classnames('add-token__add-custom-field', {
+ 'add-token__add-custom-field--error': errors.customAddress,
+ }),
+ }, [
h('div.add-token__add-custom-label', 'Token Address'),
h('input.add-token__add-custom-input', {
type: 'text',
onChange: this.tokenAddressDidChange,
value: customAddress,
}),
+ h('div.add-token__add-custom-error-message', errors.customAddress),
]),
- h('div.add-token__add-custom-field', [
+ h('div', {
+ className: classnames('add-token__add-custom-field', {
+ 'add-token__add-custom-field--error': errors.customSymbol,
+ }),
+ }, [
h('div.add-token__add-custom-label', 'Token Symbol'),
h('input.add-token__add-custom-input', {
type: 'text',
value: customSymbol,
disabled: true,
}),
+ h('div.add-token__add-custom-error-message', errors.customSymbol),
]),
- h('div.add-token__add-custom-field', [
+ h('div', {
+ className: classnames('add-token__add-custom-field', {
+ 'add-token__add-custom-field--error': errors.customDecimals,
+ }),
+ }, [
h('div.add-token__add-custom-label', 'Decimals of Precision'),
h('input.add-token__add-custom-input', {
type: 'number',
value: customDecimals,
disabled: true,
}),
+ h('div.add-token__add-custom-error-message', errors.customDecimals),
]),
])
)
}
AddTokenScreen.prototype.renderTokenList = function () {
- const { searchQuery = '', selectedToken } = this.state
+ const { searchQuery = '', selectedTokens } = this.state
const results = searchQuery
? fuse.search(searchQuery) || []
: contractList
return Array(6).fill(undefined)
.map((_, i) => {
- const { logo, symbol, name } = results[i] || {}
+ const { logo, symbol, name, address } = results[i] || {}
return Boolean(logo || symbol || name) && (
h('div.add-token__token-wrapper', {
className: classnames('add-token__token-wrapper', {
- 'add-token__token-wrapper--selected': selectedToken[symbol],
+ 'add-token__token-wrapper--selected': selectedTokens[address],
}),
- onClick: () => this.toggleToken(symbol),
+ onClick: () => this.toggleToken(address, results[i]),
}, [
h('div.add-token__token-icon', {
style: {
@@ -132,11 +238,69 @@ AddTokenScreen.prototype.renderTokenList = function () {
})
}
+AddTokenScreen.prototype.renderConfirmation = function () {
+ const {
+ customAddress: address,
+ customSymbol: symbol,
+ customDecimals: decimals,
+ selectedTokens,
+ } = this.state
+
+ const { addTokens, goHome } = this.props
+
+ const customToken = {
+ address,
+ symbol,
+ decimals,
+ }
+
+ const tokens = address && symbol && decimals
+ ? { ...selectedTokens, [address]: customToken }
+ : selectedTokens
+
+ return (
+ h('div.add-token', [
+ h('div.add-token__wrapper', [
+ h('div.add-token__title-container.add-token__confirmation-title', [
+ h('div.add-token__title', 'Add Token'),
+ h('div.add-token__description', 'Would you like to add these tokens?'),
+ ]),
+ h('div.add-token__content-container.add-token__confirmation-content', [
+ h('div.add-token__description.add-token__confirmation-description', 'Your balances'),
+ h('div.add-token__confirmation-token-list',
+ Object.entries(tokens)
+ .map(([ address, token ]) => (
+ h('span.add-token__confirmation-token-list-item', [
+ h(Identicon, {
+ className: 'add-token__confirmation-token-icon',
+ diameter: 75,
+ address,
+ }),
+ h(TokenBalance, { token }),
+ ])
+ ))
+ ),
+ ]),
+ ]),
+ h('div.add-token__buttons', [
+ h('button.btn-secondary', {
+ onClick: () => addTokens(tokens).then(goHome),
+ }, 'Add Tokens'),
+ h('button.btn-tertiary', {
+ onClick: () => this.setState({ isShowingConfirmation: false }),
+ }, 'Back'),
+ ]),
+ ])
+ )
+}
+
AddTokenScreen.prototype.render = function () {
- const { isCollapsed } = this.state
+ const { isCollapsed, errors, isShowingConfirmation } = this.state
const { goHome } = this.props
- return (
+ return isShowingConfirmation
+ ? this.renderConfirmation()
+ : (
h('div.add-token', [
h('div.add-token__wrapper', [
h('div.add-token__title-container', [
@@ -151,6 +315,7 @@ AddTokenScreen.prototype.render = function () {
placeholder: 'Search',
onChange: e => this.setState({ searchQuery: e.target.value }),
}),
+ h('div.add-token__search-input-error-message', errors.tokenSelector),
]),
h(
'div.add-token__token-icons-container',
@@ -165,7 +330,9 @@ AddTokenScreen.prototype.render = function () {
]),
]),
h('div.add-token__buttons', [
- h('button.btn-secondary', 'Next'),
+ h('button.btn-secondary', {
+ onClick: this.onNext,
+ }, 'Next'),
h('button.btn-tertiary', {
onClick: goHome,
}, 'Cancel'),
@@ -173,214 +340,3 @@ AddTokenScreen.prototype.render = function () {
])
)
}
-
-// AddTokenScreen.prototype.render = function () {
-// const state = this.state
-// const props = this.props
-// const { warning, symbol, decimals } = state
-
-// return (
-// h('.flex-column.flex-grow', [
-
-// // subtitle and nav
-// h('.section-title.flex-row.flex-center', [
-// h('i.fa.fa-arrow-left.fa-lg.cursor-pointer', {
-// onClick: (event) => {
-// props.dispatch(actions.goHome())
-// },
-// }),
-// h('h2.page-subtitle', 'Add Token'),
-// ]),
-
-// h('.error', {
-// style: {
-// display: warning ? 'block' : 'none',
-// padding: '0 20px',
-// textAlign: 'center',
-// },
-// }, warning),
-
-// // conf view
-// h('.flex-column.flex-justify-center.flex-grow.select-none', [
-// h('.flex-space-around', {
-// style: {
-// padding: '20px',
-// },
-// }, [
-
-// h('div', [
-// h(Tooltip, {
-// position: 'top',
-// title: 'The contract of the actual token contract. Click for more info.',
-// }, [
-// h('a', {
-// style: { fontWeight: 'bold', paddingRight: '10px'},
-// href: 'https://consensyssupport.happyfox.com/staff/kb/article/24-what-is-a-token-contract-address',
-// target: '_blank',
-// }, [
-// h('span', 'Token Contract Address '),
-// h('i.fa.fa-question-circle'),
-// ]),
-// ]),
-// ]),
-
-// h('section.flex-row.flex-center', [
-// h('input#token-address', {
-// name: 'address',
-// placeholder: 'Token Contract Address',
-// onChange: this.tokenAddressDidChange.bind(this),
-// style: {
-// width: 'inherit',
-// flex: '1 0 auto',
-// height: '30px',
-// margin: '8px',
-// },
-// }),
-// ]),
-
-// h('div', [
-// h('span', {
-// style: { fontWeight: 'bold', paddingRight: '10px'},
-// }, 'Token Symbol'),
-// ]),
-
-// h('div', { style: {display: 'flex'} }, [
-// h('input#token_symbol', {
-// placeholder: `Like "ETH"`,
-// value: symbol,
-// style: {
-// width: 'inherit',
-// flex: '1 0 auto',
-// height: '30px',
-// margin: '8px',
-// },
-// onChange: (event) => {
-// var element = event.target
-// var symbol = element.value
-// this.setState({ symbol })
-// },
-// }),
-// ]),
-
-// h('div', [
-// h('span', {
-// style: { fontWeight: 'bold', paddingRight: '10px'},
-// }, 'Decimals of Precision'),
-// ]),
-
-// h('div', { style: {display: 'flex'} }, [
-// h('input#token_decimals', {
-// value: decimals,
-// type: 'number',
-// min: 0,
-// max: 36,
-// style: {
-// width: 'inherit',
-// flex: '1 0 auto',
-// height: '30px',
-// margin: '8px',
-// },
-// onChange: (event) => {
-// var element = event.target
-// var decimals = element.value.trim()
-// this.setState({ decimals })
-// },
-// }),
-// ]),
-
-// h('button', {
-// style: {
-// alignSelf: 'center',
-// },
-// onClick: (event) => {
-// const valid = this.validateInputs()
-// if (!valid) return
-
-// const { address, symbol, decimals } = this.state
-// this.props.dispatch(actions.addToken(address.trim(), symbol.trim(), decimals))
-// },
-// }, 'Add'),
-// ]),
-// ]),
-// ])
-// )
-// }
-
-AddTokenScreen.prototype.componentWillMount = function () {
- if (typeof global.ethereumProvider === 'undefined') return
-
- this.eth = new Eth(global.ethereumProvider)
- this.contract = new EthContract(this.eth)
- this.TokenContract = this.contract(abi)
-}
-
-AddTokenScreen.prototype.tokenAddressDidChange = function (e) {
- const customAddress = e.target.value.trim()
- this.setState({ customAddress })
- if (ethUtil.isValidAddress(customAddress) && customAddress !== emptyAddr) {
- this.attemptToAutoFillTokenParams(customAddress)
- } else {
- this.setState({
- customSymbol: '',
- customDecimals: 0,
- })
- }
-}
-
-AddTokenScreen.prototype.validateInputs = function () {
- let msg = ''
- const state = this.state
- const identitiesList = Object.keys(this.props.identities)
- const { address, symbol, decimals } = state
- const standardAddress = ethUtil.addHexPrefix(address).toLowerCase()
-
- const validAddress = ethUtil.isValidAddress(address)
- if (!validAddress) {
- msg += 'Address is invalid. '
- }
-
- const validDecimals = decimals >= 0 && decimals < 36
- if (!validDecimals) {
- msg += 'Decimals must be at least 0, and not over 36. '
- }
-
- const symbolLen = symbol.trim().length
- const validSymbol = symbolLen > 0 && symbolLen < 10
- if (!validSymbol) {
- msg += 'Symbol must be between 0 and 10 characters.'
- }
-
- const ownAddress = identitiesList.includes(standardAddress)
- if (ownAddress) {
- msg = 'Personal address detected. Input the token contract address.'
- }
-
- const isValid = validAddress && validDecimals && !ownAddress
-
- if (!isValid) {
- this.setState({
- warning: msg,
- })
- } else {
- this.setState({ warning: null })
- }
-
- return isValid
-}
-
-AddTokenScreen.prototype.attemptToAutoFillTokenParams = async function (address) {
- const contract = this.TokenContract.at(address)
-
- const results = await Promise.all([
- contract.symbol(),
- contract.decimals(),
- ])
-
- const [ symbol, decimals ] = results
- if (symbol && decimals) {
- this.setState({
- customSymbol: symbol[0],
- customDecimals: decimals[0].toString(),
- })
- }
-}
diff --git a/ui/app/components/token-balance.js b/ui/app/components/token-balance.js
index 3a923eb9d..0342c1da9 100644
--- a/ui/app/components/token-balance.js
+++ b/ui/app/components/token-balance.js
@@ -17,7 +17,8 @@ module.exports = connect(mapStateToProps)(TokenBalance)
inherits(TokenBalance, Component)
function TokenBalance () {
this.state = {
- balance: '',
+ string: '',
+ symbol: '',
isLoading: true,
error: null,
}
@@ -26,11 +27,14 @@ function TokenBalance () {
TokenBalance.prototype.render = function () {
const state = this.state
- const { balance, isLoading } = state
+ const { symbol, string, balanceOnly, isLoading } = state
return isLoading
? h('span', '')
- : h('span', balance)
+ : h('span.token-balance', [
+ h('span.token-balance__amount', string),
+ !balanceOnly && h('span.token-balance__symbol', symbol),
+ ])
}
TokenBalance.prototype.componentDidMount = function () {
@@ -93,10 +97,10 @@ TokenBalance.prototype.componentDidUpdate = function (nextProps) {
TokenBalance.prototype.updateBalance = function (tokens = []) {
const [{ string, symbol }] = tokens
- const { balanceOnly } = this.props
this.setState({
- balance: balanceOnly ? string : `${string} ${symbol}`,
+ string,
+ symbol,
isLoading: false,
})
}
diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js
index 7a147e942..f817d03a9 100644
--- a/ui/app/components/tx-list.js
+++ b/ui/app/components/tx-list.js
@@ -77,7 +77,7 @@ TxList.prototype.renderTransactionListItem = function (transaction, conversionRa
const { showConfTxPage } = this.props
const opts = {
- key: transActionId,
+ key: transActionId || transactionHash,
txParams: transaction.txParams,
transactionStatus,
transActionId,
diff --git a/ui/app/css/itcss/components/add-token.scss b/ui/app/css/itcss/components/add-token.scss
index ebfdf7b11..d5d1aab71 100644
--- a/ui/app/css/itcss/components/add-token.scss
+++ b/ui/app/css/itcss/components/add-token.scss
@@ -56,6 +56,10 @@
margin-top: 24px;
}
+ &__confirmation-description {
+ margin: 12px 0;
+ }
+
&__content-container {
width: 100%;
border-bottom: 1px solid $gallery;
@@ -65,6 +69,18 @@
padding: 11px 0;
width: 263px;
margin: 0 auto;
+ position: relative;
+ }
+
+ &__search-input-error-message {
+ position: absolute;
+ bottom: -10px;
+ font-size: 12px;
+ width: 100%;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+ color: $red;
}
&__input {
@@ -89,9 +105,13 @@
font-size: 18px;
line-height: 24px;
text-align: center;
- padding: 11px 0 19px;
+ padding: 12px 0;
font-weight: 600;
cursor: pointer;
+
+ &:hover {
+ background-color: $gallery;
+ }
}
&__add-custom-form {
@@ -103,6 +123,24 @@
&__add-custom-field {
width: 290px;
margin: 0 auto;
+ position: relative;
+
+ &--error {
+ .add-token__add-custom-input {
+ border-color: $red;
+ }
+ }
+ }
+
+ &__add-custom-error-message {
+ position: absolute;
+ bottom: -21px;
+ font-size: 12px;
+ width: 100%;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+ color: $red;
}
&__add-custom-label {
@@ -152,9 +190,12 @@
cursor: pointer;
border: 2px solid transparent;
- &:hover,
+ &:hover {
+ border: 2px solid rgba($malibu-blue, .5);
+ }
+
&--selected {
- border: 2px solid $malibu-blue;
+ border: 2px solid $malibu-blue !important;
}
}
@@ -181,4 +222,52 @@
margin-right: 12px;
flex: 0 0 auto;
}
+
+ &__confirmation-token-list {
+ display: flex;
+ flex-flow: column nowrap;
+
+ .token-balance {
+ display: flex;
+ flex-flow: row nowrap;
+ align-items: flex-start;
+
+ &__amount {
+ color: $scorpion;
+ font-size: 43px;
+ font-weight: 300;
+ line-height: 43px;
+ margin-right: 8px;
+ }
+
+ &__symbol {
+ color: $scorpion;
+ font-size: 16px;
+ line-height: 24px;
+ }
+ }
+ }
+
+ &__confirmation-title {
+ padding: 30px 120px 12px;
+ }
+
+ &__confirmation-content {
+ padding-bottom: 60px;
+ }
+
+ &__confirmation-token-list-item {
+ display: flex;
+ flex-flow: row nowrap;
+ padding: 0 120px;
+ align-items: center;
+ }
+
+ &__confirmation-token-list-item + &__confirmation-token-list-item {
+ margin-top: 30px;
+ }
+
+ &__confirmation-token-icon {
+ margin-right: 18px;
+ }
}
diff --git a/ui/app/css/itcss/components/buttons.scss b/ui/app/css/itcss/components/buttons.scss
index 0946cdbbb..2c5e6cf57 100644
--- a/ui/app/css/itcss/components/buttons.scss
+++ b/ui/app/css/itcss/components/buttons.scss
@@ -30,8 +30,9 @@ button.btn-clear {
button[disabled],
input[type="submit"][disabled] {
cursor: not-allowed;
- background: rgba(197, 197, 197, 1);
- box-shadow: 0 3px 6px rgba(197, 197, 197, .36);
+ opacity: .5;
+ // background: rgba(197, 197, 197, 1);
+ // box-shadow: 0 3px 6px rgba(197, 197, 197, .36);
}
// button.spaced {
@@ -90,6 +91,11 @@ button.btn-thin {
font-size: 16px;
line-height: 24px;
padding: 16px 42px;
+
+ &[disabled] {
+ background-color: $white !important;
+ opacity: .5;
+ }
}
.btn-tertiary {