Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SwipeableDrawer] Add a blocking div to the edge of the screen #11031

Merged
merged 7 commits into from
Apr 16, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .size-limit
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
{
"name": "The size of the whole library.",
"path": "build/index.js",
"limit": "100.3 KB"
"limit": "100.6 KB"
},
{
"name": "The main bundle of the documentation",
Expand Down
67 changes: 67 additions & 0 deletions src/SwipeableDrawer/SwipeArea.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import withStyles from '../styles/withStyles';
import { capitalize } from '../utils/helpers';
import { isHorizontal } from '../Drawer/Drawer';

export const styles = theme => ({
root: {
position: 'fixed',
top: 0,
left: 0,
height: '100vh',
zIndex: theme.zIndex.drawer - 1,
},
discoveryAnchorLeft: {
right: 'auto',
},
discoveryAnchorRight: {
left: 'auto',
right: 0,
},
discoveryAnchorTop: {
bottom: 'auto',
right: 0,
},
discoveryAnchorBottom: {
top: 'auto',
bottom: 0,
right: 0,
},
});

/**
* @ignore - internal component.
*/
function SwipeArea(props) {
const { anchor, classes, swipeAreaWidth, ...other } = props;

return (
<div
className={classNames(classes.root, classes[`discoveryAnchor${capitalize(anchor)}`])}
style={{
[isHorizontal(props) ? 'width' : 'height']: swipeAreaWidth,
}}
{...other}
/>
);
}

SwipeArea.propTypes = {
/**
* Side on which to attach the discovery area.
*/
anchor: PropTypes.oneOf(['left', 'top', 'right', 'bottom']).isRequired,
/**
* @ignore
*/
classes: PropTypes.object.isRequired,
/**
* The width of the left most (or right most) area in pixels where the
* drawer can be swiped open from.
*/
swipeAreaWidth: PropTypes.number.isRequired,
};

export default withStyles(styles)(SwipeArea);
42 changes: 26 additions & 16 deletions src/SwipeableDrawer/SwipeableDrawer.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import Drawer, { getAnchor, isHorizontal } from '../Drawer/Drawer';
import { duration } from '../styles/transitions';
import withTheme from '../styles/withTheme';
import { getTransitionProps } from '../transitions/utils';
import SwipeArea from './SwipeArea';

const Fragment = React.Fragment || 'div';

// This value is closed to what browsers are using internally to
// trigger a native scroll.
Expand Down Expand Up @@ -330,22 +333,29 @@ class SwipeableDrawer extends React.Component {
const { maybeSwiping } = this.state;

return (
<Drawer
open={variant === 'temporary' && maybeSwiping ? true : open}
variant={variant}
ModalProps={{
BackdropProps: {
...BackdropProps,
ref: this.handleBackdropRef,
},
...ModalPropsProp,
}}
PaperProps={{
...PaperProps,
ref: this.handlePaperRef,
}}
{...other}
/>
<Fragment>
<Drawer
open={variant === 'temporary' && maybeSwiping ? true : open}
variant={variant}
ModalProps={{
BackdropProps: {
...BackdropProps,
ref: this.handleBackdropRef,
},
...ModalPropsProp,
}}
PaperProps={{
...PaperProps,
ref: this.handlePaperRef,
}}
{...other}
/>
{!disableDiscovery &&
!disableSwipeToOpen &&
variant === 'temporary' && (
<SwipeArea anchor={other.anchor} swipeAreaWidth={swipeAreaWidth} />
)}
</Fragment>
);
}
}
Expand Down
64 changes: 58 additions & 6 deletions src/SwipeableDrawer/SwipeableDrawer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import React from 'react';
import { assert } from 'chai';
import { spy, stub } from 'sinon';
import ReactDOM from 'react-dom';
import { createShallow, createMount, unwrap } from '../test-utils';
import { createMount, unwrap } from '../test-utils';
import Paper from '../Paper';
import Drawer from '../Drawer';
import SwipeableDrawer, { reset } from './SwipeableDrawer';
import SwipeArea from './SwipeArea';
import createMuiTheme from '../styles/createMuiTheme';

function fireBodyMouseEvent(name, properties) {
Expand All @@ -19,12 +20,10 @@ function fireBodyMouseEvent(name, properties) {

describe('<SwipeableDrawer />', () => {
const SwipeableDrawerNaked = unwrap(SwipeableDrawer);
let shallow;
let mount;
let findDOMNodeStub;

before(() => {
shallow = createShallow({ dive: true });
mount = createMount();
// mock the drawer DOM node, since jsdom doesn't do layouting but its size is required
const findDOMNode = ReactDOM.findDOMNode;
Expand All @@ -42,9 +41,62 @@ describe('<SwipeableDrawer />', () => {
mount.cleanUp();
});

it('should render a Drawer', () => {
const wrapper = shallow(<SwipeableDrawer onOpen={() => {}} onClose={() => {}} open={false} />);
assert.strictEqual(wrapper.type(), Drawer);
it('should render a Drawer and a SwipeArea', () => {
const wrapper = mount(
<SwipeableDrawerNaked
onOpen={() => {}}
onClose={() => {}}
open={false}
theme={createMuiTheme()}
/>,
);
if (React.Fragment) {
assert.strictEqual(wrapper.childAt(0).type(), Drawer);
assert.strictEqual(wrapper.childAt(1).type(), SwipeArea);
} else {
assert.strictEqual(
wrapper
.childAt(0)
.childAt(0)
.type(),
Drawer,
);
assert.strictEqual(
wrapper
.childAt(0)
.childAt(1)
.type(),
SwipeArea,
);
}
wrapper.unmount();
});

it('should hide the SwipeArea if swipe to open is disabled', () => {
const wrapper = mount(
<SwipeableDrawerNaked
onOpen={() => {}}
onClose={() => {}}
open={false}
theme={createMuiTheme()}
disableSwipeToOpen
/>,
);
assert.strictEqual(wrapper.children().length, 1);
wrapper.unmount();
});

it('should hide the SwipeArea if discovery is disabled', () => {
const wrapper = mount(
<SwipeableDrawerNaked
onOpen={() => {}}
onClose={() => {}}
open={false}
theme={createMuiTheme()}
disableDiscovery
/>,
);
assert.strictEqual(wrapper.children().length, 1);
wrapper.unmount();
});

Expand Down