diff options
author | fragosti <francesco.agosti93@gmail.com> | 2018-10-31 06:21:58 +0800 |
---|---|---|
committer | fragosti <francesco.agosti93@gmail.com> | 2018-10-31 06:21:58 +0800 |
commit | a49bf353f85c22a029db3085a620f3c031b52d73 (patch) | |
tree | 305a18cbdb2b2c5eca2d73598a8024ec6b87dfc7 | |
parent | d0a0af51306bf5e5b46fd8982c70b271212af42f (diff) | |
download | dexon-sol-tools-a49bf353f85c22a029db3085a620f3c031b52d73.tar.gz dexon-sol-tools-a49bf353f85c22a029db3085a620f3c031b52d73.tar.zst dexon-sol-tools-a49bf353f85c22a029db3085a620f3c031b52d73.zip |
feat: refactor animation code
10 files changed, 130 insertions, 74 deletions
diff --git a/packages/instant/src/components/animations/position_animation.tsx b/packages/instant/src/components/animations/position_animation.tsx new file mode 100644 index 000000000..de38ee30a --- /dev/null +++ b/packages/instant/src/components/animations/position_animation.tsx @@ -0,0 +1,70 @@ +import * as React from 'react'; +import { Keyframes } from 'styled-components'; + +import { css, keyframes, styled } from '../../style/theme'; + +const generateTransitionInfoCss = ( + key: keyof TransitionInfo, + top?: TransitionInfo, + bottom?: TransitionInfo, + left?: TransitionInfo, + right?: TransitionInfo, +): string => { + const topStringIfExists = top ? `top: ${top[key]};` : ''; + const bottomStringIfExists = bottom ? `bottom: ${bottom[key]};` : ''; + const leftStringIfExists = left ? `left: ${left[key]};` : ''; + const rightStringIfExists = right ? `right: ${right[key]};` : ''; + return ` + ${topStringIfExists} + ${bottomStringIfExists} + ${leftStringIfExists} + ${rightStringIfExists} + `; +}; + +const slideKeyframeGenerator = ( + top?: TransitionInfo, + bottom?: TransitionInfo, + left?: TransitionInfo, + right?: TransitionInfo, +) => keyframes` + from { + position: relative; + ${generateTransitionInfoCss('from', top, bottom, left, right)} + } + + to { + position: relative; + ${generateTransitionInfoCss('to', top, bottom, left, right)} + } +`; + +export interface TransitionInfo { + from: string; + to: string; +} + +export interface PositionAnimationProps { + top?: TransitionInfo; + bottom?: TransitionInfo; + left?: TransitionInfo; + right?: TransitionInfo; + timingFunction: string; + direction?: string; +} + +export const PositionAnimation = + styled.div < + PositionAnimationProps > + ` + animation-name: ${props => + css` + ${slideKeyframeGenerator(props.top, props.bottom, props.left, props.right)}; + `}; + animation-duration: 0.3s; + animation-timing-function: ${props => props.timingFunction}; + animation-delay: 0s; + animation-iteration-count: 1; + animation-fill-mode: ${props => props.direction || 'none'}; + position: relative; +`; diff --git a/packages/instant/src/components/animations/slide_animations.tsx b/packages/instant/src/components/animations/slide_animations.tsx index 84280372b..99533a2f0 100644 --- a/packages/instant/src/components/animations/slide_animations.tsx +++ b/packages/instant/src/components/animations/slide_animations.tsx @@ -3,56 +3,16 @@ import { Keyframes } from 'styled-components'; import { css, keyframes, styled } from '../../style/theme'; -const slideKeyframeGenerator = (fromY: string, toY: string) => keyframes` - from { - position: relative; - top: ${fromY}; - } - - to { - position: relative; - top: ${toY}; - } -`; +import { PositionAnimation, PositionAnimationProps } from './position_animation'; +export type SlideAnimationPhase = 'slideIn' | 'slideOut'; export interface SlideAnimationProps { - keyframes: Keyframes; - animationType: string; - animationDirection?: string; + phase: SlideAnimationPhase; + slideIn: PositionAnimationProps; + slideOut: PositionAnimationProps; } -export const SlideAnimation = - styled.div < - SlideAnimationProps > - ` - animation-name: ${props => - css` - ${props.keyframes}; - `}; - animation-duration: 0.3s; - animation-timing-function: ${props => props.animationType}; - animation-delay: 0s; - animation-iteration-count: 1; - animation-fill-mode: ${props => props.animationDirection || 'none'}; - position: relative; -`; - -export interface SlideAnimationComponentProps { - downY: string; -} - -export const SlideUpAnimation: React.StatelessComponent<SlideAnimationComponentProps> = props => ( - <SlideAnimation animationType="ease-in" keyframes={slideKeyframeGenerator(props.downY, '0px')}> - {props.children} - </SlideAnimation> -); - -export const SlideDownAnimation: React.StatelessComponent<SlideAnimationComponentProps> = props => ( - <SlideAnimation - animationDirection="forwards" - animationType="cubic-bezier(0.25, 0.1, 0.25, 1)" - keyframes={slideKeyframeGenerator('0px', props.downY)} - > - {props.children} - </SlideAnimation> -); +export const SlideAnimation: React.StatelessComponent<SlideAnimationProps> = props => { + const propsToUse = props.phase === 'slideIn' ? props.slideIn : props.slideOut; + return <PositionAnimation {...propsToUse}>{props.children}</PositionAnimation>; +}; diff --git a/packages/instant/src/components/erc20_asset_amount_input.tsx b/packages/instant/src/components/erc20_asset_amount_input.tsx index 4108fd0e8..bed1b3b4e 100644 --- a/packages/instant/src/components/erc20_asset_amount_input.tsx +++ b/packages/instant/src/components/erc20_asset_amount_input.tsx @@ -15,7 +15,7 @@ export interface ERC20AssetAmountInputProps { asset?: ERC20Asset; value?: BigNumberInput; onChange: (value?: BigNumberInput, asset?: ERC20Asset) => void; - onSymbolClick: (asset?: ERC20Asset) => void; + onSymbolClick?: (asset?: ERC20Asset) => void; startingFontSizePx: number; fontColor?: ColorOption; isDisabled: boolean; @@ -28,7 +28,6 @@ export interface ERC20AssetAmountInputState { export class ERC20AssetAmountInput extends React.Component<ERC20AssetAmountInputProps, ERC20AssetAmountInputState> { public static defaultProps = { onChange: util.boundNoop, - onSymbolClick: util.boundNoop, isDisabled: false, }; constructor(props: ERC20AssetAmountInputProps) { @@ -112,7 +111,9 @@ export class ERC20AssetAmountInput extends React.Component<ERC20AssetAmountInput }); }; private readonly _handleSymbolClick = () => { - this.props.onSymbolClick(this.props.asset); + if (this.props.onSymbolClick) { + this.props.onSymbolClick(this.props.asset); + } }; // For assets with symbols of different length, // start scaling the input at different character lengths diff --git a/packages/instant/src/components/instant_heading.tsx b/packages/instant/src/components/instant_heading.tsx index 0b41d44d7..e1c2f8bc3 100644 --- a/packages/instant/src/components/instant_heading.tsx +++ b/packages/instant/src/components/instant_heading.tsx @@ -60,8 +60,8 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> { private _renderAmountsSection(): React.ReactNode { return ( <Container> - <Container marginBottom="5px">{this._placeholderOrAmount(this._ethAmount)}</Container> - <Container opacity={0.7}>{this._placeholderOrAmount(this._dollarAmount)}</Container> + <Container marginBottom="5px">{this._renderPlaceholderOrAmount(this._renderEthAmount)}</Container> + <Container opacity={0.7}>{this._renderPlaceholderOrAmount(this._renderDollarAmount)}</Container> </Container> ); } @@ -92,7 +92,7 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> { return 'I want to buy'; } - private _placeholderOrAmount(amountFunction: () => React.ReactNode): React.ReactNode { + private _renderPlaceholderOrAmount(amountFunction: () => React.ReactNode): React.ReactNode { if (this.props.quoteRequestState === AsyncProcessState.PENDING) { return <AmountPlaceholder isPulsating={true} color={PLACEHOLDER_COLOR} />; } @@ -102,7 +102,7 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> { return amountFunction(); } - private readonly _ethAmount = (): React.ReactNode => { + private readonly _renderEthAmount = (): React.ReactNode => { return ( <Text fontSize="16px" fontColor={ColorOption.white} fontWeight={500}> {format.ethBaseAmount( @@ -114,7 +114,7 @@ export class InstantHeading extends React.Component<InstantHeadingProps, {}> { ); }; - private readonly _dollarAmount = (): React.ReactNode => { + private readonly _renderDollarAmount = (): React.ReactNode => { return ( <Text fontSize="16px" fontColor={ColorOption.white}> {format.ethBaseAmountInUsd( diff --git a/packages/instant/src/components/panel.tsx b/packages/instant/src/components/panel.tsx index bb16ed9b1..ecefadced 100644 --- a/packages/instant/src/components/panel.tsx +++ b/packages/instant/src/components/panel.tsx @@ -12,10 +12,11 @@ export interface PanelProps { export const Panel: React.StatelessComponent<PanelProps> = ({ children, onClose }) => ( <Container backgroundColor={ColorOption.white} - position="absolute" - top="0px" - left="0px" - width="100%" + // position="absolute" + // left="0px" + // bottom="0px" + // width="100%" + // height="100%" height="100%" zIndex={zIndex.panel} > diff --git a/packages/instant/src/components/sliding_error.tsx b/packages/instant/src/components/sliding_error.tsx index cc9abb7dd..8f209765e 100644 --- a/packages/instant/src/components/sliding_error.tsx +++ b/packages/instant/src/components/sliding_error.tsx @@ -2,7 +2,8 @@ import * as React from 'react'; import { ColorOption } from '../style/theme'; -import { SlideDownAnimation, SlideUpAnimation } from './animations/slide_animations'; +import { PositionAnimationProps } from './animations/position_animation'; +import { SlideAnimation, SlideAnimationPhase } from './animations/slide_animations'; import { Container, Flex, Text } from './ui'; @@ -31,16 +32,29 @@ export const Error: React.StatelessComponent<ErrorProps> = props => ( </Container> ); -export type SlidingDirection = 'up' | 'down'; export interface SlidingErrorProps extends ErrorProps { - direction: SlidingDirection; + phase: SlideAnimationPhase; } export const SlidingError: React.StatelessComponent<SlidingErrorProps> = props => { - const AnimationComponent = props.direction === 'up' ? SlideUpAnimation : SlideDownAnimation; - + const slideAmount = '120px'; + const slideUp: PositionAnimationProps = { + timingFunction: 'ease-in', + top: { + from: slideAmount, + to: '0px', + }, + }; + const slideDown: PositionAnimationProps = { + timingFunction: 'cubic-bezier(0.25, 0.1, 0.25, 1)', + top: { + from: '0px', + to: slideAmount, + }, + direction: 'forwards', + }; return ( - <AnimationComponent downY="120px"> + <SlideAnimation slideIn={slideUp} slideOut={slideDown} phase={props.phase}> <Error icon={props.icon} message={props.message} /> - </AnimationComponent> + </SlideAnimation> ); }; diff --git a/packages/instant/src/components/ui/container.tsx b/packages/instant/src/components/ui/container.tsx index b6842b294..7b8642761 100644 --- a/packages/instant/src/components/ui/container.tsx +++ b/packages/instant/src/components/ui/container.tsx @@ -29,6 +29,7 @@ export interface ContainerProps { whiteSpace?: string; opacity?: number; cursor?: string; + overflow?: string; } export const Container = @@ -59,6 +60,7 @@ export const Container = ${props => cssRuleIfExists(props, 'white-space')} ${props => cssRuleIfExists(props, 'opacity')} ${props => cssRuleIfExists(props, 'cursor')} + ${props => cssRuleIfExists(props, 'overflow')} ${props => (props.hasBoxShadow ? `box-shadow: 0px 2px 10px rgba(0, 0, 0, 0.1)` : '')}; background-color: ${props => (props.backgroundColor ? props.theme[props.backgroundColor] : 'none')}; border-color: ${props => (props.borderColor ? props.theme[props.borderColor] : 'none')}; diff --git a/packages/instant/src/components/zero_ex_instant_container.tsx b/packages/instant/src/components/zero_ex_instant_container.tsx index ded0d075e..c8d5235c8 100644 --- a/packages/instant/src/components/zero_ex_instant_container.tsx +++ b/packages/instant/src/components/zero_ex_instant_container.tsx @@ -4,16 +4,16 @@ import { LatestBuyQuoteOrderDetails } from '../containers/latest_buy_quote_order import { LatestError } from '../containers/latest_error'; import { SelectedAssetBuyOrderStateButtons } from '../containers/selected_asset_buy_order_state_buttons'; import { SelectedAssetInstantHeading } from '../containers/selected_asset_instant_heading'; - import { ColorOption } from '../style/theme'; import { zIndex } from '../style/z_index'; +import { Panel } from './panel'; import { Container, Flex } from './ui'; export interface ZeroExInstantContainerProps {} export const ZeroExInstantContainer: React.StatelessComponent<ZeroExInstantContainerProps> = props => ( - <Container width="350px"> + <Container width="350px" position="relative"> <Container zIndex={zIndex.errorPopup} position="relative"> <LatestError /> </Container> @@ -23,6 +23,7 @@ export const ZeroExInstantContainer: React.StatelessComponent<ZeroExInstantConta backgroundColor={ColorOption.white} borderRadius="3px" hasBoxShadow={true} + overflow="hidden" > <Flex direction="column" justify="flex-start"> <SelectedAssetInstantHeading /> @@ -31,6 +32,11 @@ export const ZeroExInstantContainer: React.StatelessComponent<ZeroExInstantConta <SelectedAssetBuyOrderStateButtons /> </Container> </Flex> + {/* <Container position="absolute" left="0px" bottom="0px" width="100%" height="100%"> + <SlideAnimationHelper direction="up" downY="200px"> + <Panel> Hey </Panel> + </SlideAnimationHelper> + </Container> */} </Container> </Container> ); diff --git a/packages/instant/src/containers/latest_error.tsx b/packages/instant/src/containers/latest_error.tsx index 45ca09673..2a8d232da 100644 --- a/packages/instant/src/containers/latest_error.tsx +++ b/packages/instant/src/containers/latest_error.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { connect } from 'react-redux'; +import { SlideAnimationPhase } from '../components/animations/slide_animations'; import { SlidingError } from '../components/sliding_error'; import { State } from '../redux/reducer'; import { Asset, DisplayStatus } from '../types'; @@ -9,26 +10,26 @@ import { Asset, DisplayStatus } from '../types'; export interface LatestErrorComponentProps { asset?: Asset; latestErrorMessage?: string; - slidingDirection: 'down' | 'up'; + slidingPhase: SlideAnimationPhase; } export const LatestErrorComponent: React.StatelessComponent<LatestErrorComponentProps> = props => { if (!props.latestErrorMessage) { return <div />; } - return <SlidingError direction={props.slidingDirection} icon="😢" message={props.latestErrorMessage} />; + return <SlidingError phase={props.slidingPhase} icon="😢" message={props.latestErrorMessage} />; }; interface ConnectedState { asset?: Asset; latestErrorMessage?: string; - slidingDirection: 'down' | 'up'; + slidingPhase: SlideAnimationPhase; } export interface LatestErrorProps {} const mapStateToProps = (state: State, _ownProps: LatestErrorProps): ConnectedState => ({ asset: state.selectedAsset, latestErrorMessage: state.latestErrorMessage, - slidingDirection: state.latestErrorDisplayStatus === DisplayStatus.Present ? 'up' : 'down', + slidingPhase: state.latestErrorDisplayStatus === DisplayStatus.Present ? 'slideIn' : 'slideOut', }); export const LatestError = connect(mapStateToProps)(LatestErrorComponent); diff --git a/packages/instant/src/containers/selected_erc20_asset_amount_input.ts b/packages/instant/src/containers/selected_erc20_asset_amount_input.ts index 4767b15d4..4df7faab9 100644 --- a/packages/instant/src/containers/selected_erc20_asset_amount_input.ts +++ b/packages/instant/src/containers/selected_erc20_asset_amount_input.ts @@ -19,6 +19,7 @@ import { errorFlasher } from '../util/error_flasher'; export interface SelectedERC20AssetAmountInputProps { fontColor?: ColorOption; startingFontSizePx: number; + onSymbolClick?: (asset?: ERC20Asset) => void; } interface ConnectedState { |