From 26370da13d7bed06d59efeba0a4921387b874e06 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 21 May 2018 16:35:49 -0700 Subject: Rewrite balance rows using flex box --- packages/website/ts/components/ui/icon_button.tsx | 63 +++++++++ packages/website/ts/components/ui/token_icon.tsx | 25 ++-- packages/website/ts/components/wallet/wallet.tsx | 163 +++++++--------------- 3 files changed, 129 insertions(+), 122 deletions(-) create mode 100644 packages/website/ts/components/ui/icon_button.tsx (limited to 'packages/website') diff --git a/packages/website/ts/components/ui/icon_button.tsx b/packages/website/ts/components/ui/icon_button.tsx new file mode 100644 index 000000000..2f5172f05 --- /dev/null +++ b/packages/website/ts/components/ui/icon_button.tsx @@ -0,0 +1,63 @@ +import { colors, Styles } from '@0xproject/react-shared'; +import * as _ from 'lodash'; +import * as React from 'react'; + +export interface IconButtonProps { + iconName: string; + labelText?: string; + onClick: () => void; + color?: string; +} +interface IconButtonState { + isHovering: boolean; +} +export class IconButton extends React.Component { + public static defaultProps: Partial = { + onClick: _.noop, + labelText: '', + color: colors.mediumBlue, + }; + public constructor(props: IconButtonProps) { + super(props); + this.state = { + isHovering: false, + }; + } + public render(): React.ReactNode { + const styles: Styles = { + root: { + cursor: 'pointer', + opacity: this.state.isHovering ? 0.5 : 1, + }, + icon: { + color: this.props.color, + fontSize: 20, + }, + label: { + color: this.props.color, + fontSize: 10, + }, + }; + return ( +
+ + {!_.isEmpty(this.props.labelText) && ( +
+ {this.props.labelText} +
+ )} +
+ ); + } + private _onToggleHover(isHovering: boolean): void { + this.setState({ + isHovering, + }); + } +} diff --git a/packages/website/ts/components/ui/token_icon.tsx b/packages/website/ts/components/ui/token_icon.tsx index a9ad567ef..0875cc56b 100644 --- a/packages/website/ts/components/ui/token_icon.tsx +++ b/packages/website/ts/components/ui/token_icon.tsx @@ -6,6 +6,7 @@ import { Token } from 'ts/types'; interface TokenIconProps { token: Token; diameter: number; + link?: string; } interface TokenIconState {} @@ -14,14 +15,20 @@ export class TokenIcon extends React.Component { public render(): React.ReactNode { const token = this.props.token; const diameter = this.props.diameter; - return ( -
- {token.isRegistered && !_.isUndefined(token.iconUrl) ? ( - - ) : ( - - )} -
- ); + const icon = + token.isRegistered && !_.isUndefined(token.iconUrl) ? ( + + ) : ( + + ); + if (_.isEmpty(this.props.link)) { + return icon; + } else { + return ( + + {icon} + + ); + } } } diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index dab8b7d2f..276a94fdb 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -9,7 +9,7 @@ import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; import FlatButton from 'material-ui/FlatButton'; import FloatingActionButton from 'material-ui/FloatingActionButton'; -import { List, ListItem } from 'material-ui/List'; +import { ListItem } from 'material-ui/List'; import ActionAccountBalanceWallet from 'material-ui/svg-icons/action/account-balance-wallet'; import ContentAdd from 'material-ui/svg-icons/content/add'; import ContentRemove from 'material-ui/svg-icons/content/remove'; @@ -23,6 +23,7 @@ import firstBy = require('thenby'); import { Blockchain } from 'ts/blockchain'; import { AllowanceToggle } from 'ts/components/inputs/allowance_toggle'; +import { IconButton } from 'ts/components/ui/icon_button'; import { Identicon } from 'ts/components/ui/identicon'; import { TokenIcon } from 'ts/components/ui/token_icon'; import { WalletDisconnectedItem } from 'ts/components/wallet/wallet_disconnected_item'; @@ -91,12 +92,6 @@ const styles: Styles = { boxShadow: `0px 4px 6px ${colors.walletBoxShadow}`, overflow: 'hidden', }, - list: { - padding: 0, - }, - tokenItemInnerDiv: { - paddingLeft: 60, - }, headerItemInnerDiv: { paddingLeft: 65, }, @@ -114,23 +109,19 @@ const styles: Styles = { tokenItem: { backgroundColor: colors.walletDefaultItemBackground, }, - wrappedEtherOpenButtonLabel: { - fontSize: 10, - }, amountLabel: { fontWeight: 'bold', color: colors.black, }, + valueLabel: { + color: colors.grey, + fontSize: 14, + }, paddedItem: { paddingTop: 8, paddingBottom: 8, }, - accessoryItemsContainer: { - width: 150, - right: 8, - }, bodyInnerDiv: { - padding: 0, // TODO: make this completely responsive maxHeight: 475, overflow: 'auto', @@ -154,6 +145,7 @@ const FOOTER_ITEM_KEY = 'FOOTER'; const DISCONNECTED_ITEM_KEY = 'DISCONNECTED'; const ETHER_ITEM_KEY = 'ETHER'; const USD_DECIMAL_PLACES = 2; +const NO_ALLOWANCE_TOGGLE_SPACE_WIDTH = 56; export class Wallet extends React.Component { private _isUnmounted: boolean; @@ -204,16 +196,13 @@ export class Wallet extends React.Component { } public render(): React.ReactNode { const isReadyToRender = this.props.blockchainIsLoaded && this.props.blockchainErr === BlockchainErrs.NoError; - return
{isReadyToRender && this._renderRows()}
; - } - private _renderRows(): React.ReactNode { const isAddressAvailable = !_.isEmpty(this.props.userAddress); return ( - - {isAddressAvailable +
+ {isReadyToRender && isAddressAvailable ? _.concat(this._renderConnectedHeaderRows(), this._renderBody(), this._renderFooterRows()) : _.concat(this._renderDisconnectedHeaderRows(), this._renderDisconnectedRows())} - +
); } private _renderDisconnectedHeaderRows(): React.ReactElement<{}> { @@ -259,15 +248,15 @@ export class Wallet extends React.Component { overflow: this.state.isHoveringSidebar ? 'auto' : 'hidden', }; return ( - {this._renderEthRows()} {this._renderTokenRows()} - + ); } private _onSidebarHover(event: React.FormEvent): void { @@ -329,6 +318,7 @@ export class Wallet extends React.Component { ); } private _renderEthRows(): React.ReactNode { + const icon = ; const primaryText = this._renderAmount( this.props.userEtherBalanceInWei, constants.DECIMAL_PLACES_ETH, @@ -350,33 +340,7 @@ export class Wallet extends React.Component { const style = isInWrappedEtherState ? { ...walletItemStyles.focusedItem, ...styles.paddedItem } : { ...styles.tokenItem, ...styles.borderedItem, ...styles.paddedItem }; - return ( -
- } - rightAvatar={this._renderAccessoryItems(accessoryItemConfig)} - disableTouchRipple={true} - style={style} - innerDivStyle={styles.tokenItemInnerDiv} - /> - {isInWrappedEtherState && ( - - )} -
- ); + return this._renderBalanceRow(icon, primaryText, secondaryText, accessoryItemConfig); } private _renderTokenRows(): React.ReactNode { const trackedTokens = this.props.trackedTokens; @@ -394,6 +358,7 @@ export class Wallet extends React.Component { this.props.networkId, EtherscanLinkSuffixes.Address, ); + const icon = ; const primaryText = this._renderAmount(tokenState.balance, token.decimals, token.symbol); const secondaryText = this._renderValue(tokenState.balance, token.decimals, tokenState.price); const wrappedEtherDirection = token.symbol === ETHER_TOKEN_SYMBOL ? Side.Receive : undefined; @@ -404,56 +369,48 @@ export class Wallet extends React.Component { tokenState, }, }; - // if this is the last item in the list, do not render the border, it is rendered by the footer - const borderedStyle = index !== this.props.trackedTokens.length - 1 ? styles.borderedItem : {}; + return this._renderBalanceRow(icon, primaryText, secondaryText, accessoryItemConfig); + } + private _renderBalanceRow( + icon: React.ReactNode, + primaryText: React.ReactNode, + secondaryText: React.ReactNode, + accessoryItemConfig: AccessoryItemConfig, + ): React.ReactNode { const shouldShowWrapEtherItem = !_.isUndefined(this.state.wrappedEtherDirection) && this.state.wrappedEtherDirection === accessoryItemConfig.wrappedEtherDirection; const style = shouldShowWrapEtherItem ? { ...walletItemStyles.focusedItem, ...styles.paddedItem } - : { ...styles.tokenItem, ...borderedStyle, ...styles.paddedItem }; - const etherToken = this._getEthToken(); + : { ...styles.tokenItem, ...styles.borderedItem, ...styles.paddedItem }; return ( -
- - {shouldShowWrapEtherItem && ( - - )} +
+
{icon}
+
+ {primaryText} + {secondaryText} +
+
+
{this._renderAccessoryItems(accessoryItemConfig)}
); } private _renderAccessoryItems(config: AccessoryItemConfig): React.ReactElement<{}> { const shouldShowWrappedEtherAction = !_.isUndefined(config.wrappedEtherDirection); const shouldShowToggle = !_.isUndefined(config.allowanceToggleConfig); + // if we don't have a toggle, we still want some space to the right of the "wrap" button so that it aligns with + // the "unwrap" button in the row below + const toggle = shouldShowToggle ? ( + this._renderAllowanceToggle(config.allowanceToggleConfig) + ) : ( +
+ ); return ( -
-
-
- {shouldShowWrappedEtherAction && this._renderWrappedEtherButton(config.wrappedEtherDirection)} -
-
- {shouldShowToggle && this._renderAllowanceToggle(config.allowanceToggleConfig)} -
+
+
+ {shouldShowWrappedEtherAction && this._renderWrappedEtherButton(config.wrappedEtherDirection)}
+
{toggle}
); } @@ -486,37 +443,24 @@ export class Wallet extends React.Component { const value = unitAmount.mul(price); const formattedAmount = value.toFixed(USD_DECIMAL_PLACES); const result = `$${formattedAmount}`; - return result; - } - private _renderTokenIcon(token: Token, tokenLink?: string): React.ReactElement<{}> { - const tooltipId = `tooltip-${token.address}`; - const tokenIcon = ; - if (_.isUndefined(tokenLink)) { - return tokenIcon; - } else { - return ( - - {tokenIcon} - - ); - } + return
{result}
; } private _renderWrappedEtherButton(wrappedEtherDirection: Side): React.ReactNode { const isWrappedEtherDirectionOpen = this.state.wrappedEtherDirection === wrappedEtherDirection; let buttonLabel; - let buttonIcon; + let buttonIconName; if (isWrappedEtherDirectionOpen) { buttonLabel = 'cancel'; - buttonIcon = ; + buttonIconName = 'zmdi-close'; } else { switch (wrappedEtherDirection) { case Side.Deposit: buttonLabel = 'wrap'; - buttonIcon = ; + buttonIconName = 'zmdi-long-arrow-down'; break; case Side.Receive: buttonLabel = 'unwrap'; - buttonIcon = ; + buttonIconName = 'zmdi-long-arrow-up'; break; default: throw utils.spawnSwitchErr('wrappedEtherDirection', wrappedEtherDirection); @@ -526,14 +470,7 @@ export class Wallet extends React.Component { ? this._closeWrappedEtherActionRow.bind(this) : this._openWrappedEtherActionRow.bind(this, wrappedEtherDirection); return ( - + ); } private _getInitialTrackedTokenStateByAddress(tokenAddresses: string[]): TokenStateByAddress { -- cgit v1.2.3 From ed8acdb11c349bd92ee89cf9c8c9921df185b67c Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 21 May 2018 16:43:55 -0700 Subject: Re add wrapped ether item --- packages/website/ts/components/wallet/wallet.tsx | 31 ++++++++++++++++++------ 1 file changed, 24 insertions(+), 7 deletions(-) (limited to 'packages/website') diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index 276a94fdb..09d094a16 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -383,15 +383,32 @@ export class Wallet extends React.Component { const style = shouldShowWrapEtherItem ? { ...walletItemStyles.focusedItem, ...styles.paddedItem } : { ...styles.tokenItem, ...styles.borderedItem, ...styles.paddedItem }; + const etherToken = this._getEthToken(); return ( -
-
{icon}
-
- {primaryText} - {secondaryText} +
+
+
{icon}
+
+ {primaryText} + {secondaryText} +
+
+
{this._renderAccessoryItems(accessoryItemConfig)}
-
-
{this._renderAccessoryItems(accessoryItemConfig)}
+ {shouldShowWrapEtherItem && ( + + )}
); } -- cgit v1.2.3 From 130e83d9b27cb541cf4f07b3d75fcfeea076df41 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Mon, 21 May 2018 21:15:41 -0700 Subject: Use flexbox for wrapped ether item --- .../ts/components/wallet/wrap_ether_item.tsx | 50 +++++++++++++--------- 1 file changed, 29 insertions(+), 21 deletions(-) (limited to 'packages/website') diff --git a/packages/website/ts/components/wallet/wrap_ether_item.tsx b/packages/website/ts/components/wallet/wrap_ether_item.tsx index 98b28b3ad..aab1d4439 100644 --- a/packages/website/ts/components/wallet/wrap_ether_item.tsx +++ b/packages/website/ts/components/wallet/wrap_ether_item.tsx @@ -37,7 +37,10 @@ interface WrapEtherItemState { } const styles: Styles = { - topLabel: { color: colors.black, fontSize: 11 }, + topLabel: { + color: colors.black, + fontSize: 11, + }, inputContainer: { backgroundColor: colors.white, borderBottomRightRadius: 3, @@ -45,9 +48,10 @@ const styles: Styles = { borderTopRightRadius: 3, borderTopLeftRadius: 3, padding: 4, - width: 125, }, - amountInput: { height: 34 }, + amountInput: { + height: 34, + }, amountInputLabel: { paddingTop: 10, paddingRight: 10, @@ -58,8 +62,6 @@ const styles: Styles = { amountInputHint: { bottom: 18, }, - innerDiv: { paddingLeft: 60, paddingTop: 0, paddingBottom: 10 }, - wrapEtherConfirmationButtonContainer: { width: 128, top: 19 }, wrapEtherConfirmationButtonLabel: { fontSize: 12, color: colors.white, @@ -70,6 +72,12 @@ const styles: Styles = { color: colors.red, minHeight: 20, }, + conversionSpinner: { + paddingTop: 26, + }, + conversionSpinnerPlaceholder: { + width: 61, + }, }; export class WrapEtherItem extends React.Component { @@ -85,11 +93,13 @@ export class WrapEtherItem extends React.Component -
{topLabelText}
+
+
{this._renderIsEthConversionHappeningSpinner()}
+
+
{topLabelText}
+
{isWrappingEth ? ( )}
- {this._renderErrorMsg()} +
{this._renderWrapEtherConfirmationButton()}
- } - secondaryTextLines={2} - disableTouchRipple={true} - style={walletItemStyles.focusedItem} - innerDivStyle={styles.innerDiv} - leftIcon={this._renderIsEthConversionHappeningSpinner()} - rightAvatar={this._renderWrapEtherConfirmationButton()} - /> + + {this._renderErrorMsg()} +
+
); } private _onValueChange(isValid: boolean, amount?: BigNumber): void { @@ -152,16 +158,18 @@ export class WrapEtherItem extends React.Component { return this.state.isEthConversionHappening ? ( -
+
- ) : null; + ) : ( +
+ ); } private _renderWrapEtherConfirmationButton(): React.ReactElement<{}> { const isWrappingEth = this.props.direction === Side.Deposit; const labelText = isWrappingEth ? 'wrap' : 'unwrap'; return ( -
+
Date: Mon, 21 May 2018 21:41:03 -0700 Subject: Add missing key --- packages/website/ts/components/wallet/wallet.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'packages/website') diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index 09d094a16..113f3c864 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -340,7 +340,8 @@ export class Wallet extends React.Component { const style = isInWrappedEtherState ? { ...walletItemStyles.focusedItem, ...styles.paddedItem } : { ...styles.tokenItem, ...styles.borderedItem, ...styles.paddedItem }; - return this._renderBalanceRow(icon, primaryText, secondaryText, accessoryItemConfig); + const key = ETHER_ITEM_KEY; + return this._renderBalanceRow(key, icon, primaryText, secondaryText, accessoryItemConfig); } private _renderTokenRows(): React.ReactNode { const trackedTokens = this.props.trackedTokens; @@ -369,9 +370,11 @@ export class Wallet extends React.Component { tokenState, }, }; - return this._renderBalanceRow(icon, primaryText, secondaryText, accessoryItemConfig); + const key = token.address; + return this._renderBalanceRow(key, icon, primaryText, secondaryText, accessoryItemConfig); } private _renderBalanceRow( + key: string, icon: React.ReactNode, primaryText: React.ReactNode, secondaryText: React.ReactNode, @@ -385,7 +388,7 @@ export class Wallet extends React.Component { : { ...styles.tokenItem, ...styles.borderedItem, ...styles.paddedItem }; const etherToken = this._getEthToken(); return ( -
+
{icon}
-- cgit v1.2.3 From 0801457ff02ac1ab16693be8bfb049fe3c284253 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Wed, 23 May 2018 15:28:51 -0700 Subject: Use visibility property instead of placeholder div in wrap ether item --- packages/website/ts/components/wallet/wrap_ether_item.tsx | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'packages/website') diff --git a/packages/website/ts/components/wallet/wrap_ether_item.tsx b/packages/website/ts/components/wallet/wrap_ether_item.tsx index 34b5b8824..1dfcffadf 100644 --- a/packages/website/ts/components/wallet/wrap_ether_item.tsx +++ b/packages/website/ts/components/wallet/wrap_ether_item.tsx @@ -75,9 +75,6 @@ const styles: Styles = { conversionSpinner: { paddingTop: 26, }, - conversionSpinnerPlaceholder: { - width: 61, - }, }; export class WrapEtherItem extends React.Component { @@ -160,12 +157,12 @@ export class WrapEtherItem extends React.Component { - return this.state.isEthConversionHappening ? ( -
+ const visibility = this.state.isEthConversionHappening ? 'visible' : 'hidden'; + const style: React.CSSProperties = { ...styles.conversionSpinner, visibility }; + return ( +
- ) : ( -
); } private _renderWrapEtherConfirmationButton(): React.ReactElement<{}> { -- cgit v1.2.3