diff options
author | Fabio Berger <me@fabioberger.com> | 2018-06-22 16:39:07 +0800 |
---|---|---|
committer | Fabio Berger <me@fabioberger.com> | 2018-06-22 16:39:07 +0800 |
commit | 3ce295a2af17feef6cd4e3140196501805493719 (patch) | |
tree | 964df912ce86d98a211f81f3d6159d797a37c3b3 /packages/website | |
parent | a30107ab867964d371b2d5fc6791c7b1963f1c7b (diff) | |
parent | 0515c6acded983bba05320895ea2c2891f37055c (diff) | |
download | dexon-0x-contracts-3ce295a2af17feef6cd4e3140196501805493719.tar.gz dexon-0x-contracts-3ce295a2af17feef6cd4e3140196501805493719.tar.zst dexon-0x-contracts-3ce295a2af17feef6cd4e3140196501805493719.zip |
Merge branch 'v2-prototype' into refactor/check-revert-reasons
* v2-prototype: (40 commits)
Use make-promises-safe as a preloader instead of manually importing
Updated compiler runs to be 1,000,000
Add event to setSignatureValidatorApproval, rename signer => signerAddress accross all contracts
Add senderAddress to Fill and Cancel logs, add comments to events and types
Fix Island component
Add missing image assets for Chris and Mel
Fix some bugs in sol-cov
Remove unreachable PreSigned check
Fix linting
Buttons look hella disabled now
Remove border radius, fix width issue for unlock step
Add Chris and Mel to about page
fix linter issues
only call getLocationByOffset if source if defined
Set settleOrder and settleMatchedOrders to private
Prevent prettier issue
Support mobile friendly onboarding flows
Removed MixinSettlement. Moved `settleOrder` into `MixinExchangeCore` and `settleMatchedOrders` into `MixinMatchOrders`
Migrations after rebasing
Linter
...
Diffstat (limited to 'packages/website')
21 files changed, 301 insertions, 173 deletions
diff --git a/packages/website/public/images/team/chris.png b/packages/website/public/images/team/chris.png Binary files differnew file mode 100644 index 000000000..242a2813f --- /dev/null +++ b/packages/website/public/images/team/chris.png diff --git a/packages/website/public/images/team/mel.png b/packages/website/public/images/team/mel.png Binary files differnew file mode 100644 index 000000000..52d779ad2 --- /dev/null +++ b/packages/website/public/images/team/mel.png diff --git a/packages/website/ts/components/generate_order/asset_picker.tsx b/packages/website/ts/components/generate_order/asset_picker.tsx index d7cc554c4..b43ac1f2e 100644 --- a/packages/website/ts/components/generate_order/asset_picker.tsx +++ b/packages/website/ts/components/generate_order/asset_picker.tsx @@ -151,12 +151,12 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt height: TILE_DIMENSION, ...tileStyles, }} - className="p2 mx-auto" + className="p2 flex flex-column items-center" onClick={this._onChooseToken.bind(this, address)} onMouseEnter={this._onToggleHover.bind(this, address, true)} onMouseLeave={this._onToggleHover.bind(this, address, false)} > - <div className="p1 center"> + <div className="p1"> <TokenIcon token={token} diameter={TOKEN_ICON_DIMENSION} /> </div> <div className="center">{token.name}</div> diff --git a/packages/website/ts/components/onboarding/onboarding_card.tsx b/packages/website/ts/components/onboarding/onboarding_card.tsx new file mode 100644 index 000000000..bc83b8034 --- /dev/null +++ b/packages/website/ts/components/onboarding/onboarding_card.tsx @@ -0,0 +1,84 @@ +import { colors } from '@0xproject/react-shared'; +import * as React from 'react'; + +import { Button } from 'ts/components/ui/button'; +import { Container } from 'ts/components/ui/container'; +import { IconButton } from 'ts/components/ui/icon_button'; +import { Island } from 'ts/components/ui/island'; +import { Text, Title } from 'ts/components/ui/text'; + +export type ContinueButtonDisplay = 'enabled' | 'disabled'; + +export interface OnboardingCardProps { + title?: string; + content: React.ReactNode; + isLastStep: boolean; + onClose: () => void; + onClickNext: () => void; + onClickBack: () => void; + continueButtonDisplay?: ContinueButtonDisplay; + shouldHideBackButton?: boolean; + shouldHideNextButton?: boolean; + continueButtonText?: string; + borderRadius?: string; +} + +export const OnboardingCard: React.StatelessComponent<OnboardingCardProps> = ({ + title, + content, + continueButtonDisplay, + continueButtonText, + onClickNext, + onClickBack, + onClose, + shouldHideBackButton, + shouldHideNextButton, + borderRadius, +}) => ( + <Island borderRadius={borderRadius}> + <Container paddingRight="30px" paddingLeft="30px" maxWidth={350} paddingTop="15px" paddingBottom="15px"> + <div className="flex flex-column"> + <div className="flex justify-between"> + <Title>{title}</Title> + <Container position="relative" bottom="20px" left="15px"> + <IconButton color={colors.grey} iconName="zmdi-close" onClick={onClose}> + Close + </IconButton> + </Container> + </div> + <Container marginBottom="15px"> + <Text>{content}</Text> + </Container> + {continueButtonDisplay && ( + <Button + isDisabled={continueButtonDisplay === 'disabled'} + onClick={onClickNext} + fontColor={colors.white} + fontSize="15px" + backgroundColor={colors.mediumBlue} + > + {continueButtonText} + </Button> + )} + <Container className="flex justify-between" marginTop="15px"> + {!shouldHideBackButton && ( + <Text fontColor={colors.grey} onClick={onClickBack}> + Back + </Text> + )} + {!shouldHideNextButton && ( + <Text fontColor={colors.grey} onClick={onClickNext}> + Skip + </Text> + )} + </Container> + </div> + </Container> + </Island> +); + +OnboardingCard.defaultProps = { + continueButtonText: 'Continue', +}; + +OnboardingCard.displayName = 'OnboardingCard'; diff --git a/packages/website/ts/components/onboarding/onboarding_flow.tsx b/packages/website/ts/components/onboarding/onboarding_flow.tsx index 34aeace82..331899469 100644 --- a/packages/website/ts/components/onboarding/onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/onboarding_flow.tsx @@ -1,7 +1,9 @@ import * as React from 'react'; import { Placement, Popper, PopperChildrenProps } from 'react-popper'; +import { OnboardingCard } from 'ts/components/onboarding/onboarding_card'; import { ContinueButtonDisplay, OnboardingTooltip } from 'ts/components/onboarding/onboarding_tooltip'; +import { Animation } from 'ts/components/ui/animation'; import { Container } from 'ts/components/ui/container'; import { Overlay } from 'ts/components/ui/overlay'; @@ -22,26 +24,37 @@ export interface OnboardingFlowProps { isRunning: boolean; onClose: () => void; updateOnboardingStep: (stepIndex: number) => void; + disableOverlay?: boolean; + isMobile: boolean; } export class OnboardingFlow extends React.Component<OnboardingFlowProps> { + public static defaultProps = { + disableOverlay: false, + isMobile: false, + }; public render(): React.ReactNode { if (!this.props.isRunning) { return null; } - return ( - <Overlay> + let onboardingElement = null; + if (this.props.isMobile) { + onboardingElement = <Animation type="easeUpFromBottom">{this._renderOnboardignCard()}</Animation>; + } else { + onboardingElement = ( <Popper referenceElement={this._getElementForStep()} placement={this._getCurrentStep().placement}> {this._renderPopperChildren.bind(this)} </Popper> - </Overlay> - ); + ); + } + if (this.props.disableOverlay) { + return onboardingElement; + } + return <Overlay>{onboardingElement}</Overlay>; } - private _getElementForStep(): Element { return document.querySelector(this._getCurrentStep().target); } - private _renderPopperChildren(props: PopperChildrenProps): React.ReactNode { return ( <div ref={props.ref} style={props.style} data-placement={props.placement}> @@ -49,13 +62,12 @@ export class OnboardingFlow extends React.Component<OnboardingFlowProps> { </div> ); } - private _renderToolTip(): React.ReactNode { const { steps, stepIndex } = this.props; const step = steps[stepIndex]; const isLastStep = steps.length - 1 === stepIndex; return ( - <Container marginLeft="30px"> + <Container marginLeft="30px" maxWidth={350}> <OnboardingTooltip title={step.title} content={step.content} @@ -72,10 +84,31 @@ export class OnboardingFlow extends React.Component<OnboardingFlowProps> { ); } + private _renderOnboardignCard(): React.ReactNode { + const { steps, stepIndex } = this.props; + const step = steps[stepIndex]; + const isLastStep = steps.length - 1 === stepIndex; + return ( + <Container position="relative" zIndex={1} maxWidth="100vw"> + <OnboardingCard + title={step.title} + content={step.content} + isLastStep={isLastStep} + shouldHideBackButton={step.shouldHideBackButton} + shouldHideNextButton={step.shouldHideNextButton} + onClose={this.props.onClose} + onClickNext={this._goToNextStep.bind(this)} + onClickBack={this._goToPrevStep.bind(this)} + continueButtonDisplay={step.continueButtonDisplay} + continueButtonText={step.continueButtonText} + borderRadius="10px 10px 0px 0px" + /> + </Container> + ); + } private _getCurrentStep(): Step { return this.props.steps[this.props.stepIndex]; } - private _goToNextStep(): void { const nextStep = this.props.stepIndex + 1; if (nextStep < this.props.steps.length) { @@ -84,7 +117,6 @@ export class OnboardingFlow extends React.Component<OnboardingFlowProps> { this.props.onClose(); } } - private _goToPrevStep(): void { const nextStep = this.props.stepIndex - 1; if (nextStep >= 0) { diff --git a/packages/website/ts/components/onboarding/onboarding_tooltip.tsx b/packages/website/ts/components/onboarding/onboarding_tooltip.tsx index 45851b4de..d8065625d 100644 --- a/packages/website/ts/components/onboarding/onboarding_tooltip.tsx +++ b/packages/website/ts/components/onboarding/onboarding_tooltip.tsx @@ -1,90 +1,25 @@ -import { colors } from '@0xproject/react-shared'; import * as React from 'react'; -import { Button } from 'ts/components/ui/button'; -import { Container } from 'ts/components/ui/container'; -import { IconButton } from 'ts/components/ui/icon_button'; -import { Island } from 'ts/components/ui/island'; +import { OnboardingCard, OnboardingCardProps } from 'ts/components/onboarding/onboarding_card'; import { Pointer, PointerDirection } from 'ts/components/ui/pointer'; -import { Text, Title } from 'ts/components/ui/text'; export type ContinueButtonDisplay = 'enabled' | 'disabled'; -export interface OnboardingTooltipProps { - title?: string; - content: React.ReactNode; - isLastStep: boolean; - onClose: () => void; - onClickNext: () => void; - onClickBack: () => void; - continueButtonDisplay?: ContinueButtonDisplay; - shouldHideBackButton?: boolean; - shouldHideNextButton?: boolean; - pointerDirection?: PointerDirection; - continueButtonText?: string; +export interface OnboardingTooltipProps extends OnboardingCardProps { className?: string; + pointerDirection?: PointerDirection; } -export const OnboardingTooltip: React.StatelessComponent<OnboardingTooltipProps> = ({ - title, - content, - continueButtonDisplay, - continueButtonText, - onClickNext, - onClickBack, - onClose, - shouldHideBackButton, - shouldHideNextButton, - pointerDirection, - className, -}) => ( - <Pointer className={className} direction={pointerDirection}> - <Island> - <Container paddingRight="30px" paddingLeft="30px" maxWidth={350} paddingTop="15px" paddingBottom="15px"> - <div className="flex flex-column"> - <div className="flex justify-between"> - <Title>{title}</Title> - <Container position="relative" bottom="20px" left="15px"> - <IconButton color={colors.grey} iconName="zmdi-close" onClick={onClose}> - Close - </IconButton> - </Container> - </div> - <Container marginBottom="15px"> - <Text>{content}</Text> - </Container> - {continueButtonDisplay && ( - <Button - isDisabled={continueButtonDisplay === 'disabled'} - onClick={onClickNext} - fontColor={colors.white} - fontSize="15px" - backgroundColor={colors.mediumBlue} - > - {continueButtonText} - </Button> - )} - <Container className="flex justify-between" marginTop="15px"> - {!shouldHideBackButton && ( - <Text fontColor={colors.grey} onClick={onClickBack}> - Back - </Text> - )} - {!shouldHideNextButton && ( - <Text fontColor={colors.grey} onClick={onClickNext}> - Skip - </Text> - )} - </Container> - </div> - </Container> - </Island> - </Pointer> -); - +export const OnboardingTooltip: React.StatelessComponent<OnboardingTooltipProps> = props => { + const { pointerDirection, className, ...cardProps } = props; + return ( + <Pointer className={className} direction={pointerDirection}> + <OnboardingCard {...cardProps} /> + </Pointer> + ); +}; OnboardingTooltip.defaultProps = { pointerDirection: 'left', - continueButtonText: 'Continue', }; OnboardingTooltip.displayName = 'OnboardingTooltip'; diff --git a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx index 7e40192f6..10d4af30e 100644 --- a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx @@ -14,7 +14,7 @@ import { SetAllowancesOnboardingStep } from 'ts/components/onboarding/set_allowa import { UnlockWalletOnboardingStep } from 'ts/components/onboarding/unlock_wallet_onboarding_step'; import { WrapEthOnboardingStep } from 'ts/components/onboarding/wrap_eth_onboarding_step'; import { AllowanceToggle } from 'ts/containers/inputs/allowance_toggle'; -import { ProviderType, Token, TokenByAddress, TokenStateByAddress } from 'ts/types'; +import { ProviderType, ScreenWidths, Token, TokenByAddress, TokenStateByAddress } from 'ts/types'; import { analytics } from 'ts/utils/analytics'; import { utils } from 'ts/utils/utils'; @@ -34,6 +34,7 @@ export interface PortalOnboardingFlowProps extends RouteComponentProps<any> { updateIsRunning: (isRunning: boolean) => void; updateOnboardingStep: (stepIndex: number) => void; refetchTokenStateAsync: (tokenAddress: string) => Promise<void>; + screenWidth: ScreenWidths; } class PlainPortalOnboardingFlow extends React.Component<PortalOnboardingFlowProps> { @@ -57,6 +58,8 @@ class PlainPortalOnboardingFlow extends React.Component<PortalOnboardingFlowProp isRunning={this.props.isRunning} onClose={this._closeOnboarding.bind(this)} updateOnboardingStep={this._updateOnboardingStep.bind(this)} + disableOverlay={this.props.screenWidth === ScreenWidths.Sm} + isMobile={this.props.screenWidth === ScreenWidths.Sm} /> ); } diff --git a/packages/website/ts/components/onboarding/unlock_wallet_onboarding_step.tsx b/packages/website/ts/components/onboarding/unlock_wallet_onboarding_step.tsx index 6e6a74a06..0039aa545 100644 --- a/packages/website/ts/components/onboarding/unlock_wallet_onboarding_step.tsx +++ b/packages/website/ts/components/onboarding/unlock_wallet_onboarding_step.tsx @@ -10,7 +10,7 @@ export const UnlockWalletOnboardingStep: React.StatelessComponent<UnlockWalletOn <Container marginTop="15px" marginBottom="15px"> <img src="/images/metamask_icon.png" height="50px" width="50px" /> </Container> - <Text>Unlock your metamask extension to begin.</Text> + <Text center={true}>Unlock your metamask extension to get started.</Text> </div> </div> ); diff --git a/packages/website/ts/components/portal/back_button.tsx b/packages/website/ts/components/portal/back_button.tsx index 2d0bbefc3..ca35abc2b 100644 --- a/packages/website/ts/components/portal/back_button.tsx +++ b/packages/website/ts/components/portal/back_button.tsx @@ -2,6 +2,7 @@ import { Styles } from '@0xproject/react-shared'; import * as React from 'react'; import { Link } from 'react-router-dom'; +import { Island } from 'ts/components/ui/island'; import { colors } from 'ts/style/colors'; export interface BackButtonProps { @@ -15,9 +16,7 @@ const styles: Styles = { backButton: { height: BACK_BUTTON_HEIGHT, paddingTop: 10, - backgroundColor: colors.white, borderRadius: BACK_BUTTON_HEIGHT, - boxShadow: `0px 4px 6px ${colors.walletBoxShadow}`, }, backButtonIcon: { color: colors.mediumBlue, @@ -29,14 +28,14 @@ export const BackButton = (props: BackButtonProps) => { return ( <div style={{ height: 65, paddingTop: 25 }}> <Link to={props.to} style={{ textDecoration: 'none' }}> - <div className="flex right" style={styles.backButton}> + <Island className="flex right" style={styles.backButton}> <div style={{ marginLeft: 12 }}> <i style={styles.backButtonIcon} className={`zmdi zmdi-arrow-left`} /> </div> <div style={{ marginLeft: 12, marginRight: 12 }}> <div style={{ fontSize: 16, color: colors.lightGrey }}>{props.labelText}</div> </div> - </div> + </Island> </Link> </div> ); diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx index 67314678b..11b3b43f4 100644 --- a/packages/website/ts/components/portal/portal.tsx +++ b/packages/website/ts/components/portal/portal.tsx @@ -246,11 +246,6 @@ export class Portal extends React.Component<PortalProps, PortalState> { : TokenVisibility.TRACKED; return ( <div style={styles.root}> - <PortalOnboardingFlow - blockchain={this._blockchain} - trackedTokenStateByAddress={this.state.trackedTokenStateByAddress} - refetchTokenStateAsync={this._refetchTokenStateAsync.bind(this)} - /> <DocumentTitle title="0x Portal DApp" /> <TopBar userAddress={this.props.userAddress} @@ -307,6 +302,11 @@ export class Portal extends React.Component<PortalProps, PortalState> { tokenVisibility={tokenVisibility} /> </div> + <PortalOnboardingFlow + blockchain={this._blockchain} + trackedTokenStateByAddress={this.state.trackedTokenStateByAddress} + refetchTokenStateAsync={this._refetchTokenStateAsync.bind(this)} + /> </div> ); } @@ -340,62 +340,77 @@ export class Portal extends React.Component<PortalProps, PortalState> { ); } private _renderWallet(): React.ReactNode { + const startOnboarding = this._renderStartOnboarding(); + const isMobile = this.props.screenWidth === ScreenWidths.Sm; + // We need room to scroll down for mobile onboarding + const marginBottom = isMobile ? '200px' : '15px'; return ( <div> - <Wallet - style={this.props.isPortalOnboardingShowing ? { zIndex: zIndex.aboveOverlay } : undefined} - userAddress={this.props.userAddress} - networkId={this.props.networkId} - blockchain={this._blockchain} - blockchainIsLoaded={this.props.blockchainIsLoaded} - blockchainErr={this.props.blockchainErr} - dispatcher={this.props.dispatcher} - tokenByAddress={this.props.tokenByAddress} - trackedTokens={this._getCurrentTrackedTokens()} - userEtherBalanceInWei={this.props.userEtherBalanceInWei} - lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} - injectedProviderName={this.props.injectedProviderName} - providerType={this.props.providerType} - screenWidth={this.props.screenWidth} - location={this.props.location} - trackedTokenStateByAddress={this.state.trackedTokenStateByAddress} - onToggleLedgerDialog={this._onToggleLedgerDialog.bind(this)} - onAddToken={this._onAddToken.bind(this)} - onRemoveToken={this._onRemoveToken.bind(this)} - refetchTokenStateAsync={this._refetchTokenStateAsync.bind(this)} - /> - <Container marginTop="15px"> - <Island> - <Container - marginTop="30px" - marginBottom="30px" - marginLeft="30px" - marginRight="30px" - className="flex justify-around items-center" - > - <ActionAccountBalanceWallet - style={{ width: '30px', height: '30px' }} - color={colors.orange} - /> - <Text - fontColor={colors.grey} - fontSize="16px" - center={true} - onClick={this._startOnboarding.bind(this)} - > - Learn how to set up your account - </Text> - </Container> - </Island> + {isMobile && <Container marginBottom="15px">{startOnboarding}</Container>} + <Container marginBottom={marginBottom}> + <Wallet + style={ + !isMobile && this.props.isPortalOnboardingShowing + ? { zIndex: zIndex.aboveOverlay, position: 'relative' } + : undefined + } + userAddress={this.props.userAddress} + networkId={this.props.networkId} + blockchain={this._blockchain} + blockchainIsLoaded={this.props.blockchainIsLoaded} + blockchainErr={this.props.blockchainErr} + dispatcher={this.props.dispatcher} + tokenByAddress={this.props.tokenByAddress} + trackedTokens={this._getCurrentTrackedTokens()} + userEtherBalanceInWei={this.props.userEtherBalanceInWei} + lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} + injectedProviderName={this.props.injectedProviderName} + providerType={this.props.providerType} + screenWidth={this.props.screenWidth} + location={this.props.location} + trackedTokenStateByAddress={this.state.trackedTokenStateByAddress} + onToggleLedgerDialog={this._onToggleLedgerDialog.bind(this)} + onAddToken={this._onAddToken.bind(this)} + onRemoveToken={this._onRemoveToken.bind(this)} + refetchTokenStateAsync={this._refetchTokenStateAsync.bind(this)} + /> </Container> + {!isMobile && <Container marginTop="15px">{startOnboarding}</Container>} </div> ); } + private _renderStartOnboarding(): React.ReactNode { + return ( + <Island> + <Container + marginTop="30px" + marginBottom="30px" + marginLeft="30px" + marginRight="30px" + className="flex justify-around items-center" + > + <ActionAccountBalanceWallet style={{ width: '30px', height: '30px' }} color={colors.orange} /> + <Text + fontColor={colors.grey} + fontSize="16px" + center={true} + onClick={this._startOnboarding.bind(this)} + > + Learn how to set up your account + </Text> + </Container> + </Island> + ); + } private _startOnboarding(): void { const networkName = sharedConstants.NETWORK_NAME_BY_ID[this.props.networkId]; analytics.logEvent('Portal', 'Onboarding Started - Manual', networkName, this.props.portalOnboardingStep); this.props.dispatcher.updatePortalOnboardingShowing(true); + // On mobile, make sure the wallet is completely visible. + if (this.props.screenWidth === ScreenWidths.Sm) { + document.querySelector('.wallet').scrollIntoView(); + } } private _renderWalletSection(): React.ReactNode { return <Section header={<TextHeader labelText="Your Account" />} body={this._renderWallet()} />; diff --git a/packages/website/ts/components/top_bar/provider_display.tsx b/packages/website/ts/components/top_bar/provider_display.tsx index 1e8855c14..496e5cae0 100644 --- a/packages/website/ts/components/top_bar/provider_display.tsx +++ b/packages/website/ts/components/top_bar/provider_display.tsx @@ -10,6 +10,7 @@ import { Container } from 'ts/components/ui/container'; import { DropDown } from 'ts/components/ui/drop_down'; import { Identicon } from 'ts/components/ui/identicon'; import { Image } from 'ts/components/ui/image'; +import { Island } from 'ts/components/ui/island'; import { Text } from 'ts/components/ui/text'; import { Dispatcher } from 'ts/redux/dispatcher'; import { colors } from 'ts/style/colors'; @@ -35,9 +36,7 @@ interface ProviderDisplayState {} const styles: Styles = { root: { height: ROOT_HEIGHT, - backgroundColor: colors.white, borderRadius: ROOT_HEIGHT, - boxShadow: `0px 4px 6px ${colors.walletBoxShadow}`, }, }; @@ -62,7 +61,7 @@ export class ProviderDisplay extends React.Component<ProviderDisplayProps, Provi this.props.providerType === ProviderType.Injected ? injectedProviderName : 'Ledger Nano S'; const isProviderMetamask = providerTitle === constants.PROVIDER_NAME_METAMASK; const hoverActiveNode = ( - <div className="flex items-center p1" style={styles.root}> + <Island className="flex items-center p1" style={styles.root}> <div> {this._isBlockchainReady() ? ( <Identicon address={this.props.userAddress} diameter={ROOT_HEIGHT} /> @@ -78,7 +77,7 @@ export class ProviderDisplay extends React.Component<ProviderDisplayProps, Provi {isProviderMetamask && ( <Image src="/images/metamask_icon.png" height={ROOT_HEIGHT} width={ROOT_HEIGHT} /> )} - </div> + </Island> ); const hasLedgerProvider = this.props.providerType === ProviderType.Ledger; const horizontalPosition = isExternallyInjectedProvider || hasLedgerProvider ? 'left' : 'middle'; diff --git a/packages/website/ts/components/ui/animation.tsx b/packages/website/ts/components/ui/animation.tsx new file mode 100644 index 000000000..cbda2993d --- /dev/null +++ b/packages/website/ts/components/ui/animation.tsx @@ -0,0 +1,32 @@ +import * as React from 'react'; +import { keyframes, styled } from 'ts/style/theme'; + +export type AnimationType = 'easeUpFromBottom'; + +export interface AnimationProps { + type: AnimationType; +} + +const PlainAnimation: React.StatelessComponent<AnimationProps> = props => <div {...props} />; + +const appearFromBottomFrames = keyframes` + from { + position: absolute; + bottom: -500px; + } + + to { + position: absolute; + bottom: 0px; + } +`; + +const animations: { [K in AnimationType]: string } = { + easeUpFromBottom: `${appearFromBottomFrames} 1s ease 0s 1 forwards`, +}; + +export const Animation = styled(PlainAnimation)` + animation: ${props => animations[props.type]}; +`; + +Animation.displayName = 'Animation'; diff --git a/packages/website/ts/components/ui/button.tsx b/packages/website/ts/components/ui/button.tsx index cb542a386..02fa47480 100644 --- a/packages/website/ts/components/ui/button.tsx +++ b/packages/website/ts/components/ui/button.tsx @@ -1,5 +1,5 @@ import { colors } from '@0xproject/react-shared'; -import { darken, grayscale } from 'polished'; +import { darken, saturate } from 'polished'; import * as React from 'react'; import { styled } from 'ts/style/theme'; @@ -17,7 +17,7 @@ export interface ButtonProps { } const PlainButton: React.StatelessComponent<ButtonProps> = ({ children, isDisabled, onClick, type, className }) => ( - <button type={type} className={className} onClick={isDisabled ? undefined : onClick}> + <button type={type} className={className} onClick={isDisabled ? undefined : onClick} disabled={isDisabled}> {children} </button> ); @@ -26,14 +26,15 @@ export const Button = styled(PlainButton)` cursor: ${props => (props.isDisabled ? 'default' : 'pointer')}; font-size: ${props => props.fontSize}; color: ${props => props.fontColor}; - transition: background-color 0.5s ease; + transition: background-color, opacity 0.5s ease; padding: 0.8em 2.2em; border-radius: 6px; box-shadow: 0px 0px 4px rgba(0, 0, 0, 0.25); font-weight: 500; + outline: none; font-family: ${props => props.fontFamily}; width: ${props => props.width}; - background-color: ${props => (props.isDisabled ? grayscale(props.backgroundColor) : props.backgroundColor)}; + background-color: ${props => props.backgroundColor}; border: ${props => (props.borderColor ? `1px solid ${props.borderColor}` : 'none')}; &:hover { background-color: ${props => (!props.isDisabled ? darken(0.1, props.backgroundColor) : '')}; @@ -41,6 +42,13 @@ export const Button = styled(PlainButton)` &:active { background-color: ${props => (!props.isDisabled ? darken(0.2, props.backgroundColor) : '')}; } + &:disabled { + opacity: 0.5; + box-shadow: none; + } + &:focus { + background-color: ${props => saturate(0.2, props.backgroundColor)}; + } `; Button.defaultProps = { diff --git a/packages/website/ts/components/ui/container.tsx b/packages/website/ts/components/ui/container.tsx index 1776345da..90aec0e7c 100644 --- a/packages/website/ts/components/ui/container.tsx +++ b/packages/website/ts/components/ui/container.tsx @@ -23,6 +23,7 @@ export interface ContainerProps { left?: string; right?: string; bottom?: string; + zIndex?: number; } export const Container: React.StatelessComponent<ContainerProps> = ({ children, className, isHidden, ...style }) => { diff --git a/packages/website/ts/components/ui/identicon.tsx b/packages/website/ts/components/ui/identicon.tsx index 30df995c8..cc1655962 100644 --- a/packages/website/ts/components/ui/identicon.tsx +++ b/packages/website/ts/components/ui/identicon.tsx @@ -23,7 +23,7 @@ export class Identicon extends React.Component<IdenticonProps, IdenticonState> { const radius = diameter / 2; return ( <div - className="circle mx-auto relative transitionFix" + className="circle relative transitionFix" style={{ width: diameter, height: diameter, diff --git a/packages/website/ts/components/ui/island.tsx b/packages/website/ts/components/ui/island.tsx index de90b664f..c8abfb7e0 100644 --- a/packages/website/ts/components/ui/island.tsx +++ b/packages/website/ts/components/ui/island.tsx @@ -1,31 +1,28 @@ import * as React from 'react'; import { colors } from 'ts/style/colors'; +import { styled } from 'ts/style/theme'; export interface IslandProps { style?: React.CSSProperties; - children?: React.ReactNode; className?: string; Component?: string | React.ComponentClass<any> | React.StatelessComponent<any>; + borderRadius?: string; } -const defaultStyle: React.CSSProperties = { - backgroundColor: colors.white, - borderBottomRightRadius: 10, - borderBottomLeftRadius: 10, - borderTopRightRadius: 10, - borderTopLeftRadius: 10, - boxShadow: `0px 4px 6px ${colors.walletBoxShadow}`, - overflow: 'hidden', -}; - -export const Island: React.StatelessComponent<IslandProps> = (props: IslandProps) => ( - <props.Component style={{ ...defaultStyle, ...props.style }} className={props.className}> - {props.children} - </props.Component> +const PlainIsland: React.StatelessComponent<IslandProps> = ({ Component, style, className, children }) => ( + <Component style={style} className={className} children={children} /> ); +export const Island = styled(PlainIsland)` + background-color: ${colors.white}; + border-radius: ${props => props.borderRadius}; + box-shadow: 0px 4px 6px ${colors.walletBoxShadow}; + overflow: hidden; +`; + Island.defaultProps = { Component: 'div', + borderRadius: '10px', style: {}, }; diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index ac2fe0d31..f88fd6c24 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -86,7 +86,6 @@ interface AccessoryItemConfig { const styles: Styles = { root: { width: '100%', - position: 'relative', }, footerItemInnerDiv: { paddingLeft: 24, @@ -323,6 +322,9 @@ export class Wallet extends React.Component<WalletProps, WalletState> { } private _renderTokenRow(token: Token, _index: number): React.ReactNode { const tokenState = this.props.trackedTokenStateByAddress[token.address]; + if (_.isUndefined(tokenState)) { + return null; + } const tokenLink = sharedUtils.getEtherScanLinkIfExists( token.address, this.props.networkId, diff --git a/packages/website/ts/containers/portal_onboarding_flow.ts b/packages/website/ts/containers/portal_onboarding_flow.ts index ba2b8f512..12daad021 100644 --- a/packages/website/ts/containers/portal_onboarding_flow.ts +++ b/packages/website/ts/containers/portal_onboarding_flow.ts @@ -3,7 +3,7 @@ import * as React from 'react'; import { connect } from 'react-redux'; import { Dispatch } from 'redux'; import { Blockchain } from 'ts/blockchain'; -import { ActionTypes, ProviderType, TokenByAddress, TokenStateByAddress } from 'ts/types'; +import { ActionTypes, ProviderType, ScreenWidths, TokenByAddress, TokenStateByAddress } from 'ts/types'; import { PortalOnboardingFlow as PortalOnboardingFlowComponent } from 'ts/components/onboarding/portal_onboarding_flow'; import { State } from 'ts/redux/reducer'; @@ -25,6 +25,7 @@ interface ConnectedState { blockchainIsLoaded: boolean; userEtherBalanceInWei?: BigNumber; tokenByAddress: TokenByAddress; + screenWidth: ScreenWidths; } interface ConnectedDispatch { @@ -43,6 +44,7 @@ const mapStateToProps = (state: State, _ownProps: PortalOnboardingFlowProps): Co userEtherBalanceInWei: state.userEtherBalanceInWei, tokenByAddress: state.tokenByAddress, hasBeenSeen: state.hasPortalOnboardingBeenSeen, + screenWidth: state.screenWidth, }); const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({ diff --git a/packages/website/ts/pages/about/about.tsx b/packages/website/ts/pages/about/about.tsx index 3136dbca3..6830b64ab 100644 --- a/packages/website/ts/pages/about/about.tsx +++ b/packages/website/ts/pages/about/about.tsx @@ -150,12 +150,30 @@ const teamRow5: ProfileInfo[] = [ }, { name: 'Francesco Agosti', - title: 'Senior Frontend Engineer', + title: 'Engineer', description: `Full-stack engineer. Previously senior software engineer at Yelp. Computer Science at Duke.`, image: 'images/team/fragosti.png', linkedIn: 'https://www.linkedin.com/in/fragosti/', github: 'http://github.com/fragosti', }, + { + name: 'Chris Kalani', + title: 'Director of Design', + description: `Previously founded Wake (acquired by InVision). Early Facebook product designer.`, + image: 'images/team/chris.png', + linkedIn: 'https://www.linkedin.com/in/chriskalani/', + github: 'https://github.com/chriskalani', + }, +]; + +const teamRow6: ProfileInfo[] = [ + { + name: 'Mel Oberto', + title: 'Office Operations / Executive Assistant', + description: `Daily Operations. Previously People Operations Associate at Heap. Marketing and MBA at Sacred Heart University.`, + image: 'images/team/mel.png', + linkedIn: 'https://www.linkedin.com/in/melanieoberto', + }, ]; const advisors: ProfileInfo[] = [ @@ -252,6 +270,7 @@ export class About extends React.Component<AboutProps, AboutState> { <div className="clearfix">{this._renderProfiles(teamRow3)}</div> <div className="clearfix">{this._renderProfiles(teamRow4)}</div> <div className="clearfix">{this._renderProfiles(teamRow5)}</div> + <div className="clearfix">{this._renderProfiles(teamRow6)}</div> </div> <div className="pt3 pb2"> <div diff --git a/packages/website/ts/pages/about/profile.tsx b/packages/website/ts/pages/about/profile.tsx index dd046a8cb..e73b1f193 100644 --- a/packages/website/ts/pages/about/profile.tsx +++ b/packages/website/ts/pages/about/profile.tsx @@ -47,7 +47,7 @@ export const Profile = (props: ProfileProps) => { <div style={{ minHeight: 60, lineHeight: 1.4 }} className="pt1 pb2 mx-auto lg-h6 md-h6 sm-h5 sm-center"> {props.profileInfo.description} </div> - <div className="flex pb3 mx-auto sm-hide xs-hide" style={{ width: 280, opacity: 0.5 }}> + <div className="flex pb3 sm-hide xs-hide" style={{ width: 280, opacity: 0.5 }}> {renderSocialMediaIcons(props.profileInfo)} </div> </div> diff --git a/packages/website/ts/style/colors.ts b/packages/website/ts/style/colors.ts index b15000d7a..45be4fe7f 100644 --- a/packages/website/ts/style/colors.ts +++ b/packages/website/ts/style/colors.ts @@ -1,7 +1,7 @@ import { colors as sharedColors } from '@0xproject/react-shared'; const appColors = { - walletBoxShadow: 'rgba(56, 59, 137, 0.2)', + walletBoxShadow: 'rgba(0, 0, 0, 0.05)', walletBorder: '#ededee', walletDefaultItemBackground: '#fbfbfc', walletFocusedItemBackground: '#f0f1f4', |