UNPKG

5.54 kBJavaScriptView Raw
1import React from 'react'
2import styled, { withTheme } from 'styled-components'
3
4import {
5 H1,
6 H2,
7 FlexRow,
8 FlexCol,
9 Chevron
10} from 'SRC'
11
12import PressIcon from 'SRC/core/icons/press/PressIcon'
13import IconRow from './IconRow'
14import defaultProps from './defaultProps.js'
15
16import MediaQuery from 'react-responsive';
17import { CSSTransitionGroup } from 'react-transition-group'
18
19class BasePressQuotes extends React.Component {
20 constructor (props) {
21 super(props)
22 this.state = {
23 index: 0
24 }
25 }
26
27 onClick = (index) => {
28 return (() => {
29 this.setState({index: index})
30 clearInterval(this.timer)
31 this.quoteTimer()
32 })
33 }
34
35 onClickChevronLeft = () => {
36 const { quotes } = this.props
37 const { index } = this.state
38 if (index === 0) {
39 this.setState({index: (quotes.length - 1) })
40 clearInterval(this.timer)
41 this.quoteTimer((quotes.length - 1))
42 } else {
43 this.setState({index: index - 1 })
44 clearInterval(this.timer)
45 this.quoteTimer()
46 }
47 }
48
49 onClickChevronRight = () => {
50 const { index } = this.state
51 const { quotes } = this.props
52
53 if (index === (quotes.length - 1)) {
54 this.setState({index: 0})
55 clearInterval(this.timer)
56 this.quoteTimer()
57 } else {
58 this.setState({index: index + 1})
59 clearInterval(this.timer)
60 this.quoteTimer()
61 }
62 }
63
64 updateIndex = () => {
65 const { quotes } = this.props
66 const { index } = this.state
67
68 if (index === quotes.length - 1) {
69 this.setState({index: 0})
70 } else {
71 this.setState({index: index + 1})
72 }
73 }
74
75 quoteTimer = () => {
76 this.timer = setInterval(this.updateIndex, 5000)
77 }
78
79 componentWillUnmount () {
80 clearInterval(this.timer)
81 }
82
83 componentWillMount () {
84 this.setState({index: 0})
85 this.quoteTimer()
86 }
87
88 render () {
89 const { className, header, headerLabel, theme, quotes} = this.props
90 const { index } = this.state
91 return (
92 <FlexRow
93 constrained
94 element='section'
95 className={className}>
96 <FlexCol mobile={{width: 4}} desktop={{width: 12}}>
97 <H1 aria-label={headerLabel}>{header}</H1>
98 </FlexCol>
99 <FlexCol
100 className="quote_controller"
101 mobile={{width: 4}}
102 desktop={{span: 1, width: 10}}>
103 <Chevron left onClick={this.onClickChevronLeft} />
104 <CSSTransitionGroup
105 aria-hidden
106 transitionName="quote"
107 transitionEnterTimeout={500}
108 transitionLeaveTimeout={1}>
109 <H2 lowercase key={index}>{quotes[index].quote}</H2>
110 </CSSTransitionGroup>
111 <Chevron right onClick={this.onClickChevronRight} />
112 </FlexCol>
113 <FlexCol mobile={{width: 4}} desktop={{span: 1, width: 10}}>
114 <MediaQuery query={theme.breakpoints.aboveTabletMax}>
115 <IconRow
116 quotes={quotes}
117 onClick={this.onClick}
118 selected={index} />
119 </MediaQuery>
120 </FlexCol>
121 <FlexCol mobile={{width: 4}} desktop={{span: 1, width: 10}}>
122 <MediaQuery query="(max-device-width: 959px)">
123 <PressIcon
124 key={index}
125 brand={quotes[index].id}
126 selected={true} />
127 </MediaQuery>
128 </FlexCol>
129 {quotes.map(({quote, name}, index) => {
130 return (
131 <blockquote key={index}>
132 {quote}
133 <cite>{name}</cite>
134 </blockquote>
135 )
136 })}
137 </FlexRow>
138 )
139 }
140}
141
142const PressQuotes = styled(BasePressQuotes)`
143 margin-top: 4rem;
144 margin-bottom: 2rem;
145 ${props => props.theme.media.tablet`
146 margin-top: 6rem;
147 `}
148 ${H1}, ${H2} {
149 text-align: center;
150 margin: 0 0 1rem 0;
151 }
152 ${H1} {
153 @media (max-width: 958px) { font-size: 3.4rem; }
154 }
155 ${H2} {
156 color: ${props => props.theme.colors.rocketBlue};
157 display: flex;
158 justify-content: center;
159 align-items: center;
160 height: 100%;
161 margin-top: 0;
162 margin-bottom: 0;
163 min-height: 12rem;
164 max-height: 45rem;
165 font-style: italic;
166 }
167 ${Chevron} {
168 flex-basis: 2.4rem;
169 min-width: 2.4rem;
170 height: 2.4rem;
171 stroke-width: .7rem;
172 }
173 ${PressIcon} {
174 max-height: 4.5rem;
175 box-sizing: border-box;
176 &: hover {
177 fill: ${props => props.theme.colors.rocketBlue};
178 }
179 }
180 .quote_controller {
181 display: flex;
182 justify-content: space-between;
183 align-items: center;
184 min-height: 14rem;
185 max-height: 45rem;
186 position: relative
187 width: 100%;
188 }
189 .press_icons {
190 display: flex;
191 flex-wrap: wrap;
192 max-height: 12rem;
193 justify-content: center;
194 @media (max-width: 958px) { margin-top: 0.5em; }
195 > * {
196 width: 30rem;
197 @media (min-width: 959px) { width: 25%; }
198 }
199 }
200 .quote_controller span {
201 display: flex;
202 justify-content: space-between;
203 align-items: center;
204 min-height: 12rem;
205 max-height: 45rem;
206 }
207 .quote-enter {
208 opacity: 0.01;
209 }
210 .quote-enter.quote-enter-active {
211 opacity: 1;
212 transition: opacity 500ms ease-in;
213 }
214 .quote-leave {
215 opacity: 0;
216 }
217 .quote-leave.quote-leave-active {
218 opacity: 0;
219 }
220 blockquote {
221 border: 0;
222 clip: rect(0 0 0 0);
223 height: 1px;
224 margin: -1px;
225 overflow: hidden;
226 padding: 0;
227 position: absolute;
228 width: 1px;
229 }
230`
231
232PressQuotes.defaultProps = {
233 ...defaultProps,
234 padding: true,
235 constrained: true
236}
237
238/** @component */
239export default withTheme(PressQuotes)