Tidy up new React + API explorer for mobile (fixes #3607) (#3635)

* Remove useless CSS declaration

* Remove commented out styles

* Merge duplicate declarations

* Remove even more commented out code

* Move footer mq to footer declaration

* Remove more useless code

* Stop vendor prefixing for IE below 11

* Remove useless vendor prefixing

* Merge identical declarations

* Fix 1px overflow in content wrapper

* Fix explorer scrolling when open on mobile

* Remove unused import

* Add Redux performance measurements to explorer menu

* Rewrite explorer reducer to avoid unnecessary operations

* Stop changing reducer state on every action regardless of type

* Remove redundant children.isFetching property in nodes reducer

* Remove redundant children.isLoaded property in nodes reducer

* Remove redundant children.isError property in nodes reducer

* Refactor nodes explorer reducer with sub-reducer

* Fix linting issue

* Remove unused class name

* Change default icon className from empty string to null

* Remove old TODO comment

* Hoist icons in ExplorerItem component for better performance

* Add comment

* Add tooling for performance measurement of React components

* Clean up explorer panel component definition

* Make performance measurements opt-in

* Improve alignment of page explorer menu on mobile

* Close explorer on touchend rather than touchstart

* Comment out performance measurement code

* Remove fade transition completely
This commit is contained in:
Thibaud Colas 2017-06-09 00:08:04 +03:00 committed by GitHub
parent ea8ab5de45
commit 61b6de2e4e
24 changed files with 278 additions and 211 deletions

View file

@ -3,6 +3,7 @@ $c-explorer-bg-dark: $color-grey-1;
$c-explorer-bg-active: rgba(0,0,0,0.425);
$c-explorer-secondary: #a5a5a5;
$c-explorer-easing: cubic-bezier(0.075, 0.820, 0.165, 1.000);
$menu-footer-height: 50px;
@import 'ExplorerItem';
@ -92,7 +93,6 @@ $c-explorer-easing: cubic-bezier(0.075, 0.820, 0.165, 1.000);
.c-explorer__header {
display: block;
height: 50px;
background-color: $c-explorer-bg-dark;
border-bottom: 1px solid $c-explorer-bg-dark;
color: $color-white;
@ -114,7 +114,7 @@ $c-explorer-easing: cubic-bezier(0.075, 0.820, 0.165, 1.000);
}
.c-explorer__header__inner {
padding: 1rem;
padding: 1em .75em;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
@ -124,17 +124,24 @@ $c-explorer-easing: cubic-bezier(0.075, 0.820, 0.165, 1.000);
margin-right: .25rem;
font-size: 1rem;
}
@include medium {
padding: 1em 1.5em;
}
}
.c-explorer__placeholder {
padding: 1rem;
padding: 1em;
color: $color-white;
@include medium {
padding: 1em 1.75em;
}
}
.c-explorer__see-more {
display: block;
padding: 1rem;
height: 50px;
padding: 1em;
background: rgba(0,0,0,0.3);
color: $color-white;
@ -152,4 +159,9 @@ $c-explorer-easing: cubic-bezier(0.075, 0.820, 0.165, 1.000);
@include hover {
background: $c-explorer-bg-active;
}
@include medium {
padding: 1em 1.75em;
height: $menu-footer-height;
}
}

View file

@ -6,6 +6,23 @@ import Icon from '../../components/Icon/Icon';
import Button from '../../components/Button/Button';
import PublicationStatus from '../../components/PublicationStatus/PublicationStatus';
// Hoist icons in the explorer item, as it is re-rendered many times.
const childrenIcon = (
<Icon name="folder-inverse" />
);
const editIcon = (
<Icon name="edit" title={STRINGS.EDIT} />
);
const nextIcon = (
<Icon name="arrow-right" title={STRINGS.SEE_CHILDREN} />
);
/**
* One menu item in the page explorer, with different available actions
* and information depending on the metadata of the page.
*/
const ExplorerItem = ({ item, onClick }) => {
const { id, title, meta } = item;
const hasChildren = meta.children.count > 0;
@ -14,9 +31,7 @@ const ExplorerItem = ({ item, onClick }) => {
return (
<div className="c-explorer__item">
<Button href={`${ADMIN_URLS.PAGES}${id}/`} className="c-explorer__item__link">
{hasChildren ? (
<Icon name="folder-inverse" className={'c-explorer__children'} />
) : null}
{hasChildren ? childrenIcon : null}
<h3 className="c-explorer__item__title">
{title}
@ -32,14 +47,14 @@ const ExplorerItem = ({ item, onClick }) => {
href={`${ADMIN_URLS.PAGES}${id}/edit/`}
className="c-explorer__item__action c-explorer__item__action--small"
>
<Icon name="edit" title={`${STRINGS.EDIT} '${title}'`} />
{editIcon}
</Button>
{hasChildren ? (
<Button
className="c-explorer__item__action"
onClick={onClick}
>
<Icon name="arrow-right" title={STRINGS.SEE_CHILDREN} />
{nextIcon}
</Button>
) : null}
</div>

View file

@ -8,7 +8,7 @@
display: inline-flex;
align-items: center;
flex-grow: 1;
padding: 1.45em 1.75em;
padding: 1.45em 1em;
cursor: pointer;
&:focus {
@ -25,6 +25,10 @@
@include hover {
background: $c-explorer-bg-active;
}
@include medium {
padding: 1.45em 1.75em;
}
}
.c-explorer__item__link .icon {

View file

@ -6,12 +6,16 @@ import { STRINGS, MAX_EXPLORER_PAGES } from '../../config/wagtailConfig';
import Button from '../Button/Button';
import LoadingSpinner from '../LoadingSpinner/LoadingSpinner';
import Transition, { PUSH, POP, FADE } from '../Transition/Transition';
import Transition, { PUSH, POP } from '../Transition/Transition';
import ExplorerHeader from './ExplorerHeader';
import ExplorerItem from './ExplorerItem';
import PageCount from './PageCount';
export default class ExplorerPanel extends React.Component {
/**
* The main panel of the page explorer menu, with heading,
* menu items, and special states.
*/
class ExplorerPanel extends React.Component {
constructor(props) {
super(props);
@ -38,14 +42,14 @@ export default class ExplorerPanel extends React.Component {
document.querySelector('[data-explorer-menu-item]').classList.add('submenu-active');
document.body.classList.add('explorer-open');
document.addEventListener('mousedown', this.clickOutside);
document.addEventListener('touchstart', this.clickOutside);
document.addEventListener('touchend', this.clickOutside);
}
componentWillUnmount() {
document.querySelector('[data-explorer-menu-item]').classList.remove('submenu-active');
document.body.classList.remove('explorer-open');
document.removeEventListener('mousedown', this.clickOutside);
document.removeEventListener('touchstart', this.clickOutside);
document.removeEventListener('touchend', this.clickOutside);
}
clickOutside(e) {
@ -136,7 +140,10 @@ export default class ExplorerPanel extends React.Component {
tag="nav"
className="explorer"
paused={paused || !page || page.isFetching}
focusTrapOptions={{ onDeactivate: onClose }}
focusTrapOptions={{
initialFocus: '.c-explorer__close',
onDeactivate: onClose,
}}
>
<Button className="c-explorer__close u-hidden" onClick={onClose}>
{STRINGS.CLOSE_EXPLORER}
@ -163,14 +170,17 @@ export default class ExplorerPanel extends React.Component {
ExplorerPanel.propTypes = {
nodes: PropTypes.object.isRequired,
path: PropTypes.array,
path: PropTypes.array.isRequired,
page: PropTypes.shape({
isFetching: PropTypes.bool,
children: PropTypes.shape({
count: PropTypes.number,
items: PropTypes.array,
}),
}),
}).isRequired,
onClose: PropTypes.func.isRequired,
popPage: PropTypes.func.isRequired,
pushPage: PropTypes.func.isRequired,
};
export default ExplorerPanel;

View file

@ -46,12 +46,10 @@ exports[`Explorer visible 1`] = `
"1": Object {
"children": Object {
"count": 0,
"isFetching": true,
"items": Array [],
},
"isError": false,
"isFetching": true,
"isLoaded": true,
"meta": Object {
"children": Object {},
},
@ -101,12 +99,10 @@ exports[`Explorer visible 2`] = `
"1": Object {
"children": Object {
"count": 0,
"isFetching": true,
"items": Array [],
},
"isError": false,
"isFetching": true,
"isLoaded": true,
"meta": Object {
"children": Object {},
},
@ -118,12 +114,10 @@ exports[`Explorer visible 2`] = `
Object {
"children": Object {
"count": 0,
"isFetching": true,
"items": Array [],
},
"isError": false,
"isFetching": true,
"isLoaded": true,
"meta": Object {
"children": Object {},
},

View file

@ -15,7 +15,7 @@ exports[`ExplorerHeader #depth at root 1`] = `
className="c-explorer__header__inner"
>
<Icon
className=""
className={null}
name="home"
title={null}
/>
@ -41,7 +41,7 @@ exports[`ExplorerHeader #page 1`] = `
className="c-explorer__header__inner"
>
<Icon
className=""
className={null}
name="arrow-left"
title={null}
/>
@ -67,7 +67,7 @@ exports[`ExplorerHeader basic 1`] = `
className="c-explorer__header__inner"
>
<Icon
className=""
className={null}
name="arrow-left"
title={null}
/>

View file

@ -15,7 +15,7 @@ exports[`ExplorerItem children 1`] = `
target={null}
>
<Icon
className="c-explorer__children"
className={null}
name="folder-inverse"
title={null}
/>
@ -36,9 +36,9 @@ exports[`ExplorerItem children 1`] = `
target={null}
>
<Icon
className=""
className={null}
name="edit"
title="Edit 'test'"
title="Edit"
/>
</Button>
<Button
@ -52,7 +52,7 @@ exports[`ExplorerItem children 1`] = `
target={null}
>
<Icon
className=""
className={null}
name="arrow-right"
title="See children"
/>
@ -91,9 +91,9 @@ exports[`ExplorerItem renders 1`] = `
target={null}
>
<Icon
className=""
className={null}
name="edit"
title="Edit 'test'"
title="Edit"
/>
</Button>
</div>
@ -114,7 +114,7 @@ exports[`ExplorerItem should show a publication status if not live 1`] = `
target={null}
>
<Icon
className="c-explorer__children"
className={null}
name="folder-inverse"
title={null}
/>
@ -148,9 +148,9 @@ exports[`ExplorerItem should show a publication status if not live 1`] = `
target={null}
>
<Icon
className=""
className={null}
name="edit"
title="Edit 'test'"
title="Edit"
/>
</Button>
<Button
@ -164,7 +164,7 @@ exports[`ExplorerItem should show a publication status if not live 1`] = `
target={null}
>
<Icon
className=""
className={null}
name="arrow-right"
title="See children"
/>
@ -187,7 +187,7 @@ exports[`ExplorerItem should show a publication status with unpublished changes
target={null}
>
<Icon
className="c-explorer__children"
className={null}
name="folder-inverse"
title={null}
/>
@ -221,9 +221,9 @@ exports[`ExplorerItem should show a publication status with unpublished changes
target={null}
>
<Icon
className=""
className={null}
name="edit"
title="Edit 'test'"
title="Edit"
/>
</Button>
<Button
@ -237,7 +237,7 @@ exports[`ExplorerItem should show a publication status with unpublished changes
target={null}
>
<Icon
className=""
className={null}
name="arrow-right"
title="See children"
/>

View file

@ -7,6 +7,7 @@ exports[`ExplorerPanel #isError 1`] = `
className="explorer"
focusTrapOptions={
Object {
"initialFocus": ".c-explorer__close",
"onDeactivate": [Function],
}
}
@ -78,6 +79,7 @@ exports[`ExplorerPanel #isFetching 1`] = `
className="explorer"
focusTrapOptions={
Object {
"initialFocus": ".c-explorer__close",
"onDeactivate": [Function],
}
}
@ -139,6 +141,7 @@ exports[`ExplorerPanel #items 1`] = `
className="explorer"
focusTrapOptions={
Object {
"initialFocus": ".c-explorer__close",
"onDeactivate": [Function],
}
}
@ -224,6 +227,7 @@ exports[`ExplorerPanel no children 1`] = `
className="explorer"
focusTrapOptions={
Object {
"initialFocus": ".c-explorer__close",
"onDeactivate": [Function],
}
}
@ -281,6 +285,7 @@ exports[`ExplorerPanel renders 1`] = `
className="explorer"
focusTrapOptions={
Object {
"initialFocus": ".c-explorer__close",
"onDeactivate": [Function],
}
}

View file

@ -11,7 +11,7 @@ exports[`PageCount #title 1`] = `
5 pages
</span>
<Icon
className=""
className={null}
name="arrow-right"
title={null}
/>
@ -29,7 +29,7 @@ exports[`PageCount plural 1`] = `
5 pages
</span>
<Icon
className=""
className={null}
name="arrow-right"
title={null}
/>
@ -47,7 +47,7 @@ exports[`PageCount works 1`] = `
1 page
</span>
<Icon
className=""
className={null}
name="arrow-right"
title={null}
/>

View file

@ -87,7 +87,7 @@ export function pushPage(id) {
dispatch(pushPagePrivate(id));
if (page && !page.children.isFetching && !page.children.isLoaded) {
if (page && !page.isFetching && !page.children.count > 0) {
dispatch(getChildren(id));
}
};

View file

@ -12,10 +12,8 @@ const stubState = {
},
nodes: {
5: {
children: {
isFetching: false,
isLoaded: true,
},
isFetching: true,
children: {},
},
},
};
@ -90,7 +88,7 @@ describe('actions', () => {
it('triggers getChildren', () => {
const stub = Object.assign({}, stubState);
stub.nodes[5].children.isLoaded = false;
stub.nodes[5].isFetching = false;
const store = mockStore(stub);
store.dispatch(actions.pushPage(5));
expect(store.getActions()).toMatchSnapshot();

View file

@ -4,6 +4,7 @@ import { Provider } from 'react-redux';
import { createStore, combineReducers, applyMiddleware, compose } from 'redux';
import thunkMiddleware from 'redux-thunk';
// import { perfMiddleware } from '../../utils/performance';
import Explorer from './Explorer';
import ExplorerToggle from './ExplorerToggle';
import explorer from './reducers/explorer';
@ -22,6 +23,11 @@ const initExplorer = (explorerNode, toggleNode) => {
thunkMiddleware,
];
// Uncomment this to use performance measurements.
// if (process.env.NODE_ENV !== 'production') {
// middleware.push(perfMiddleware);
// }
const store = createStore(rootReducer, {}, compose(
applyMiddleware(...middleware),
// Expose store to Redux DevTools extension.

View file

@ -5,12 +5,10 @@ Object {
"1": Object {
"children": Object {
"count": 0,
"isFetching": false,
"items": Array [],
},
"isError": true,
"isFetching": false,
"isLoaded": true,
"meta": Object {
"children": Object {},
},
@ -22,9 +20,14 @@ exports[`nodes GET_CHILDREN_START 1`] = `
Object {
"1": Object {
"children": Object {
"isFetching": true,
"count": 0,
"items": Array [],
},
"isError": false,
"isFetching": true,
"meta": Object {
"children": Object {},
},
},
}
`;
@ -34,9 +37,6 @@ Object {
"1": Object {
"children": Object {
"count": 3,
"isError": false,
"isFetching": false,
"isLoaded": true,
"items": Array [
3,
4,
@ -45,7 +45,6 @@ Object {
},
"isError": false,
"isFetching": false,
"isLoaded": true,
"meta": Object {
"children": Object {},
},
@ -53,13 +52,11 @@ Object {
"3": Object {
"children": Object {
"count": 0,
"isFetching": false,
"items": Array [],
},
"id": 3,
"isError": false,
"isFetching": false,
"isLoaded": true,
"meta": Object {
"children": Object {},
},
@ -67,13 +64,11 @@ Object {
"4": Object {
"children": Object {
"count": 0,
"isFetching": false,
"items": Array [],
},
"id": 4,
"isError": false,
"isFetching": false,
"isLoaded": true,
"meta": Object {
"children": Object {},
},
@ -81,13 +76,11 @@ Object {
"5": Object {
"children": Object {
"count": 0,
"isFetching": false,
"items": Array [],
},
"id": 5,
"isError": false,
"isFetching": false,
"isLoaded": true,
"meta": Object {
"children": Object {},
},
@ -100,12 +93,10 @@ Object {
"1": Object {
"children": Object {
"count": 0,
"isFetching": false,
"items": Array [],
},
"isError": true,
"isFetching": false,
"isLoaded": true,
"meta": Object {
"children": Object {},
},
@ -116,7 +107,15 @@ Object {
exports[`nodes GET_PAGE_SUCCESS 1`] = `
Object {
"1": Object {
"children": Object {
"count": 0,
"items": Array [],
},
"isError": false,
"isFetching": false,
"meta": Object {
"children": Object {},
},
},
}
`;
@ -126,12 +125,10 @@ Object {
"1": Object {
"children": Object {
"count": 0,
"isFetching": false,
"items": Array [],
},
"isError": false,
"isFetching": false,
"isLoaded": true,
"meta": Object {
"children": Object {},
},

View file

@ -9,31 +9,30 @@ const defaultState = {
* - Whether the explorer is open or not.
*/
export default function explorer(prevState = defaultState, { type, payload }) {
const state = Object.assign({}, prevState);
switch (type) {
case 'OPEN_EXPLORER':
// Provide a starting page when opening the explorer.
state.path = [payload.id];
state.isVisible = true;
break;
return {
isVisible: true,
path: [payload.id],
};
case 'CLOSE_EXPLORER':
state.path = [];
state.isVisible = false;
break;
return defaultState;
case 'PUSH_PAGE':
state.path = state.path.concat([payload.id]);
break;
return {
isVisible: prevState.isVisible,
path: prevState.path.concat([payload.id]),
};
case 'POP_PAGE':
state.path = state.path.slice(0, -1);
break;
return {
isVisible: prevState.isVisible,
path: prevState.path.slice(0, -1),
};
default:
break;
return prevState;
}
return state;
}

View file

@ -1,69 +1,86 @@
const defaultState = {};
const defaultPageState = {
isFetching: false,
isLoaded: true,
isError: false,
children: {
items: [],
count: 0,
isFetching: false,
},
meta: {
children: {},
},
};
export default function nodes(prevState = defaultState, { type, payload }) {
const state = Object.assign({}, prevState);
/**
* A single page node in the explorer.
*/
const node = (state = defaultPageState, { type, payload }) => {
switch (type) {
case 'OPEN_EXPLORER':
state[payload.id] = Object.assign({}, defaultPageState, state[payload.id]);
break;
return state || defaultPageState;
case 'GET_PAGE_SUCCESS':
state[payload.id] = Object.assign({}, state[payload.id], payload.data);
state[payload.id].isError = false;
break;
case 'GET_CHILDREN_START':
state[payload.id] = Object.assign({}, state[payload.id]);
state[payload.id].isFetching = true;
state[payload.id].children = Object.assign({}, state[payload.id].children);
state[payload.id].children.isFetching = true;
break;
case 'GET_CHILDREN_SUCCESS':
state[payload.id] = Object.assign({}, state[payload.id]);
state[payload.id].isFetching = false;
state[payload.id].isError = false;
state[payload.id].children = Object.assign({}, state[payload.id].children, {
items: state[payload.id].children.items.slice(),
count: payload.meta.total_count,
isFetching: false,
isLoaded: true,
return Object.assign({}, state, payload.data, {
isError: false,
});
payload.items.forEach((item) => {
state[item.id] = Object.assign({}, defaultPageState, state[item.id], item);
state[payload.id].children.items.push(item.id);
case 'GET_CHILDREN_START':
return Object.assign({}, state, {
isFetching: true,
});
case 'GET_CHILDREN_SUCCESS':
return Object.assign({}, state, {
isFetching: false,
isError: false,
children: {
items: state.children.items.slice().concat(payload.items.map(item => item.id)),
count: payload.meta.total_count,
},
});
break;
case 'GET_PAGE_FAILURE':
case 'GET_CHILDREN_FAILURE':
state[payload.id] = Object.assign({}, state[payload.id]);
state[payload.id].isFetching = false;
state[payload.id].isError = true;
state[payload.id].children.isFetching = false;
break;
return Object.assign({}, state, {
isFetching: false,
isError: true,
});
default:
break;
return state;
}
};
return state;
const defaultState = {};
/**
* Contains all of the page nodes in one object.
*/
export default function nodes(state = defaultState, { type, payload }) {
switch (type) {
case 'OPEN_EXPLORER':
case 'GET_PAGE_SUCCESS':
case 'GET_CHILDREN_START':
case 'GET_PAGE_FAILURE':
case 'GET_CHILDREN_FAILURE':
return Object.assign({}, state, {
// Delegate logic to single-node reducer.
[payload.id]: node(state[payload.id], { type, payload }),
});
// eslint-disable-next-line no-case-declarations
case 'GET_CHILDREN_SUCCESS':
const newState = Object.assign({}, state, {
[payload.id]: node(state[payload.id], { type, payload }),
});
payload.items.forEach((item) => {
newState[item.id] = Object.assign({}, defaultPageState, item);
});
return newState;
default:
return state;
}
}

View file

@ -7,7 +7,7 @@ import React from 'react';
*/
const Icon = ({ name, className, title }) => (
<span>
<span className={`icon icon-${name} ${className}`} aria-hidden></span>
<span className={`icon icon-${name} ${className || ''}`} aria-hidden></span>
{title ? (
<span className="visuallyhidden">
{title}
@ -23,7 +23,7 @@ Icon.propTypes = {
};
Icon.defaultProps = {
className: '',
className: null,
title: null,
};

View file

@ -8,7 +8,6 @@ const TRANSITION_DURATION = 210;
// The available transitions. Must match the class names in CSS.
export const PUSH = 'push';
export const POP = 'pop';
export const FADE = 'fade';
/**
* Wrapper arround react-transition-group with default values.
@ -32,7 +31,7 @@ const Transition = ({
);
Transition.propTypes = {
name: PropTypes.oneOf([PUSH, POP, FADE]).isRequired,
name: PropTypes.oneOf([PUSH, POP]).isRequired,
component: PropTypes.string,
className: PropTypes.string,
duration: PropTypes.number,

View file

@ -57,29 +57,3 @@ $c-transition-duration: 200ms;
transform: translateX(100%);
opacity: 0;
}
// =============================================================================
// Fade transition
// =============================================================================
.c-transition-fade-enter {
position: absolute;
width: 100%;
opacity: 0;
transition: opacity $c-transition-duration ease $c-transition-duration;
}
.c-transition-fade-enter-active {
opacity: 1;
}
.c-transition-fade-leave {
position: absolute;
width: 100%;
opacity: 1;
transition: opacity $c-transition-duration ease;
}
.c-transition-fade-leave-active {
opacity: 0;
}

View file

@ -0,0 +1,86 @@
import React, { Component } from 'react';
/* eslint-disable import/no-mutable-exports */
let perfMiddleware;
if (process.env.NODE_ENV !== 'production') {
/**
* Performance middleware for use with a Redux store.
* Will log the time taken by every action across all
* of the reducers of the store.
*/
perfMiddleware = () => {
/* eslint-disable no-console */
// `next` is a function that takes an 'action' and sends it through to the 'reducers'.
const middleware = (next) => (action) => {
let result;
if (!!console.time) {
console.time(action.type);
result = next(action);
console.timeEnd(action.type);
} else {
result = next(action);
}
return result;
};
return middleware;
};
}
let perfComponent;
if (process.env.NODE_ENV !== 'production') {
/**
* Wraps the passed in `Component` in a higher-order component. It can then
* measure the performance of every render of the `Component`.
*
* Can also be used as an ES2016 decorator.
* @param {ReactComponent} Component the component to wrap
* @return {ReactComponent} the wrapped component
* See https://github.com/sheepsteak/react-perf-component
*/
perfComponent = (Target) => {
if (process.env.NODE_ENV === 'production') {
return Target;
}
// eslint-disable-next-line global-require
const ReactPerf = require('react-addons-perf');
class Perf extends Component {
componentDidMount() {
ReactPerf.start();
}
componentDidUpdate() {
ReactPerf.stop();
const measurements = ReactPerf.getLastMeasurements();
ReactPerf.printWasted(measurements);
ReactPerf.start();
}
componentWillUnmount() {
ReactPerf.stop();
}
render() {
return <Target {...this.props} />;
}
}
Perf.displayName = `perf(${Target.displayName || Target.name || 'Component'})`;
Perf.WrappedComponent = Target;
return Perf;
};
}
export {
perfMiddleware,
perfComponent,
};

View file

@ -33,7 +33,7 @@ gulp.task('styles:sass', function () {
outputStyle: 'expanded'
}).on('error', sass.logError))
.pipe(autoprefixer({
browsers: ['last 3 versions', 'not ie <= 8'],
browsers: ['last 3 versions', 'ie 11'],
cascade: false
}))
.pipe(gulp.dest(function(file) {

View file

@ -49,6 +49,7 @@
"imports-loader": "^0.7.1",
"jest": "^20.0.4",
"mustache": "^2.2.1",
"react-addons-perf": "^15.4.2",
"react-addons-test-utils": "^15.4.2",
"react-test-renderer": "^15.5.4",
"redux-mock-store": "^1.2.2",

View file

@ -213,7 +213,6 @@ $footer-submenu: $submenu-color;
body.nav-open {
.wrapper {
transform: translate3d($menu-width, 0, 0);
-webkit-transform: translate3d($menu-width, 0, 0);
}
.content-wrapper {
@ -242,13 +241,8 @@ body.explorer-open {
}
@media screen and (min-width: $breakpoint-mobile) {
body.explorer-open {
overflow: hidden;
}
.wrapper,
body.nav-open .wrapper {
-webkit-transform: none;
transform: none;
padding-left: $menu-width;
}
@ -416,13 +410,14 @@ body.explorer-open {
}
body.explorer-open {
overflow: hidden;
&:after {
opacity: 1;
visibility: visible;
}
.wrapper {
-webkit-transform: none;
transform: none;
}

View file

@ -85,11 +85,6 @@ body {
transition: transform 0.2s ease;
}
.nav-wrapper {
// See components/main-nav.scss
}
.logo {
display: block;
text-align: left;
@ -112,6 +107,7 @@ body {
}
.content-wrapper {
box-sizing: border-box;
width: 100%;
height: 100%; // this has no effect on desktop, but on mobile it helps aesthetics of menu popout action
float: left;
@ -198,30 +194,14 @@ footer {
white-space: normal;
}
}
@media screen and (min-width: 90em) {
width: 90em;
}
}
// Let's not, for now...
// ::-webkit-scrollbar {
// height: 10px;
// width: 10px;
// background: $color-grey-1;
// }
// ::-webkit-scrollbar-thumb {
// background: $color-grey-2;
// -webkit-border-radius: 1ex;
// }
// ::-webkit-scrollbar-corner {
// background: $color-grey-1;
// }
.breadcrumb {
@include unlist();
}
.breadcrumb {
@include clearfix();
overflow: hidden;
padding-top: 1.4em;
@ -509,27 +489,3 @@ footer,
z-index: 200;
}
}
@media screen and (min-width: 90em) {
.wrapper {
// width: 100%;
}
footer {
width: 90em;
}
}
// Transitions (resolution agnostic)
.content-wrapper,
.nav-main,
.nav-toggle,
footer,
.logo {
// @include transition(all 0.2s ease);
}
// .nav-main a,
// a {
// @include transition(color 0.2s ease, background-color 0.2s ease);
// }

View file

@ -24,7 +24,6 @@
IMAGES: '{% url "wagtailadmin_api_v1:images:listing" %}',
{# // Use this to add an extra query string on all API requests. #}
{# // Example value: '&order=-id' #}
{# // TODO Hook it up to Django settings #}
EXTRA_CHILDREN_PARAMETERS: '',
};