Skip to content

Commit 49933ca

Browse files
committed
New Component: Text Rotator
1 parent 3c998ac commit 49933ca

File tree

2 files changed

+130
-0
lines changed

2 files changed

+130
-0
lines changed
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import React, { PropTypes } from 'react';
2+
import './text-rotater.scss';
3+
4+
export default class TextRotater extends React.PureComponent {
5+
6+
constructor(props) {
7+
super(props);
8+
this.handleTransitionEnd = this.handleTransitionEnd.bind(this);
9+
this.calculateContentHeight = this.calculateContentHeight.bind(this);
10+
11+
this.state = {
12+
currentIndex: 0,
13+
contentHeight: 0,
14+
};
15+
}
16+
17+
componentDidMount() {
18+
const { delay } = this.props;
19+
20+
setTimeout(() => {
21+
this.calculateContentHeight();
22+
}, 50);
23+
24+
setTimeout(() => {
25+
this.textRotatorWrap.classList.add('text-rotater--slide-up');
26+
}, delay);
27+
28+
window.addEventListener('resize', this.calculateContentHeight);
29+
}
30+
31+
componentWillUnmount() {
32+
window.removeEventListener('resize', this.calculateContentHeight);
33+
}
34+
35+
calculateContentHeight() {
36+
this.setState({
37+
contentHeight: this.content.clientHeight,
38+
});
39+
}
40+
41+
handleTransitionEnd() {
42+
const { children, repeatDelay } = this.props;
43+
this.textRotatorWrap.classList.remove('text-rotater--slide-up');
44+
this.setState({
45+
currentIndex: (this.state.currentIndex + 1) % React.Children.count(children),
46+
}, () => {
47+
setTimeout(() => {
48+
this.textRotatorWrap.classList.add('text-rotater--slide-up');
49+
}, repeatDelay);
50+
});
51+
}
52+
53+
render() {
54+
const { children } = this.props;
55+
const { currentIndex, contentHeight } = this.state;
56+
const childrenCount = React.Children.count(children);
57+
58+
const currentChild = React.cloneElement(children[currentIndex], { ref: c => (this.content = c)});
59+
60+
const nextChild = React.cloneElement(children[(currentIndex + 1) % childrenCount]);
61+
62+
return (
63+
<div className="text-rotater">
64+
<div
65+
className="text-rotater__wrap"
66+
ref={ trw => (this.textRotatorWrap = trw) }
67+
onTransitionEnd={ this.handleTransitionEnd }
68+
style={ { height: contentHeight } }
69+
>
70+
{ currentChild }
71+
{ nextChild }
72+
</div>
73+
</div>
74+
);
75+
}
76+
}
77+
78+
TextRotater.defaultProps = {
79+
delay: 0,
80+
repeatDelay: 3000,
81+
};
82+
83+
84+
TextRotater.propTypes = {
85+
children: PropTypes.arrayOf(PropTypes.node),
86+
delay: PropTypes.number,
87+
repeatDelay: PropTypes.number,
88+
};
89+
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
.text-rotater {
2+
overflow: hidden;
3+
position: relative;
4+
display: inline-block;
5+
padding: 0 0.3em;
6+
vertical-align: bottom;
7+
8+
&::after,
9+
&::before {
10+
content: '';
11+
position: absolute;
12+
height: 3px;
13+
left: 0;
14+
}
15+
16+
&::after {
17+
top: 0;
18+
background-image: linear-gradient(#{getColor(elephant)}, transparent);
19+
}
20+
21+
&::before {
22+
bottom: 0;
23+
z-index: 1;
24+
background-image: linear-gradient(transparent, #{getColor(elephant)});
25+
}
26+
27+
> * {
28+
display: inline-block;
29+
}
30+
}
31+
32+
.text-rotater--slide-up {
33+
transition: transform 1s;
34+
transition-timing-function: cubic-bezier(0.7, 0, 0.3, 1);
35+
transform: translateY(-100%);
36+
}
37+
38+
.text-rotater__wrap {
39+
display: inline-flex;
40+
flex-direction: column;
41+
}

0 commit comments

Comments
 (0)