diff --git a/js/components/App.js b/js/components/App.js index 26d6537..f11ee96 100644 --- a/js/components/App.js +++ b/js/components/App.js @@ -1,4 +1,5 @@ import React from 'react'; +import classNames from 'classnames'; import { connect } from 'react-redux'; import actions from '../actions'; @@ -13,7 +14,7 @@ function App(props) {
-
+
diff --git a/js/components/Fadeable.js b/js/components/Fadeable.js new file mode 100644 index 0000000..66f5efb --- /dev/null +++ b/js/components/Fadeable.js @@ -0,0 +1,45 @@ +import React from 'react'; +import classNames from 'classnames'; + +class Fadeable extends React.Component { + constructor(props) { + super(props); + this.state = { + faded: props.leaving, + }; + } + + componentWillReceiveProps({ leaving }) { + if (!this.props.leaving && leaving) { + this.setState({ + ...this.state, + faded: true, + }); + } + if (this.props.leaving && !leaving) { + this.setState({ + ...this.state, + faded: false, + }); + } + } + + handleTransitionEnd = () => { + if (this.state.faded) { + this.props.onLeave(); + } + }; + + render() { + return ( +
+ {this.props.children} +
+ ); + } +} + +export default Fadeable; diff --git a/js/components/PageHelp.js b/js/components/PageHelp.js index a27c016..74a1178 100644 --- a/js/components/PageHelp.js +++ b/js/components/PageHelp.js @@ -1,10 +1,11 @@ import React from 'react'; import HeroHeadline from './HeroHeadline'; +import Fadeable from './Fadeable'; -export default function PageHelp() { +export default function PageHelp({ leaving, onLeave }) { return ( -
+ How to use AOE Technology Radar -
+ ); } diff --git a/js/components/PageIndex.js b/js/components/PageIndex.js index e79f869..0a502db 100644 --- a/js/components/PageIndex.js +++ b/js/components/PageIndex.js @@ -1,14 +1,15 @@ import React from 'react'; import HeroHeadline from './HeroHeadline'; import QuadrantGrid from './QuadrantGrid'; +import Fadeable from './Fadeable'; -export default function PageIndex({ items, navigate }) { +export default function PageIndex({ leaving, onLeave, items, navigate }) { return ( -
+
AOE Technology Radar
-
+ ); } diff --git a/js/components/PageItem.js b/js/components/PageItem.js index cc66e73..03e67a3 100644 --- a/js/components/PageItem.js +++ b/js/components/PageItem.js @@ -3,49 +3,53 @@ import HeroHeadline from './HeroHeadline'; import Badge from './Badge'; import ItemList from './ItemList'; import Link from './Link'; +import Fadeable from './Fadeable'; + import { groupByQuadrants } from '../../common/model'; -export default function PageItems({ pageName, items }) { +export default function PageItems({ leaving, onLeave, pageName, items }) { const [quadrantName, itemName] = pageName.split('/'); const item = items.filter(item => item.quadrant === quadrantName && item.name === itemName)[0]; const itemsInRing = groupByQuadrants(items)[item.quadrant][item.ring]; return ( -
-
-
-
-

Languages & Frameworks

-
- -
-
- {item.ring} + +
+
+
+
+

Languages & Frameworks

+
+ +
+
+ {item.ring} +
+
+ + Quadrant Overview + +
-
- - Quadrant Overview - -
-
- -
-
-
-
-
-
-
-

{item.title}

-
-
- {item.ring} + +
+
+
+
+
+
+
+

{item.title}

+
+
+ {item.ring} +
+
-
-
+ ); } diff --git a/js/components/PageOverview.js b/js/components/PageOverview.js index 8f25937..b2025c8 100644 --- a/js/components/PageOverview.js +++ b/js/components/PageOverview.js @@ -4,6 +4,7 @@ import HeadlineGroup from './HeadlineGroup'; import HeroHeadline from './HeroHeadline'; import Badge from './Badge'; import Link from './Link'; +import Fadeable from './Fadeable'; import { groupByFirstLetter } from '../../common/model'; import { translate } from '../../common/config'; @@ -45,7 +46,7 @@ class PageOverview extends React.Component { const groups = this.getFilteredAndGroupedItems(); return ( -
+ Technologies Overview @@ -106,7 +107,7 @@ class PageOverview extends React.Component { }
-
+ ); } } diff --git a/js/components/PageQuadrant.js b/js/components/PageQuadrant.js index cb2f5fb..b4091fb 100644 --- a/js/components/PageQuadrant.js +++ b/js/components/PageQuadrant.js @@ -2,17 +2,19 @@ import React from 'react'; import HeroHeadline from './HeroHeadline'; import HeadlineGroup from './HeadlineGroup'; import QuadrantSection from './QuadrantSection'; +import Fadeable from './Fadeable'; + import { translate } from '../../common/config'; import { groupByQuadrants } from '../../common/model'; -export default function PageQuadrant({ pageName, items }) { +export default function PageQuadrant({ leaving, onLeave, pageName, items }) { const groups = groupByQuadrants(items); return ( -
+ {translate(pageName)} -
+ ); } diff --git a/js/components/Router.js b/js/components/Router.js index 1002355..dba1bd8 100644 --- a/js/components/Router.js +++ b/js/components/Router.js @@ -27,7 +27,46 @@ const getPageByName = (items, pageName) => { return 'div'; } -export default function Router({ pageName, ...props}) { - const Comp = getPageByName(props.items, pageName); - return ; +class Router extends React.Component { + constructor(props) { + super(props); + this.state = { + pageName: props.pageName, + leaving: false, + }; + } + + componentWillReceiveProps({ pageName }) { + this.setState({ + ...this.state, + nextPageName: pageName, + leaving: true, + }); + } + + handlePageLeave = () => { + this.setState({ + ...this.state, + pageName: this.state.nextPageName, + leaving: true, + nextPageName: null, + }); + + window.setTimeout(() => { + window.requestAnimationFrame(() => { + this.setState({ + ...this.state, + leaving: false, + }); + }); + }, 0); + }; + + render() { + const { pageName, leaving } = this.state; + const Comp = getPageByName(this.props.items, pageName); + return ; + } } + +export default Router; diff --git a/styles/components/fadeable.css b/styles/components/fadeable.css new file mode 100644 index 0000000..ad72fe6 --- /dev/null +++ b/styles/components/fadeable.css @@ -0,0 +1,23 @@ +.fadable { + position: relative; + + &::after { + transition: opacity 0.2s cubic-bezier(0.54, 0, 0.28, 1); + content: ''; + display: block; + width: 100%; + height: 100%; + position: absolute; + left: 0; + top: 0; + opacity: 0; + background: var(--color-gray-dark); + pointer-events: none; + } + + &.is-faded { + &::after { + opacity: 1; + } + } +}