From 5ca4acff061c147bee90315187a72d61dcd125dc Mon Sep 17 00:00:00 2001 From: Zachary Shilton <4624598+zchsh@users.noreply.github.com> Date: Mon, 29 Mar 2021 11:37:48 -0400 Subject: [PATCH] website: use global featured-slider component (#10254) * website: use global featured-slider component * website: delete unused local featured-slider --- .../featured-slider-section/index.jsx | 12 - .../featured-slider-section/style.css | 12 - .../components/featured-slider/StatusBar.jsx | 16 -- website/components/featured-slider/index.jsx | 221 ------------------ .../components/featured-slider/index.props.js | 41 ---- website/components/featured-slider/style.css | 176 -------------- website/package-lock.json | 34 +++ website/package.json | 1 + website/pages/style.css | 3 +- ...tomated-service-networking-with-consul.jsx | 6 +- ...ontainerized-application-orchestration.jsx | 6 +- .../simple-container-orchestration.jsx | 6 +- 12 files changed, 48 insertions(+), 486 deletions(-) delete mode 100644 website/components/featured-slider-section/index.jsx delete mode 100644 website/components/featured-slider-section/style.css delete mode 100644 website/components/featured-slider/StatusBar.jsx delete mode 100644 website/components/featured-slider/index.jsx delete mode 100644 website/components/featured-slider/index.props.js delete mode 100644 website/components/featured-slider/style.css diff --git a/website/components/featured-slider-section/index.jsx b/website/components/featured-slider-section/index.jsx deleted file mode 100644 index d8292dfb8..000000000 --- a/website/components/featured-slider-section/index.jsx +++ /dev/null @@ -1,12 +0,0 @@ -import FeaturedSlider from '../featured-slider' - -export default function FeaturedSliderSection({ heading, features }) { - return ( -
-
-

{heading}

- -
-
- ) -} diff --git a/website/components/featured-slider-section/style.css b/website/components/featured-slider-section/style.css deleted file mode 100644 index 80d4f16e3..000000000 --- a/website/components/featured-slider-section/style.css +++ /dev/null @@ -1,12 +0,0 @@ -.g-featured-slider-section { - background: var(--black); - padding-top: 128px; - padding-bottom: 128px; - color: var(--white); - - & h2 { - margin-top: 0; - color: var(--white); - text-align: center; - } -} diff --git a/website/components/featured-slider/StatusBar.jsx b/website/components/featured-slider/StatusBar.jsx deleted file mode 100644 index 3eb388f11..000000000 --- a/website/components/featured-slider/StatusBar.jsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react' - -export default function StatusBar({ theme, active, timing, brand }) { - return ( -
- -
- ) -} diff --git a/website/components/featured-slider/index.jsx b/website/components/featured-slider/index.jsx deleted file mode 100644 index 2ffaacb47..000000000 --- a/website/components/featured-slider/index.jsx +++ /dev/null @@ -1,221 +0,0 @@ -import React, { Component } from 'react' -import StatusBar from './StatusBar' -import marked from 'marked' -import Button from '@hashicorp/react-button' -import Image from '@hashicorp/react-image' - -class FeaturedSlider extends Component { - constructor(props) { - super(props) - const timing = this.props.timing ? parseInt(this.props.timing) : 10 - this.state = { - active: 0, - timing: timing, - numFrames: this.props.features.length, - measure: true, - containerWidth: 0, - } - - this.frames = [] - - this.handleClick = this.handleClick.bind(this) - this.throttledResize = this.throttledResize.bind(this) - this.measureFrameSize = this.measureFrameSize.bind(this) - this.resetTimer = this.resetTimer.bind(this) - this.resizeTimeout = null - } - - componentDidMount() { - if (this.state.numFrames > 1) { - this.timer = setInterval(() => this.tick(), this.state.timing * 1000) - this.measureFrameSize() - } - window.addEventListener('resize', this.throttledResize, false) - } - - componentWillUnmount() { - clearInterval(this.timer) - window.removeEventListener('resize', this.throttledResize) - } - - componentDidUpdate(prevProps, prevState) { - if (this.props.features !== prevProps.features) { - if (this.props.features.length != prevState.numFrames) { - this.setState( - { - numFrames: this.props.features.length, - measure: true, - }, - () => { - if (this.props.features.length === 1) { - clearInterval(this.timer) - window.removeEventListener('resize', this.throttledResize) - } - } - ) - } - if (prevState.active > this.props.features.length - 1) { - this.setState({ active: 0 }) - } - } - - if (this.props.timing && parseInt(this.props.timing) != prevState.timing) { - this.setState( - { - timing: parseInt(this.props.timing), - active: 0, - }, - this.resetTimer - ) - } - // If we're measuring on this update get the width - if (!prevState.measure && this.state.measure && this.state.numFrames > 1) { - this.measureFrameSize() - } - } - - resetTimer() { - clearInterval(this.timer) - this.timer = setInterval(() => this.tick(), this.state.timing * 1000) - } - - throttledResize() { - this.resizeTimeout && clearTimeout(this.resizeTimeout) - this.resizeTimeout = setTimeout(() => { - this.resizeTimeout = null - this.setState({ measure: true }) - }, 250) - } - - tick() { - const nextSlide = - this.state.active === this.state.numFrames - 1 ? 0 : this.state.active + 1 - this.setState({ active: nextSlide }) - } - - handleClick(i) { - if (i === this.state.active) return - this.setState({ active: i }, this.resetTimer) - } - - measureFrameSize() { - // All frames are the same size, so we measure the first one - if (this.frames[0]) { - const { width } = this.frames[0].getBoundingClientRect() - this.setState({ - frameSize: width, - containerWidth: width * this.state.numFrames, - measure: false, - }) - } - } - - render() { - // Clear our frames array so we don't keep old refs around - this.frames = [] - const { theme, brand, features } = this.props - const { measure, active, timing, numFrames, containerWidth } = this.state - - const single = numFrames === 1 - - // Create inline styling for slide container - // If we're measuring, or have a single slide then no inline styles should be applied - const containerStyle = - measure || single - ? {} - : { - width: `${containerWidth}px`, - transform: `translateX(-${(containerWidth / numFrames) * active}px`, - } - - // Create inline styling to apply to each frame - // If we're measuring or have a single slide then no inline styles should be applied - const frameStyle = - measure || single ? {} : { float: 'left', width: `${100 / numFrames}%` } - - return ( -
- {!single && ( -
- {features.map((feature, i) => ( -
this.handleClick(i)} - key={feature.logo.url} - > -
- {feature.logo.alt} -
- -
- ))} -
- )} -
-
- {/* React pushes a null ref the first time, so we're filtering those out. */} - {/* see https://reactjs.org/docs/refs-and-the-dom.html#caveats-with-callback-refs */} - {features.map((feature) => ( -
el && this.frames.push(el)} - key={feature.heading} - > -
-
- - {feature.image.alt} - -
-
- {single && ( -
- {feature.logo.alt} -
- )} -

-

-

-
-
- ))} -
-
-
- ) - } -} - -export default FeaturedSlider diff --git a/website/components/featured-slider/index.props.js b/website/components/featured-slider/index.props.js deleted file mode 100644 index 1b3887e27..000000000 --- a/website/components/featured-slider/index.props.js +++ /dev/null @@ -1,41 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' -import FeaturedSlider from './dist/index.js' - -function FeaturedSliderProps(props) { - return -} - -FeaturedSliderProps.propTypes = { - theme: PropTypes.oneOf(['light', 'dark']), - brand: PropTypes.oneOf([ - 'hashicorp', - 'terraform', - 'vault', - 'consul', - 'nomad', - 'packer', - 'vagrant', - ]), - features: PropTypes.arrayOf( - PropTypes.shape({ - logo: PropTypes.shape({ - url: PropTypes.string, - alt: PropTypes.string, - }), - image: PropTypes.shape({ - url: PropTypes.string, - alt: PropTypes.string, - }), - heading: PropTypes.string, - content: PropTypes.string, - link: PropTypes.shape({ - text: PropTypes.string, - url: PropTypes.string, - type: PropTypes.oneOf(['anchor', 'inbound', 'outbound']), - }), - }) - ), -} - -export default FeaturedSliderProps diff --git a/website/components/featured-slider/style.css b/website/components/featured-slider/style.css deleted file mode 100644 index 5924b7d1f..000000000 --- a/website/components/featured-slider/style.css +++ /dev/null @@ -1,176 +0,0 @@ -.g-featured-slider { - & .logo-bar-container { - display: flex; - padding: 32px 0; - align-items: center; - justify-content: center; - - & .logo-bar { - flex-basis: 33.333%; - cursor: pointer; - position: relative; - transition: transform 0.2s ease; - margin-right: 32px; - - &:last-child { - margin-right: 0; - } - - & .logo-container { - height: 84px; - text-align: center; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - padding: 24px; - - & picture, - & img { - object-fit: contain; - width: 100%; - height: 100%; - } - - @media (min-width: 768px) { - height: 92px; - padding: 32px; - } - } - - & .progress-bar { - width: 100%; - height: 2px; - display: block; - background-color: var(--DEPRECATED-gray-9); - - &.dark { - background-color: var(--DEPRECATED-gray-3); - } - - & span { - width: 0; - background-color: var(--brand); - height: 100%; - display: block; - animation-duration: 10s; - &.nomad { - background-color: var(--nomad); - } - &.consul { - background-color: var(--consul); - } - &.terraform { - background-color: var(--terraform); - } - &.active { - animation-name: case-study-bar; - animation-timing-function: linear; - } - } - } - - &:hover { - transform: translateY(-4px); - } - } - - /* When there are two case studies */ - &.double { - & .logo-bar { - flex-basis: 50%; - } - } - - @media (min-width: 768px) { - padding: 0 0 48px; - } - } - - & .feature-container { - overflow: hidden; - - & .slider-container { - transition: transform 400ms ease-out; - - & .slider-frame { - & .feature { - & .feature-image { - margin-bottom: 2rem; - - & img, - & picture { - width: 100%; - height: auto; - } - } - - & .feature-content { - text-align: center; - - & h3 { - margin: 0 0 8px; - } - - & .single-logo { - margin-bottom: 32px; - width: 100%; - height: 65px; - - & picture, - & img { - height: 100%; - width: auto; - } - } - - & .g-btn { - margin-top: 32px; - } - } - - @media (min-width: 768px) { - display: flex; - flex-direction: row; - flex-wrap: nowrap; - align-items: center; - - & .feature-image { - margin-bottom: 0; - flex-basis: 60%; - margin-right: 64px; - } - - & .feature-content { - flex-basis: 40%; - text-align: left; - - & p { - margin: 0; - - & + p { - margin-top: 1em; - } - } - } - } - } - - &.single { - & .case-study { - align-items: flex-start; - } - } - } - } - } -} - -@keyframes case-study-bar { - 0% { - width: 0; - } - 100% { - width: 100%; - } -} diff --git a/website/package-lock.json b/website/package-lock.json index e9d5d3098..766845280 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -1556,6 +1556,40 @@ "@hashicorp/js-utils": "^1.0.10" } }, + "@hashicorp/react-featured-slider": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@hashicorp/react-featured-slider/-/react-featured-slider-2.0.0.tgz", + "integrity": "sha512-JShdDxe3+3xGh2d4VsfautZxih/qG6QAmSVbt2TtaCaEVm7lVdJ1e4uo0QQ5zTlrlrpBNacD23ZXWIgMJYZY9g==", + "requires": { + "@hashicorp/react-button": "^2.2.6", + "@hashicorp/react-image": "^2.0.3" + }, + "dependencies": { + "@hashicorp/react-button": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@hashicorp/react-button/-/react-button-2.3.0.tgz", + "integrity": "sha512-1C6V8OxadkdDAkwgItDfNxx7ns9EB6znK39V94RBiPvElmsNLCEG7zujcQX71V2n+HMSv1JPgDvXp4WLICzK+Q==", + "requires": { + "@hashicorp/react-inline-svg": "^1.0.0", + "slugify": "^1.3.6" + } + }, + "@hashicorp/react-image": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@hashicorp/react-image/-/react-image-2.0.4.tgz", + "integrity": "sha512-rJCx74lxQE9l9LpFhlxSjQ0yjrzjce5uzEGmMgPvMsNiQtgetjNyeg1p5N8k7xRGYXNapt8uY2kZiE69OyL9cQ==", + "requires": { + "object-assign": "^4.1.1", + "query-string": "5.1.1" + } + }, + "@hashicorp/react-inline-svg": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@hashicorp/react-inline-svg/-/react-inline-svg-1.0.2.tgz", + "integrity": "sha512-AAFnBslSTgnEr++dTbMn3sybAqvn7myIj88ijGigF6u11eSRiV64zqEcyYLQKWTV6dF4AvYoxiYC6GSOgiM0Yw==" + } + } + }, "@hashicorp/react-global-styles": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/@hashicorp/react-global-styles/-/react-global-styles-4.6.1.tgz", diff --git a/website/package.json b/website/package.json index ee1459065..d1a483f19 100644 --- a/website/package.json +++ b/website/package.json @@ -14,6 +14,7 @@ "@hashicorp/react-call-to-action": "1.0.3", "@hashicorp/react-content": "6.2.0", "@hashicorp/react-docs-page": "10.6.0", + "@hashicorp/react-featured-slider": "^2.0.0", "@hashicorp/react-hashi-stack-menu": "^1.1.0", "@hashicorp/react-hero": "4.1.0", "@hashicorp/react-image": "3.0.3", diff --git a/website/pages/style.css b/website/pages/style.css index 5a85b6c52..d4b410802 100644 --- a/website/pages/style.css +++ b/website/pages/style.css @@ -20,6 +20,7 @@ @import '~@hashicorp/react-docs-page/style.css'; @import '~@hashicorp/react-docs-sidenav/style.css'; @import '~@hashicorp/react-enterprise-alert/style.css'; +@import '~@hashicorp/react-featured-slider/style.css'; @import '~@hashicorp/react-hero/style.css'; @import '~@hashicorp/react-product-downloader/dist/style.css'; @import '~@hashicorp/react-search/style.css'; @@ -37,8 +38,6 @@ @import '../components/enterprise-info/style.css'; @import '../components/mini-cta/style.css'; @import '../components/homepage-hero/style.css'; -@import '../components/featured-slider/style.css'; -@import '../components/featured-slider-section/style.css'; @import '../components/learn-nomad/style.css'; @import '../components/basic-hero/style.css'; @import '../components/footer/style.css'; diff --git a/website/pages/use-cases/automated-service-networking-with-consul.jsx b/website/pages/use-cases/automated-service-networking-with-consul.jsx index 6bb829a1c..3abb8598c 100644 --- a/website/pages/use-cases/automated-service-networking-with-consul.jsx +++ b/website/pages/use-cases/automated-service-networking-with-consul.jsx @@ -1,6 +1,6 @@ import UseCasesLayout from 'components/use-case-page' import TextSplitWithImage from '@hashicorp/react-text-split-with-image' -import FeaturedSliderSection from 'components/featured-slider-section' +import FeaturedSlider from '@hashicorp/react-featured-slider' export default function AutomatedServiceNetworkingWithConsulPage() { return ( @@ -71,8 +71,10 @@ export default function AutomatedServiceNetworkingWithConsulPage() { }} /> - - -