Skip to content

Commit

Permalink
[SwipeableDrawer] Batch of fixes (mui#10806)
Browse files Browse the repository at this point in the history
  • Loading branch information
oliviertassinari authored Mar 26, 2018
1 parent 4ad49a0 commit 2a7104a
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 36 deletions.
8 changes: 8 additions & 0 deletions docs/src/modules/components/AppDrawer.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ function reduceChildRoutes({ props, activePage, items, page, depth }) {
}

const GITHUB_RELEASE_BASE_URL = 'https://github.com/mui-org/material-ui/releases/tag/';
// iOS is hosted on high-end devices. We can enable the backdrop transition without
// dropping frames. The performance will be good enough.
// iOS has a "swipe to go back" feature that mess with the discovery feature.
// We have to disable it.
// So: <SwipeableDrawer disableBackdropTransition={false} disableDiscovery={true} />
const iOS = process.browser && /iPad|iPhone|iPod/.test(navigator.userAgent);

function AppDrawer(props, context) {
const { classes, className, disablePermanent, mobileOpen, onClose, onOpen } = props;
Expand Down Expand Up @@ -119,6 +125,8 @@ function AppDrawer(props, context) {
classes={{
paper: classNames(classes.paper, 'algolia-drawer'),
}}
disableBackdropTransition={!iOS}
disableDiscovery={iOS}
variant="temporary"
open={mobileOpen}
onOpen={onOpen}
Expand Down
13 changes: 13 additions & 0 deletions docs/src/pages/demos/drawers/drawers.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,19 @@ You can use the `disableBackdropTransition` property to help.

{{"demo": "pages/demos/drawers/SwipeableTemporaryDrawer.js", "hideEditButton": true}}

We are using the follow set of properties on this documentation website for optimal usability of the component:
- iOS is hosted on high-end devices.
We can enable the backdrop transition without dropping frames.
The performance will be good enough.
- iOS has a "swipe to go back" feature that mess
with the discovery feature. We have to disable it.

```jsx
const iOS = process.browser && /iPad|iPhone|iPod/.test(navigator.userAgent);

<SwipeableDrawer disableBackdropTransition={!iOS} disableDiscovery={iOS} />
```

## Permanent drawer

Permanent navigation drawers are always visible and pinned to the left edge, at the same elevation as the content or background. They cannot be closed.
Expand Down
31 changes: 24 additions & 7 deletions src/SwipeableDrawer/SwipeableDrawer.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class SwipeableDrawer extends React.Component {
}

setPosition(translate, options = {}) {
const { mode = null } = options;
const { mode = null, changeTransition = true } = options;

const anchor = getAnchor(this.props);
const rtlTranslateMultiplier = ['right', 'bottom'].indexOf(anchor) !== -1 ? 1 : -1;
Expand All @@ -94,15 +94,19 @@ class SwipeableDrawer extends React.Component {
);
}

drawerStyle.webkitTransition = transition;
drawerStyle.transition = transition;
if (changeTransition) {
drawerStyle.webkitTransition = transition;
drawerStyle.transition = transition;
}

if (!this.props.disableBackdropTransition) {
const backdropStyle = this.backdrop.style;
backdropStyle.opacity = 1 - translate / this.getMaxTranslate();

backdropStyle.webkitTransition = transition;
backdropStyle.transition = transition;
if (changeTransition) {
backdropStyle.webkitTransition = transition;
backdropStyle.transition = transition;
}
}
}

Expand Down Expand Up @@ -139,7 +143,9 @@ class SwipeableDrawer extends React.Component {

this.setState({ maybeSwiping: true });
if (!open) {
this.setPosition(this.getMaxTranslate() - (disableDiscovery ? 0 : swipeAreaWidth));
this.setPosition(this.getMaxTranslate() - (disableDiscovery ? 0 : swipeAreaWidth), {
changeTransition: false,
});
}

document.body.addEventListener('touchmove', this.handleBodyTouchMove, { passive: false });
Expand Down Expand Up @@ -173,11 +179,20 @@ class SwipeableDrawer extends React.Component {
? dx > UNCERTAINTY_THRESHOLD && dy <= UNCERTAINTY_THRESHOLD
: dy > UNCERTAINTY_THRESHOLD && dx <= UNCERTAINTY_THRESHOLD;

// We are likely to be swiping, let's prevent the scroll event on iOS.
if (dx > dy) {
event.preventDefault();
}

if (isSwiping) {
this.isSwiping = this.props.open ? 'closing' : 'opening';

// Shift the starting point.
this.startX = currentX;
this.startY = currentY;

// Compensate for the part of the drawer displayed on touch start.
if (!this.props.disableDiscovery) {
if (!this.props.disableDiscovery && !this.props.open) {
if (horizontalSwipe) {
this.startX -= this.props.swipeAreaWidth;
} else {
Expand All @@ -197,6 +212,8 @@ class SwipeableDrawer extends React.Component {
return;
}

// We are swiping, let's prevent the scroll event on iOS.
event.preventDefault();
this.setPosition(this.getTranslate(horizontalSwipe ? currentX : currentY));
};

Expand Down
1 change: 1 addition & 0 deletions src/SwipeableDrawer/SwipeableDrawer.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ describe('<SwipeableDrawer />', () => {
</div>,
);
fireBodyMouseEvent('touchstart', { touches: [{ pageX: 0, clientY: 0 }] });
fireBodyMouseEvent('touchmove', { touches: [{ pageX: 20, clientY: 0 }] });
fireBodyMouseEvent('touchmove', { touches: [{ pageX: 180, clientY: 0 }] });
fireBodyMouseEvent('touchend', { changedTouches: [{ pageX: 180, clientY: 0 }] });
assert.strictEqual(handleOpen.callCount, 1, 'should call onOpen once, not twice');
Expand Down
14 changes: 4 additions & 10 deletions src/transitions/Fade.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ class Fade extends React.Component {
const transitionProps = getTransitionProps(this.props, {
mode: 'enter',
});
node.style.transition = theme.transitions.create('opacity', transitionProps);
node.style.webkitTransition = theme.transitions.create('opacity', transitionProps);
node.style.transition = theme.transitions.create('opacity', transitionProps);

if (this.props.onEnter) {
this.props.onEnter(node);
Expand All @@ -38,17 +38,11 @@ class Fade extends React.Component {

handleExit = node => {
const { theme } = this.props;
const { duration: transitionDuration, delay } = getTransitionProps(this.props, {
const transitionProps = getTransitionProps(this.props, {
mode: 'exit',
});
node.style.transition = theme.transitions.create('opacity', {
duration: transitionDuration,
delay,
});
node.style.webkitTransition = theme.transitions.create('opacity', {
duration: transitionDuration,
delay,
});
node.style.webkitTransition = theme.transitions.create('opacity', transitionProps);
node.style.transition = theme.transitions.create('opacity', transitionProps);

if (this.props.onExit) {
this.props.onExit(node);
Expand Down
16 changes: 8 additions & 8 deletions src/transitions/Slide.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ export function setTranslateValue(props, node) {
const transform = getTranslateValue(props, node);

if (transform) {
node.style.transform = transform;
node.style.webkitTransform = transform;
node.style.transform = transform;
}
}

Expand Down Expand Up @@ -132,16 +132,16 @@ class Slide extends React.Component {
const transitionProps = getTransitionProps(this.props, {
mode: 'enter',
});
node.style.transition = theme.transitions.create('transform', {
node.style.webkitTransition = theme.transitions.create('-webkit-transform', {
...transitionProps,
easing: theme.transitions.easing.easeOut,
});
node.style.webkitTransition = theme.transitions.create('-webkit-transform', {
node.style.transition = theme.transitions.create('transform', {
...transitionProps,
easing: theme.transitions.easing.easeOut,
});
node.style.transform = 'translate3d(0, 0, 0)';
node.style.webkitTransform = 'translate3d(0, 0, 0)';
node.style.webkitTransform = 'translate(0, 0)';
node.style.transform = 'translate(0, 0)';
if (this.props.onEntering) {
this.props.onEntering(node);
}
Expand All @@ -153,11 +153,11 @@ class Slide extends React.Component {
const transitionProps = getTransitionProps(this.props, {
mode: 'exit',
});
node.style.transition = theme.transitions.create('transform', {
node.style.webkitTransition = theme.transitions.create('-webkit-transform', {
...transitionProps,
easing: theme.transitions.easing.sharp,
});
node.style.webkitTransition = theme.transitions.create('-webkit-transform', {
node.style.transition = theme.transitions.create('transform', {
...transitionProps,
easing: theme.transitions.easing.sharp,
});
Expand All @@ -170,8 +170,8 @@ class Slide extends React.Component {

handleExited = node => {
// No need for transitions when the component is hidden
node.style.transition = '';
node.style.webkitTransition = '';
node.style.transition = '';

if (this.props.onExited) {
this.props.onExited(node);
Expand Down
2 changes: 1 addition & 1 deletion src/transitions/Slide.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ describe('<Slide />', () => {
});

it('should reset the translate3d', () => {
assert.strictEqual(element.style.transform, 'translate3d(0, 0, 0)');
assert.strictEqual(element.style.transform, 'translate(0, 0)');
});
});

Expand Down
14 changes: 4 additions & 10 deletions src/transitions/Zoom.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ class Zoom extends React.Component {
const transitionProps = getTransitionProps(this.props, {
mode: 'enter',
});
node.style.transition = theme.transitions.create('transform', transitionProps);
node.style.webkitTransition = theme.transitions.create('transform', transitionProps);
node.style.transition = theme.transitions.create('transform', transitionProps);

if (this.props.onEnter) {
this.props.onEnter(node);
Expand All @@ -39,17 +39,11 @@ class Zoom extends React.Component {

handleExit = node => {
const { theme } = this.props;
const { duration: transitionDuration, delay } = getTransitionProps(this.props, {
const transitionProps = getTransitionProps(this.props, {
mode: 'exit',
});
node.style.transition = theme.transitions.create('transform', {
duration: transitionDuration,
delay,
});
node.style.webkitTransition = theme.transitions.create('transform', {
duration: transitionDuration,
delay,
});
node.style.webkitTransition = theme.transitions.create('transform', transitionProps);
node.style.transition = theme.transitions.create('transform', transitionProps);

if (this.props.onExit) {
this.props.onExit(node);
Expand Down

0 comments on commit 2a7104a

Please sign in to comment.