diff --git a/www/src/components/ecosystem/ecosystem-board.js b/www/src/components/ecosystem/ecosystem-board.js index a5f3f31cb4872..3f9f528ee530d 100644 --- a/www/src/components/ecosystem/ecosystem-board.js +++ b/www/src/components/ecosystem/ecosystem-board.js @@ -1,4 +1,4 @@ -import React from "react" +import React, { Component } from "react" import PropTypes from "prop-types" import styled from "react-emotion" @@ -20,46 +20,116 @@ const EcosystemBoardRoot = styled(`div`)` } ` -const EcosystemBoard = ({ - icons: { plugins: PluginsIcon, starters: StartersIcon }, - starters, - plugins, -}) => ( - - - - - -) +class EcosystemBoard extends Component { + observer + observerTargets = [] + + componentDidMount() { + if (typeof window.IntersectionObserver !== `undefined`) { + this.setupObserver() + } + } + + componentWillUnmount() { + if (typeof window.IntersectionObserver !== `undefined`) { + this.observerTargets.forEach(target => this.observer.unobserve(target)) + } + } + + setupObserver = () => { + const options = { rootMargin: `0px`, threshold: [1] } + this.observer = new IntersectionObserver(this.handleIntersect, options) + this.observerTargets = Array.from( + document.querySelectorAll(`.featuredItems`) + ) + + this.observerTargets.forEach(target => this.observer.observe(target)) + } + + handleIntersect = (entries, observer) => { + entries.forEach(entry => { + const target = entry.target + + if (entry.intersectionRatio > 0) { + setTimeout( + () => this.turnOnLeadScroll({ target, duration: 1000, distance: 20 }), + 250 + ) + this.observer.unobserve(target) + } + }) + } + + turnOnLeadScroll = ({ target, duration, distance }) => { + let startTime = null + + function animation(currentTime) { + if (startTime === null) { + startTime = currentTime + } + + const timeElapsed = currentTime - startTime + const getDistanceToScroll = ease(timeElapsed, 0, distance, duration) + + target.scroll({ top: 0, left: getDistanceToScroll }) + + if (timeElapsed < duration) { + requestAnimationFrame(animation) + } + } + + function ease(t, b, c, d) { + return -c * (t /= d) * (t - 2) + b + } + + requestAnimationFrame(animation) + } + + render() { + const { + icons: { plugins: PluginsIcon, starters: StartersIcon }, + starters, + plugins, + } = this.props + + return ( + + + + + + ) + } +} EcosystemBoard.propTypes = { icons: PropTypes.object, diff --git a/www/src/components/ecosystem/ecosystem-featured-items.js b/www/src/components/ecosystem/ecosystem-featured-items.js index 8f1f171fe98e6..e8198d7468503 100644 --- a/www/src/components/ecosystem/ecosystem-featured-items.js +++ b/www/src/components/ecosystem/ecosystem-featured-items.js @@ -11,6 +11,7 @@ import { scrollbarStyles } from "../../utils/styles" const EcosystemFeaturedItemsRoot = styled(`div`)` overflow-x: scroll; margin: ${rhythm(0.1)} -${rhythm(options.blockMarginBottom)}; + -webkit-overflow-scrolling: touch; ${presets.Tablet} { border-top: 1px solid ${colors.gray.superLight}; @@ -37,7 +38,7 @@ const List = styled(`ul`)` ` const EcosystemFeaturedItems = ({ items }) => ( - + {items.map(item => { const { slug } = item