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