Skip to content

Instantly share code, notes, and snippets.

@kaneel
Last active January 11, 2019 10:20
Show Gist options
  • Save kaneel/ee1ffd08078229487b941cf1df2ee3a4 to your computer and use it in GitHub Desktop.
Save kaneel/ee1ffd08078229487b941cf1df2ee3a4 to your computer and use it in GitHub Desktop.
A simple text revealer (char by char), you could make different type of animations and make it optionable
import * as React from 'react';
import { styled, keyframes, StyledComponentClass } from '../styled';
export interface IProps {
onDoneHandler?: () => void;
}
export interface IState {
cursor: number;
content: JSX.Element[];
}
export interface IRevealItemProps {
onDoneHandler: () => void;
duration: number;
}
const reveal = keyframes`
0%{ opacity: 0; }
100%{ opacity: 1; }
`;
const StyledRevealItem = styled.div`
display: inline=block;
opacity: 0;
animation-name: ${reveal};
animation-timing-function: ease-in-out;
animation-fill-mode: forwards;
${({duration}) => `animation-duration: ${duration}ms`}
` as StyledComponentClass<any, {duration: number}>;
export class RevealItem extends React.Component<IRevealItemProps, {}> {
public static defaultProps: IRevealItemProps = {
duration: 250,
onDoneHandler: null
};
public componentDidMount() {
const { onDoneHandler, duration } = this.props;
setTimeout(onDoneHandler, duration);
}
public render() {
const { children, duration } = this.props;
return(
<StyledRevealItem duration={duration}>{children}</StyledRevealItem>
);
}
}
export default class Revealer extends React.Component<IProps, IState> {
public static Item: React.ComponentClass = RevealItem;
public static defaultProps: IProps = {
onDoneHandler: null
};
public state: IState = {
cursor: 1,
content: []
};
private onDone = (index: number) => {
const { onDoneHandler, children } = this.props;
const { content } = this.state;
const cursor = this.state.cursor + 1;
this.setState({ cursor });
if (cursor >= content.length && onDoneHandler) {
onDoneHandler();
}
}
public componentWillMount() {
const content = React.Children.toArray(this.props.children).map(
(child: any, index: number) => React.cloneElement(child, {
onDoneHandler: () => this.onDone(index)
})
);
this.setState({ content });
}
public render() {
const { content, cursor } = this.state;
return (
<>
{ content.slice(0, cursor).map((item: JSX.Element, key: number) => React.cloneElement(item, { key })) }
</>
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment