Skip to content

Commit

Permalink
[Tabs] Reduce the bundle size
Browse files Browse the repository at this point in the history
  • Loading branch information
oliviertassinari committed Dec 7, 2018
1 parent 29eae3a commit 6f32951
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 51 deletions.
41 changes: 16 additions & 25 deletions packages/material-ui/src/Tabs/ScrollbarSize.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import EventListener from 'react-event-listener';
import debounce from 'debounce'; // < 1kb payload overhead when lodash/debounce is > 3kb.

const styles = {
width: 100,
height: 100,
width: 90,
height: 90,
position: 'absolute',
top: -10000,
top: -9000,
overflow: 'scroll',
// Support IE 11
msOverflowStyle: 'scrollbar',
};

Expand All @@ -23,30 +24,29 @@ class ScrollbarSize extends React.Component {

if (typeof window !== 'undefined') {
this.handleResize = debounce(() => {
const { onChange } = this.props;

const prevHeight = this.scrollbarHeight;
const prevWidth = this.scrollbarWidth;
this.setMeasurements();
if (prevHeight !== this.scrollbarHeight || prevWidth !== this.scrollbarWidth) {
onChange({ scrollbarHeight: this.scrollbarHeight, scrollbarWidth: this.scrollbarWidth });

if (prevHeight !== this.scrollbarHeight) {
this.props.onChange(this.scrollbarHeight);
}
}, 166); // Corresponds to 10 frames at 60 Hz.
}
}

componentDidMount() {
this.setMeasurements();
this.props.onLoad({
scrollbarHeight: this.scrollbarHeight,
scrollbarWidth: this.scrollbarWidth,
});
this.props.onChange(this.scrollbarHeight);
}

componentWillUnmount() {
this.handleResize.clear();
}

handleRef = ref => {
this.nodeRef = ref;
};

setMeasurements = () => {
const nodeRef = this.nodeRef;

Expand All @@ -55,29 +55,20 @@ class ScrollbarSize extends React.Component {
}

this.scrollbarHeight = nodeRef.offsetHeight - nodeRef.clientHeight;
this.scrollbarWidth = nodeRef.offsetWidth - nodeRef.clientWidth;
};

render() {
const { onChange } = this.props;

return (
<div>
{onChange ? <EventListener target="window" onResize={this.handleResize} /> : null}
<div
style={styles}
ref={ref => {
this.nodeRef = ref;
}}
/>
</div>
<React.Fragment>
<EventListener target="window" onResize={this.handleResize} />
<div style={styles} ref={this.handleRef} />
</React.Fragment>
);
}
}

ScrollbarSize.propTypes = {
onChange: PropTypes.func.isRequired,
onLoad: PropTypes.func.isRequired,
};

export default ScrollbarSize;
33 changes: 12 additions & 21 deletions packages/material-ui/src/Tabs/ScrollbarSize.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import ScrollbarSize from './ScrollbarSize';

describe('<ScrollbarSize />', () => {
const defaultProps = {
onLoad: () => {},
onChange: () => {},
};
let clock;
Expand All @@ -20,28 +19,24 @@ describe('<ScrollbarSize />', () => {
clock.restore();
});

describe('prop: onLoad', () => {
describe('mount', () => {
let wrapper;

afterEach(() => {
wrapper.unmount();
});

it('should not call on initial load', () => {
const onLoad = spy();
const onChange = spy();
wrapper = mount(<ScrollbarSize {...defaultProps} />);
assert.strictEqual(onLoad.callCount, 0, 'should not have been called');
assert.strictEqual(onChange.callCount, 0);
});

it('should call on initial load', () => {
const onLoad = spy();
wrapper = mount(<ScrollbarSize {...defaultProps} onLoad={onLoad} />);
assert.strictEqual(onLoad.callCount, 1, 'should have been called once');
assert.strictEqual(
onLoad.calledWith({ scrollbarHeight: 0, scrollbarWidth: 0 }),
true,
'should have been called with expected sizes',
);
const onChange = spy();
wrapper = mount(<ScrollbarSize {...defaultProps} onChange={onChange} />);
assert.strictEqual(onChange.callCount, 1);
assert.strictEqual(onChange.calledWith(0), true);
});
});

Expand All @@ -56,26 +51,22 @@ describe('<ScrollbarSize />', () => {
instance.nodeRef = {
offsetHeight: 17,
clientHeight: 0,
offsetWidth: 17,
clientWidth: 0,
};
});

it('should call on first resize event', () => {
assert.strictEqual(onChange.callCount, 1);
wrapper.find(EventListener).simulate('resize');
clock.tick(166);
assert.strictEqual(onChange.callCount, 1, 'should have been called once');
assert.strictEqual(
onChange.calledWith({ scrollbarHeight: 17, scrollbarWidth: 17 }),
true,
'should have been called with expected sizes',
);
assert.strictEqual(onChange.callCount, 2);
assert.strictEqual(onChange.calledWith(17), true);
});

it('should not call on second resize event', () => {
assert.strictEqual(onChange.callCount, 1);
wrapper.find(EventListener).simulate('resize');
clock.tick(166);
assert.strictEqual(onChange.callCount, 1, 'should only have been called once');
assert.strictEqual(onChange.callCount, 2);
});
});
});
7 changes: 2 additions & 5 deletions packages/material-ui/src/Tabs/Tabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,7 @@ class Tabs extends React.Component {
const { classes, scrollable, ScrollButtonComponent, scrollButtons, theme } = this.props;
const conditionalElements = {};
conditionalElements.scrollbarSizeListener = scrollable ? (
<ScrollbarSize
onLoad={this.handleScrollbarSizeChange}
onChange={this.handleScrollbarSizeChange}
/>
<ScrollbarSize onChange={this.handleScrollbarSizeChange} />
) : null;

const showScrollButtons = scrollable && (scrollButtons === 'auto' || scrollButtons === 'on');
Expand Down Expand Up @@ -194,7 +191,7 @@ class Tabs extends React.Component {
this.moveTabsScroll(this.tabsRef.clientWidth);
};

handleScrollbarSizeChange = ({ scrollbarHeight }) => {
handleScrollbarSizeChange = scrollbarHeight => {
this.setState({
scrollerStyle: {
marginBottom: -scrollbarHeight,
Expand Down

0 comments on commit 6f32951

Please sign in to comment.