Add Fadable component
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import actions from '../actions';
|
import actions from '../actions';
|
||||||
@@ -13,7 +14,7 @@ function App(props) {
|
|||||||
<div className="page__header">
|
<div className="page__header">
|
||||||
<Header {...props} />
|
<Header {...props} />
|
||||||
</div>
|
</div>
|
||||||
<div className="page__content">
|
<div className={classNames('page__content', { 'is-faded': props.isFaded })}>
|
||||||
<Router {...props} />
|
<Router {...props} />
|
||||||
</div>
|
</div>
|
||||||
<div className="page__footer">
|
<div className="page__footer">
|
||||||
|
|||||||
45
js/components/Fadeable.js
Normal file
45
js/components/Fadeable.js
Normal file
@@ -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 (
|
||||||
|
<div
|
||||||
|
className={classNames('fadable', { 'is-faded': this.state.faded })}
|
||||||
|
onTransitionEnd={this.handleTransitionEnd}
|
||||||
|
>
|
||||||
|
{this.props.children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Fadeable;
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import HeroHeadline from './HeroHeadline';
|
import HeroHeadline from './HeroHeadline';
|
||||||
|
import Fadeable from './Fadeable';
|
||||||
|
|
||||||
export default function PageHelp() {
|
export default function PageHelp({ leaving, onLeave }) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<Fadeable leaving={leaving} onLeave={onLeave}>
|
||||||
<HeroHeadline>How to use AOE Technology Radar</HeroHeadline>
|
<HeroHeadline>How to use AOE Technology Radar</HeroHeadline>
|
||||||
</div>
|
</Fadeable>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import HeroHeadline from './HeroHeadline';
|
import HeroHeadline from './HeroHeadline';
|
||||||
import QuadrantGrid from './QuadrantGrid';
|
import QuadrantGrid from './QuadrantGrid';
|
||||||
|
import Fadeable from './Fadeable';
|
||||||
|
|
||||||
export default function PageIndex({ items, navigate }) {
|
export default function PageIndex({ leaving, onLeave, items, navigate }) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<Fadeable leaving={leaving} onLeave={onLeave}>
|
||||||
<div className="headline-group">
|
<div className="headline-group">
|
||||||
<HeroHeadline alt="Mar 2017">AOE Technology Radar</HeroHeadline>
|
<HeroHeadline alt="Mar 2017">AOE Technology Radar</HeroHeadline>
|
||||||
</div>
|
</div>
|
||||||
<QuadrantGrid items={items} />
|
<QuadrantGrid items={items} />
|
||||||
</div>
|
</Fadeable>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,49 +3,53 @@ import HeroHeadline from './HeroHeadline';
|
|||||||
import Badge from './Badge';
|
import Badge from './Badge';
|
||||||
import ItemList from './ItemList';
|
import ItemList from './ItemList';
|
||||||
import Link from './Link';
|
import Link from './Link';
|
||||||
|
import Fadeable from './Fadeable';
|
||||||
|
|
||||||
import { groupByQuadrants } from '../../common/model';
|
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 [quadrantName, itemName] = pageName.split('/');
|
||||||
const item = items.filter(item => item.quadrant === quadrantName && item.name === itemName)[0];
|
const item = items.filter(item => item.quadrant === quadrantName && item.name === itemName)[0];
|
||||||
const itemsInRing = groupByQuadrants(items)[item.quadrant][item.ring];
|
const itemsInRing = groupByQuadrants(items)[item.quadrant][item.ring];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="item-page">
|
<Fadeable leaving={leaving} onLeave={onLeave}>
|
||||||
<div className="item-page__nav">
|
<div className="item-page">
|
||||||
<div className="item-page__nav__inner">
|
<div className="item-page__nav">
|
||||||
<div className="item-page__header">
|
<div className="item-page__nav__inner">
|
||||||
<h3 className="headline">Languages & Frameworks</h3>
|
<div className="item-page__header">
|
||||||
</div>
|
<h3 className="headline">Languages & Frameworks</h3>
|
||||||
<ItemList items={itemsInRing} activeItem={item}>
|
</div>
|
||||||
<div className="split">
|
<ItemList items={itemsInRing} activeItem={item}>
|
||||||
<div className="split__left">
|
<div className="split">
|
||||||
<Badge big type={item.ring}>{item.ring}</Badge>
|
<div className="split__left">
|
||||||
|
<Badge big type={item.ring}>{item.ring}</Badge>
|
||||||
|
</div>
|
||||||
|
<div className="split__right">
|
||||||
|
<Link className="icon-link" pageName={item.quadrant}>
|
||||||
|
<span className="icon icon--pie icon-link__icon"></span>Quadrant Overview
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="split__right">
|
</ItemList>
|
||||||
<Link className="icon-link" pageName={item.quadrant}>
|
</div>
|
||||||
<span className="icon icon--pie icon-link__icon"></span>Quadrant Overview
|
</div>
|
||||||
</Link>
|
<div className="item-page__content">
|
||||||
</div>
|
<div className="item-page__content__inner">
|
||||||
</div>
|
<div className="item-page__header">
|
||||||
</ItemList>
|
<div className="split">
|
||||||
</div>
|
<div className="split__left">
|
||||||
</div>
|
<h1 className="hero-headline hero-headline--inverse">{item.title}</h1>
|
||||||
<div className="item-page__content">
|
</div>
|
||||||
<div className="item-page__content__inner">
|
<div className="split__right">
|
||||||
<div className="item-page__header">
|
<Badge big type={item.ring}>{item.ring}</Badge>
|
||||||
<div className="split">
|
</div>
|
||||||
<div className="split__left">
|
|
||||||
<h1 className="hero-headline hero-headline--inverse">{item.title}</h1>
|
|
||||||
</div>
|
|
||||||
<div className="split__right">
|
|
||||||
<Badge big type={item.ring}>{item.ring}</Badge>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="markdown" dangerouslySetInnerHTML={{__html: item.body}} />
|
||||||
</div>
|
</div>
|
||||||
<div className="markdown" dangerouslySetInnerHTML={{__html: item.body}} />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Fadeable>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import HeadlineGroup from './HeadlineGroup';
|
|||||||
import HeroHeadline from './HeroHeadline';
|
import HeroHeadline from './HeroHeadline';
|
||||||
import Badge from './Badge';
|
import Badge from './Badge';
|
||||||
import Link from './Link';
|
import Link from './Link';
|
||||||
|
import Fadeable from './Fadeable';
|
||||||
import { groupByFirstLetter } from '../../common/model';
|
import { groupByFirstLetter } from '../../common/model';
|
||||||
import { translate } from '../../common/config';
|
import { translate } from '../../common/config';
|
||||||
|
|
||||||
@@ -45,7 +46,7 @@ class PageOverview extends React.Component {
|
|||||||
const groups = this.getFilteredAndGroupedItems();
|
const groups = this.getFilteredAndGroupedItems();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<Fadeable leaving={this.props.leaving} onLeave={this.props.onLeave}>
|
||||||
<HeadlineGroup>
|
<HeadlineGroup>
|
||||||
<HeroHeadline>Technologies Overview</HeroHeadline>
|
<HeroHeadline>Technologies Overview</HeroHeadline>
|
||||||
</HeadlineGroup>
|
</HeadlineGroup>
|
||||||
@@ -106,7 +107,7 @@ class PageOverview extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Fadeable>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,17 +2,19 @@ import React from 'react';
|
|||||||
import HeroHeadline from './HeroHeadline';
|
import HeroHeadline from './HeroHeadline';
|
||||||
import HeadlineGroup from './HeadlineGroup';
|
import HeadlineGroup from './HeadlineGroup';
|
||||||
import QuadrantSection from './QuadrantSection';
|
import QuadrantSection from './QuadrantSection';
|
||||||
|
import Fadeable from './Fadeable';
|
||||||
|
|
||||||
import { translate } from '../../common/config';
|
import { translate } from '../../common/config';
|
||||||
import { groupByQuadrants } from '../../common/model';
|
import { groupByQuadrants } from '../../common/model';
|
||||||
|
|
||||||
export default function PageQuadrant({ pageName, items }) {
|
export default function PageQuadrant({ leaving, onLeave, pageName, items }) {
|
||||||
const groups = groupByQuadrants(items);
|
const groups = groupByQuadrants(items);
|
||||||
return (
|
return (
|
||||||
<div>
|
<Fadeable leaving={leaving} onLeave={onLeave}>
|
||||||
<HeadlineGroup>
|
<HeadlineGroup>
|
||||||
<HeroHeadline>{translate(pageName)}</HeroHeadline>
|
<HeroHeadline>{translate(pageName)}</HeroHeadline>
|
||||||
</HeadlineGroup>
|
</HeadlineGroup>
|
||||||
<QuadrantSection groups={groups} quadrantName={pageName} big />
|
<QuadrantSection groups={groups} quadrantName={pageName} big />
|
||||||
</div>
|
</Fadeable>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,46 @@ const getPageByName = (items, pageName) => {
|
|||||||
return 'div';
|
return 'div';
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Router({ pageName, ...props}) {
|
class Router extends React.Component {
|
||||||
const Comp = getPageByName(props.items, pageName);
|
constructor(props) {
|
||||||
return <Comp {...props} pageName={pageName} />;
|
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 <Comp {...this.props} pageName={pageName} leaving={leaving} onLeave={this.handlePageLeave} />;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default Router;
|
||||||
|
|||||||
23
styles/components/fadeable.css
Normal file
23
styles/components/fadeable.css
Normal file
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user