diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2017-12-22 11:49:52 +0100 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2017-12-22 11:49:52 +0100 |
| commit | 41d50449196fb9028850720b919221ffca456508 (patch) | |
| tree | 61d5f595c793512ce1333874e6556d8782fda509 /app/components | |
| parent | cf2c7fc7cb18a41543078ae154133d30f09b08a0 (diff) | |
| parent | fd33249dc0e08de64f0ba2898b5640a70972a346 (diff) | |
| download | mullvadvpn-41d50449196fb9028850720b919221ffca456508.tar.xz mullvadvpn-41d50449196fb9028850720b919221ffca456508.zip | |
Merge branch 'autohide-scrollbars'
Diffstat (limited to 'app/components')
| -rw-r--r-- | app/components/CustomScrollbars.css | 7 | ||||
| -rw-r--r-- | app/components/CustomScrollbars.js | 65 |
2 files changed, 66 insertions, 6 deletions
diff --git a/app/components/CustomScrollbars.css b/app/components/CustomScrollbars.css index 074c081209..fb00d1b7cb 100644 --- a/app/components/CustomScrollbars.css +++ b/app/components/CustomScrollbars.css @@ -19,4 +19,11 @@ width: 8px; transition: height 0.25s ease-in-out, opacity 0.25s ease-in-out; pointer-events: none; + opacity: 0; +} + +.custom-scrollbars__thumb--visible { + /* thumb appears without animation */ + transition: height 0.25s ease-in-out; + opacity: 1; }
\ No newline at end of file diff --git a/app/components/CustomScrollbars.js b/app/components/CustomScrollbars.js index 6d0ce96daa..d2f89d5e15 100644 --- a/app/components/CustomScrollbars.js +++ b/app/components/CustomScrollbars.js @@ -6,24 +6,43 @@ type ScrollbarUpdateContext = { position: boolean, }; +const AUTOHIDE_TIMEOUT = 1000; + export default class CustomScrollbars extends Component { props: { + autoHide: boolean, thumbInset: { x: number, y: number }, children: ?React.Element<*>, }; static defaultProps = { + autoHide: true, thumbInset: { x: 2, y: 2 }, }; + state = { + canScroll: false, + showScrollIndicators: true, + }; + _scrollableElement: ?HTMLElement; _thumbElement: ?HTMLElement; + _autoHideTimer: ?number; componentDidMount() { this._updateScrollbarsHelper({ position: true, size: true }); + + // show scroll indicators briefly when mounted + if(this.props.autoHide) { + this._startAutoHide(); + } + } + + componentWillUnmount() { + this._stopAutoHide(); } componentDidUpdate() { @@ -34,9 +53,11 @@ export default class CustomScrollbars extends Component { } render() { + const showScrollbars = this.state.canScroll && this.state.showScrollIndicators; + const thumbAnimationClass = showScrollbars ? ' custom-scrollbars__thumb--visible' : ''; return ( <div className="custom-scrollbars"> - <div className="custom-scrollbars__thumb" + <div className={ `custom-scrollbars__thumb ${thumbAnimationClass}` } style={{ position: 'absolute', top: 0, right: 0 }} ref={ this._onThumbRef }></div> <div className="custom-scrollbars__scrollable" @@ -49,7 +70,6 @@ export default class CustomScrollbars extends Component { ); } - _onScrollableRef = (ref) => { this._scrollableElement = ref; } @@ -60,6 +80,35 @@ export default class CustomScrollbars extends Component { _onScroll = () => { this._updateScrollbarsHelper({ position: true }); + + if(this.props.autoHide) { + this._startAutoHide(); + } + } + + _startAutoHide() { + if(this._autoHideTimer) { + clearTimeout(this._autoHideTimer); + } + + this._autoHideTimer = setTimeout(() => { + this.setState({ + showScrollIndicators: false, + }); + }, AUTOHIDE_TIMEOUT); + + if(!this.state.showScrollIndicators) { + this.setState({ + showScrollIndicators: true, + }); + } + } + + _stopAutoHide() { + if(this._autoHideTimer) { + clearTimeout(this._autoHideTimer); + this._autoHideTimer = null; + } } _computeThumbPosition(scrollable: HTMLElement, thumb: HTMLElement) { @@ -118,10 +167,14 @@ export default class CustomScrollbars extends Component { thumb.style.setProperty('height', thumbHeight + 'px'); // hide thumb when there is nothing to scroll - if(thumbHeight < scrollable.offsetHeight) { - thumb.style.setProperty('opacity', '1'); - } else { - thumb.style.setProperty('opacity', '0'); + const canScroll = (thumbHeight < scrollable.offsetHeight); + if(this.state.canScroll !== canScroll) { + this.setState({ canScroll }); + + // flash the scroll indicators when the view becomes scrollable + if(this.props.autoHide && canScroll) { + this._startAutoHide(); + } } } |
