Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(www): tagline on plugin library landing page #12530

Merged
merged 18 commits into from
Mar 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
195 changes: 195 additions & 0 deletions www/src/components/rotator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
import React, { Component } from "react"
import Slider from "./slider"
import { options } from "../utils/typography"
import { scale, colors, space, radii } from "../utils/presets"
import Link from "gatsby-link"
import MdNavigateBefore from "react-icons/lib/md/navigate-before"
import MdNavigateNext from "react-icons/lib/md/navigate-next"
import { srOnly } from "../utils/styles"

const controlButtonStyles = {
WebkitAppearance: `none`,
color: colors.gray.calm,
fontWeight: 700,
border: 0,
background: `transparent`,
position: `absolute`,
top: 0,
bottom: 0,
left: 0,
padding: 0,
fontSize: scale[5],
width: space[8],
textAlign: `center`,
"&:hover": {
cursor: `pointer`,
color: colors.gatsby,
background: colors.ui.whisper,
},
"&:active": { background: colors.ui.light },
}

class Rotator extends Component {
state = {
item: 0,
size: {},
}
sliderContainer = React.createRef()
intervalId = null

_clearInterval() {
if (this.intervalId) {
clearInterval(this.intervalId)
this.intervalId = null
}
}

decrementItem = () => {
this._clearInterval()
this.setState({
item:
(this.state.item + this.props.items.length - 1) %
this.props.items.length,
})
}

incrementItemAndClearInterval = () => {
this._clearInterval()
this.incrementItem()
}

incrementItem = () => {
this.setState(state => {
return {
item: (state.item + 1) % this.props.items.length,
}
})
}

componentDidMount() {
if (this.shouldAnimate()) {
requestAnimationFrame(() => {
this.intervalId = setInterval(this.incrementItem, 5000)
this.setState({ size: this.getDimensions() })
})
}
}

componentWillUnmount() {
clearInterval(this.intervalId)
}

componentDidUpdate(prevProps, prevState) {
if (this.shouldAnimate() && prevState.item !== this.state.item) {
requestAnimationFrame(() => {
this.setState({ size: this.getDimensions() })
})
}
}

getDimensions() {
if (this.sliderContainer.current === null) {
return {
width: `auto`,
height: `auto`,
}
}

return this.sliderContainer.current.getBoundingClientRect()
}

shouldAnimate() {
const mediaQuery = window.matchMedia(`(prefers-reduced-motion)`)
return !mediaQuery || !mediaQuery.matches
}

render() {
const { text, pluginName } = this.props.items[this.state.item]
const enableSlider = this.shouldAnimate() && this.intervalId

return (
<div
css={{
borderTop: `1px solid ${colors.gray.border}`,
borderBottom: `1px solid ${colors.gray.border}`,
borderRadius: radii[2],
padding: `${space[4]} ${space[9]}`,
margin: `${space[6]} 0`,
position: `relative`,
}}
>
<p
css={{
color: colors.gray.copy,
fontSize: scale[4],
fontFamily: options.headerFontFamily.join(`,`),
textAlign: `center`,
marginBottom: 0,
}}
>
<span>Need&nbsp;</span>
<span
style={{
display: `inline-block`,
transition: `width 150ms linear`,
width: this.state.size.width || `auto`,
}}
>
<span
css={{
fontWeight: 600,
whiteSpace: `nowrap`,
display: `inline-block`,
}}
id="headline-slider"
ref={this.sliderContainer}
aria-live={this.intervalId ? `off` : `polite`}
>
{!enableSlider ? (
<>{text}</>
) : (
<Slider items={[text]} color={`#000`} />
)}
</span>
</span>
</p>

<p
css={{
color: colors.gray.calm,
margin: 0,
fontSize: scale[3],
textAlign: `center`,
}}
>
There’s{` `}
{pluginName ? (
<Link to={`/packages/` + pluginName}>a plugin</Link>
) : (
`a plugin`
)}
{` `}
for that.
</p>
<button
css={{ ...controlButtonStyles }}
onClick={this.decrementItem}
aria-controls="headline-slider"
>
<MdNavigateBefore aria-hidden="true" />
<span css={srOnly}>Previous</span>
</button>
<button
css={{ ...controlButtonStyles, left: `auto`, right: 0 }}
onClick={this.incrementItemAndClearInterval}
aria-controls="headline-slider"
>
<MdNavigateNext aria-hidden="true" />
<span css={srOnly}>Next</span>
</button>
</div>
)
}
}

export default Rotator
43 changes: 43 additions & 0 deletions www/src/components/slider.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from "react"
import { keyframes } from "@emotion/core"

export default ({ items, color }) => (
<span
css={{
"& span": {
animation: `${topToBottom} 5s linear infinite 0s`,
opacity: 0,
},
}}
>
{items.map(item => (
<span key={item} css={{ color }}>
{item}
</span>
))}
</span>
)

const topToBottom = keyframes({
"0%": {
opacity: 0,
},
"6%": {
opacity: 0,
},
"21%": {
opacity: 1,
},
"69%": {
opacity: 1,
},
"84%": {
opacity: 0,
},
"90%": {
opacity: 0,
},
"100%": {
opacity: 0,
},
})
64 changes: 56 additions & 8 deletions www/src/pages/plugins.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React, { Component } from "react"
import Container from "../components/container"
import Rotator from "../components/rotator"
import Unbird from "../components/unbird"
import { Link } from "gatsby"
import logo from "../monogram.svg"
import { rhythm } from "../utils/typography"
import { colors, space, dimensions, scale, fonts } from "../utils/presets"
import { colors, space, dimensions, scale } from "../utils/presets"

class Plugins extends Component {
render() {
Expand All @@ -28,8 +29,8 @@ class Plugins extends Component {
src={logo}
css={{
display: `inline-block`,
height: rhythm(4),
width: rhythm(4),
height: rhythm(3),
width: rhythm(3),
marginLeft: `auto`,
marginRight: `auto`,
}}
Expand All @@ -40,18 +41,65 @@ class Plugins extends Component {
fontSize: scale[6],
marginLeft: space[5],
marginRight: space[5],
marginBottom: 0,
textAlign: `center`,
}}
>
Welcome to the Gatsby Plugin Library!
</h1>
<Rotator
items={[
{
text: `SEO?`,
pluginName: `gatsby-plugin-react-helmet`,
},
{
text: `responsive images?`,
pluginName: `gatsby-image`,
},
{
text: `offline support?`,
pluginName: `gatsby-plugin-offline`,
},
{
text: `Sass support?`,
pluginName: `gatsby-plugin-sass`,
},
{
text: `a sitemap?`,
pluginName: `gatsby-plugin-sitemap`,
},
{
text: `an RSS feed?`,
pluginName: `gatsby-plugin-feed`,
},
{
text: `great typography?`,
pluginName: `gatsby-plugin-typography`,
},
{
text: `Typescript?`,
pluginName: `gatsby-plugin-typescript`,
},
{
text: `Google Analytics?`,
pluginName: `gatsby-plugin-google-analytics`,
},
{
text: `Wordpress integration?`,
pluginName: `gatsby-source-wordpress`,
},
{
text: `anything?`,
},
]}
color={colors.lilac}
/>

<p
css={{
color: colors.gray.calm,
marginLeft: space[9],
marginRight: space[9],
fontSize: scale[4],
fontFamily: fonts.header,
color: colors.gray.lightCopy,
fontSize: scale[2],
textAlign: `center`,
}}
>
Expand Down
11 changes: 11 additions & 0 deletions www/src/utils/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@ const stripeAnimation = keyframes({
"100%": { backgroundPosition: `${space[7]} ${space[11]}` },
})

export const srOnly = {
position: `absolute`,
width: 1,
height: 1,
padding: 0,
overflow: `hidden`,
clip: `rect(0,0,0,0)`,
whiteSpace: `nowrap`,
border: 0,
}

export const scrollbarStyles = {
WebkitOverflowScrolling: `touch`,
"&::-webkit-scrollbar": {
Expand Down