@rocketsofawesome/mirage
Version:
[Live Demo of the Pattern Library](https://rocketsofawesome.github.io/mirage/)
240 lines (222 loc) • 5.54 kB
JavaScript
import React from 'react'
import styled, { withTheme } from 'styled-components'
import {
H1,
H2,
FlexRow,
FlexCol,
Chevron
} from 'SRC'
import PressIcon from 'SRC/core/icons/press/PressIcon'
import IconRow from './IconRow'
import defaultProps from './defaultProps.js'
import MediaQuery from 'react-responsive';
import { CSSTransitionGroup } from 'react-transition-group'
class BasePressQuotes extends React.Component {
constructor (props) {
super(props)
this.state = {
index: 0
}
}
onClick = (index) => {
return (() => {
this.setState({index: index})
clearInterval(this.timer)
this.quoteTimer()
})
}
onClickChevronLeft = () => {
const { quotes } = this.props
const { index } = this.state
if (index === 0) {
this.setState({index: (quotes.length - 1) })
clearInterval(this.timer)
this.quoteTimer((quotes.length - 1))
} else {
this.setState({index: index - 1 })
clearInterval(this.timer)
this.quoteTimer()
}
}
onClickChevronRight = () => {
const { index } = this.state
const { quotes } = this.props
if (index === (quotes.length - 1)) {
this.setState({index: 0})
clearInterval(this.timer)
this.quoteTimer()
} else {
this.setState({index: index + 1})
clearInterval(this.timer)
this.quoteTimer()
}
}
updateIndex = () => {
const { quotes } = this.props
const { index } = this.state
if (index === quotes.length - 1) {
this.setState({index: 0})
} else {
this.setState({index: index + 1})
}
}
quoteTimer = () => {
this.timer = setInterval(this.updateIndex, 5000)
}
componentWillUnmount () {
clearInterval(this.timer)
}
componentDidMount () {
this.setState({index: 0})
this.quoteTimer()
}
render () {
const { className, header, headerLabel, theme, quotes} = this.props
const { index } = this.state
return (
<FlexRow
constrained
element='section'
className={className}>
<FlexCol mobile={{width: 4}} desktop={{width: 12}}>
<H1 aria-label={headerLabel}>{header}</H1>
</FlexCol>
<FlexCol
className="quote_controller"
mobile={{width: 4}}
desktop={{span: 1, width: 10}}>
<Chevron left onClick={this.onClickChevronLeft} />
<CSSTransitionGroup
aria-hidden
transitionName="quote"
transitionEnterTimeout={500}
transitionLeaveTimeout={1}>
<H2 lowercase key={index}>{quotes[index].quote}</H2>
</CSSTransitionGroup>
<Chevron right onClick={this.onClickChevronRight} />
</FlexCol>
<FlexCol mobile={{width: 4}} desktop={{span: 1, width: 10}}>
<MediaQuery query={theme.breakpoints.aboveTabletMax}>
<IconRow
quotes={quotes}
onClick={this.onClick}
selected={index} />
</MediaQuery>
</FlexCol>
<FlexCol mobile={{width: 4}} desktop={{span: 1, width: 10}}>
<MediaQuery query="(max-device-width: 959px)">
<PressIcon
key={index}
brand={quotes[index].id}
selected={true} />
</MediaQuery>
</FlexCol>
{quotes.map(({quote, name}, index) => {
return (
<blockquote key={index}>
{quote}
<cite>{name}</cite>
</blockquote>
)
})}
</FlexRow>
)
}
}
const PressQuotes = styled(BasePressQuotes)`
margin-top: 4rem;
margin-bottom: 2rem;
${props => props.theme.media.tablet`
margin-top: 6rem;
`}
${H1}, ${H2} {
text-align: center;
margin: 0 0 1rem 0;
}
${H1} {
@media (max-width: 958px) { font-size: 3.4rem; }
}
${H2} {
color: ${props => props.theme.colors.rocketBlue};
display: flex;
justify-content: center;
align-items: center;
height: 100%;
margin-top: 0;
margin-bottom: 0;
min-height: 12rem;
max-height: 45rem;
font-style: italic;
}
${Chevron} {
flex-basis: 2.4rem;
min-width: 2.4rem;
height: 2.4rem;
stroke-width: .7rem;
}
${PressIcon} {
max-height: 4.5rem;
box-sizing: border-box;
&: hover {
fill: ${props => props.theme.colors.rocketBlue};
}
}
.quote_controller {
display: flex;
justify-content: space-between;
align-items: center;
min-height: 14rem;
max-height: 45rem;
position: relative
width: 100%;
}
.press_icons {
display: flex;
flex-wrap: wrap;
max-height: 12rem;
justify-content: center;
@media (max-width: 958px) { margin-top: 0.5em; }
> * {
width: 30rem;
@media (min-width: 959px) { width: 25%; }
}
}
.quote_controller span {
display: flex;
justify-content: space-between;
align-items: center;
min-height: 12rem;
max-height: 45rem;
}
.quote-enter {
opacity: 0.01;
}
.quote-enter.quote-enter-active {
opacity: 1;
transition: opacity 500ms ease-in;
}
.quote-leave {
opacity: 0;
}
.quote-leave.quote-leave-active {
opacity: 0;
}
blockquote {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
`
PressQuotes.defaultProps = {
...defaultProps,
padding: true,
constrained: true
}
/** @component */
export default withTheme(PressQuotes)