Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
With Animation HOC; styled-components animation made easy
// See original source here: https://github.com/RyanCCollins/the-agency/tree/master/packages/ui/src/WithAnimation
import * as React from 'react';
import { ThemedCssFunction } from 'styled-components';
import Animation from './animation';
import { AnimationType } from './types';
export interface Props {
type?: AnimationType;
isVisible: boolean;
children?: JSX.Element;
duration?: number;
delay?: number;
css?: ThemedCssFunction<{}>;
}
type HOC = (props: Props) => JSX.Element;
const WithAnimation: HOC = ({
duration = 1000,
type = 'fadeIn',
children,
delay = 0,
...props,
}) => (
<Animation type={type} duration={duration} {...props}>
{children}
</Animation>
);
export default WithAnimation;
import styled, { css } from 'styled-components';
import { Props } from './types';
function styles(props: Props) {
const opacity = props.isVisible ? 1.0 : 0.0;
const transform = props.isVisible ? 0 : 20;
switch (props.type) {
case 'fadeIn':
return css`
opacity: ${opacity};
`;
case 'fadeInUp':
return css`
opacity: ${opacity};
transform: translateY(${transform}%);
will-change: transform, opacity;
`;
default:
return '';
}
}
function transition(props: Props) {
const duration = 600;
return css`
transition: transform ${duration / 2}ms ease, opacity ${duration}ms ease-out;
`;
}
function delay({ delay }: Props) {
return css`
animation-delay: ${delay}ms;
`;
}
export default styled.div`
${(props: Props) => styles(props)}
${(props: Props) => transition(props)}
${(props: Props) => delay(props)}
${(props: Props) => props.css}
`;
// Original Source From here: https://github.com/RyanCCollins/the-agency/blob/master/src/client/containers/Home/presentation.tsx
import * as React from 'react';
import { findDOMNode } from 'react-dom';
import { Hero, Headline, Image, Box, WithAnimation, Button } from 'ui';
import { StateProps } from './types';
import Wrapper from './styles';
interface State {
section1: boolean;
section2: boolean;
}
export default class Presentation extends React.Component<StateProps, State> {
constructor() {
super();
this.handleScroll = this.handleScroll.bind(this);
this.state = {
section1: false,
section2: false,
};
}
public componentDidMount() {
if (typeof window !== 'undefined') {
window.addEventListener('scroll', this.handleScroll);
}
}
private section1Ref: Element;
private section2Ref: Element;
private handleScroll() {
const windowHeight = window ? window.innerHeight : 1000;
const section1Node = findDOMNode(this.section1Ref);
const section2Node = findDOMNode(this.section2Ref);
const section1 = section1Node.getBoundingClientRect().top < windowHeight / 2;
const section2 = section2Node.getBoundingClientRect().top < windowHeight / 2;
this.setState({
section1,
section2,
});
}
public render() {
return (
<Wrapper>
<Hero backgroundColor="#03A9F4">
<Box alignItems="center" style={{ minHeight: 'calc(100vh - 100px)' }} justifyContent="center">
<Image
alt="The Agency"
src="https://github.com/RyanCCollins/cdn/blob/master/misc/rocket.png?raw=true"
size={300}
/>
<Headline color="white">
The Agency
</Headline>
</Box>
</Hero>
<div ref={(ref) => { this.section1Ref = ref; }}>
<Hero backgroundColor="#9c27b0">
<Box alignItems="center" style={{ minHeight: 'calc(100vh - 100px)' }} justifyContent="center">
<Box style={{ maxWidth: 576 }} justifyContent="center">
<WithAnimation type="fadeInUp" isVisible={this.state.section1}>
<Headline color="white">
We are a dedicated digital agency
</Headline>
</WithAnimation>
</Box>
</Box>
</Hero>
</div>
<div ref={(ref) => { this.section2Ref = ref; }}>
<Hero backgroundColor="#ff9800">
<Box alignItems="center" style={{ minHeight: 'calc(100vh - 100px)' }} justifyContent="center">
<Box style={{ maxWidth: 576 }} justifyContent="center">
<WithAnimation type="fadeInUp" isVisible={this.state.section2}>
<Headline color="white">
We build scalable solutions for the web and mobile platforms
</Headline>
<Button
borderColor="#fff"
backgroundColor="transparent"
onClick={(e) => e}
label="See Case Studies"
/>
</WithAnimation>
</Box>
</Box>
</Hero>
</div>
</Wrapper>
);
}
}
// Original Source From here: https://github.com/RyanCCollins/the-agency/blob/master/src/client/containers/NavigationMenu/presentation.tsx
import * as React from 'react';
import { Props } from './types';
import { Box, WithAnimation, Heading } from 'ui';
import Nav from './nav';
import Li from './li';
import Ul from './ul';
export default function Presentation({
actions,
isVisible,
...props,
}: Props) {
return (
<Nav {...props} isVisible={isVisible} onClick={actions.toggleMenu}>
<Box pad="large" flexDirection="row" justifyContent="space-between">
<Box>
<WithAnimation type="fadeInUp" isVisible={isVisible}>
<Heading color="white" upcase>The Agency</Heading>
</WithAnimation>
</Box>
<Ul>
<Li>
<WithAnimation type="fadeInUp" isVisible={isVisible}>
<Heading textAlign="right" tag="h2" color="white">
Case Studies
</Heading>
</WithAnimation>
</Li>
<Li>
<WithAnimation type="fadeInUp" isVisible={isVisible}>
<Heading textAlign="right" tag="h2" color="white">
Clients
</Heading>
</WithAnimation>
</Li>
<Li>
<WithAnimation type="fadeInUp" isVisible={isVisible}>
<Heading textAlign="right" tag="h2" color="white">
About
</Heading>
</WithAnimation>
</Li>
</Ul>
</Box>
</Nav>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment