diff --git a/www/src/components/rotator.js b/www/src/components/rotator.js new file mode 100644 index 0000000000000..27ff993a69316 --- /dev/null +++ b/www/src/components/rotator.js @@ -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 ( +
+

+ Need  + + + {!enableSlider ? ( + <>{text} + ) : ( + + )} + + +

+ +

+ There’s{` `} + {pluginName ? ( + a plugin + ) : ( + `a plugin` + )} + {` `} + for that. +

+ + +
+ ) + } +} + +export default Rotator diff --git a/www/src/components/slider.js b/www/src/components/slider.js new file mode 100644 index 0000000000000..dfa631b243939 --- /dev/null +++ b/www/src/components/slider.js @@ -0,0 +1,43 @@ +import React from "react" +import { keyframes } from "@emotion/core" + +export default ({ items, color }) => ( + + {items.map(item => ( + + {item} + + ))} + +) + +const topToBottom = keyframes({ + "0%": { + opacity: 0, + }, + "6%": { + opacity: 0, + }, + "21%": { + opacity: 1, + }, + "69%": { + opacity: 1, + }, + "84%": { + opacity: 0, + }, + "90%": { + opacity: 0, + }, + "100%": { + opacity: 0, + }, +}) diff --git a/www/src/pages/plugins.js b/www/src/pages/plugins.js index 83f23d59fb4c9..ecdb18b9961d4 100644 --- a/www/src/pages/plugins.js +++ b/www/src/pages/plugins.js @@ -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() { @@ -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`, }} @@ -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! + +

diff --git a/www/src/utils/styles.js b/www/src/utils/styles.js index fd1511b95ae6d..4a61d52b029bd 100644 --- a/www/src/utils/styles.js +++ b/www/src/utils/styles.js @@ -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": {