summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--app/components/CustomScrollbars.css24
-rw-r--r--app/components/CustomScrollbars.js130
-rw-r--r--package.json1
-rw-r--r--yarn.lock42
4 files changed, 144 insertions, 53 deletions
diff --git a/app/components/CustomScrollbars.css b/app/components/CustomScrollbars.css
index 24788230b8..074c081209 100644
--- a/app/components/CustomScrollbars.css
+++ b/app/components/CustomScrollbars.css
@@ -1,4 +1,22 @@
-.custom-scrollbars__thumb-vertical {
- background-color: rgba(255, 255, 255, 0.2);
- border-radius: 3px;
+.custom-scrollbars {
+ display: flex;
+ flex-direction: column;
+ position: relative;
+}
+
+.custom-scrollbars__scrollable {
+ width: 100%;
+ height: 100%;
}
+
+.custom-scrollbars__scrollable::-webkit-scrollbar {
+ display: none;
+}
+
+.custom-scrollbars__thumb {
+ background-color: rgba(255, 255, 255, 0.2);
+ border-radius: 4px;
+ width: 8px;
+ transition: height 0.25s ease-in-out, opacity 0.25s ease-in-out;
+ pointer-events: none;
+} \ No newline at end of file
diff --git a/app/components/CustomScrollbars.js b/app/components/CustomScrollbars.js
index 4a0899c1be..6d0ce96daa 100644
--- a/app/components/CustomScrollbars.js
+++ b/app/components/CustomScrollbars.js
@@ -1,19 +1,133 @@
// @flow
import React, { Component } from 'react';
-import { Scrollbars } from 'react-custom-scrollbars';
+
+type ScrollbarUpdateContext = {
+ size: boolean,
+ position: boolean,
+};
export default class CustomScrollbars extends Component {
props: {
- children: ?React.Element<*>
+ thumbInset: { x: number, y: number },
+ children: ?React.Element<*>,
+ };
+
+ static defaultProps = {
+ thumbInset: { x: 2, y: 2 },
+ };
+
+ _scrollableElement: ?HTMLElement;
+ _thumbElement: ?HTMLElement;
+
+ componentDidMount() {
+ this._updateScrollbarsHelper({
+ position: true,
+ size: true
+ });
}
- render(): React.Element<*> {
+ componentDidUpdate() {
+ this._updateScrollbarsHelper({
+ position: true,
+ size: true
+ });
+ }
+
+ render() {
return (
- <Scrollbars
- { ...this.props }
- renderThumbVertical={ () => <div className="custom-scrollbars__thumb-vertical"/> }>
- { this.props.children }
- </Scrollbars>
+ <div className="custom-scrollbars">
+ <div className="custom-scrollbars__thumb"
+ style={{ position: 'absolute', top: 0, right: 0 }}
+ ref={ this._onThumbRef }></div>
+ <div className="custom-scrollbars__scrollable"
+ style={{ overflow: 'auto' }}
+ onScroll={ this._onScroll }
+ ref={ this._onScrollableRef }>
+ { this.props.children }
+ </div>
+ </div>
);
}
+
+
+ _onScrollableRef = (ref) => {
+ this._scrollableElement = ref;
+ }
+
+ _onThumbRef = (ref) => {
+ this._thumbElement = ref;
+ }
+
+ _onScroll = () => {
+ this._updateScrollbarsHelper({ position: true });
+ }
+
+ _computeThumbPosition(scrollable: HTMLElement, thumb: HTMLElement) {
+ // the content height of the scroll view
+ const scrollHeight = scrollable.scrollHeight;
+
+ // the visible height of the scroll view
+ const visibleHeight = scrollable.offsetHeight;
+
+ // scroll offset
+ const scrollTop = scrollable.scrollTop;
+
+ // lowest point of scrollTop
+ const maxScrollTop = scrollHeight - visibleHeight;
+
+ // calculate scroll position within 0..1 range
+ const scrollPosition = scrollHeight > 0 ? scrollTop / maxScrollTop : 0;
+
+ const thumbHeight = thumb.clientHeight;
+
+ // calculate the thumb boundary to make sure that the visual appearance of
+ // a thumb at lowest point matches the bottom of scrollable view
+ const thumbBoundary = visibleHeight - thumbHeight - (this.props.thumbInset.y * 2);
+
+ // calculate thumb position based on scroll progress and thumb boundary
+ // adding vertical inset to adjust the thumb's appearance
+ const thumbPosition = (thumbBoundary * scrollPosition) + this.props.thumbInset.y;
+
+ return {
+ x: -this.props.thumbInset.x,
+ y: thumbPosition,
+ };
+ }
+
+ _computeThumbHeight(scrollable: HTMLElement) {
+ const scrollHeight = scrollable.scrollHeight;
+ const visibleHeight = scrollable.offsetHeight;
+
+ const thumbHeight = (visibleHeight / scrollHeight) * visibleHeight;
+
+ // ensure that the scroll thumb doesn't shrink to nano size
+ return Math.max(thumbHeight, 8);
+ }
+
+ _updateScrollbarsHelper(updateFlags: $Shape<ScrollbarUpdateContext>) {
+ const scrollable = this._scrollableElement;
+ const thumb = this._thumbElement;
+ if(scrollable && thumb) {
+ this._updateScrollbars(scrollable, thumb, updateFlags);
+ }
+ }
+
+ _updateScrollbars(scrollable: HTMLElement, thumb: HTMLElement, context: $Shape<ScrollbarUpdateContext>) {
+ if(context.size) {
+ const thumbHeight = this._computeThumbHeight(scrollable);
+ 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');
+ }
+ }
+
+ if(context.position) {
+ const { x, y } = this._computeThumbPosition(scrollable, thumb);
+ thumb.style.setProperty('transform', `translate(${x}px, ${y}px)`);
+ }
+ }
}
diff --git a/package.json b/package.json
index 421d637605..9c08ea1d29 100644
--- a/package.json
+++ b/package.json
@@ -21,7 +21,6 @@
"moment": "^2.17.1",
"prop-types": "^15.5.10",
"react": "^16.0.0",
- "react-custom-scrollbars": "^4.2.1",
"react-dom": "^16.0.0",
"react-if": "^2.2.1",
"react-mapbox-gl": "^2.1.0",
diff --git a/yarn.lock b/yarn.lock
index b428120ff3..5e16592c88 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -128,10 +128,6 @@ acorn@^5.0.0, acorn@^5.1.0, acorn@^5.2.1:
version "5.2.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.2.1.tgz#317ac7821826c22c702d66189ab8359675f135d7"
-add-px-to-style@1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/add-px-to-style/-/add-px-to-style-1.0.0.tgz#d0c135441fa8014a8137904531096f67f28f263a"
-
after@0.8.1:
version "0.8.1"
resolved "https://registry.yarnpkg.com/after/-/after-0.8.1.tgz#ab5d4fb883f596816d3515f8f791c0af486dd627"
@@ -2469,14 +2465,6 @@ doctrine@^2.0.0, doctrine@^2.0.2:
dependencies:
esutils "^2.0.2"
-dom-css@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/dom-css/-/dom-css-2.1.0.tgz#fdbc2d5a015d0a3e1872e11472bbd0e7b9e6a202"
- dependencies:
- add-px-to-style "1.0.0"
- prefix-style "2.0.1"
- to-camel-case "1.0.0"
-
dom-helpers@^3.2.0:
version "3.2.1"
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.2.1.tgz#3203e07fed217bd1f424b019735582fc37b2825a"
@@ -6098,10 +6086,6 @@ prebuild-install@^2.3.0:
tunnel-agent "^0.6.0"
xtend "4.0.1"
-prefix-style@2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/prefix-style/-/prefix-style-2.0.1.tgz#66bba9a870cfda308a5dc20e85e9120932c95a06"
-
prelude-ls@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
@@ -6263,7 +6247,7 @@ rabin-bindings@~1.7.4:
nan "^2.8.0"
prebuild-install "^2.3.0"
-raf@^3.1.0, raf@^3.4.0:
+raf@^3.4.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.0.tgz#a28876881b4bc2ca9117d4138163ddb80f781575"
dependencies:
@@ -6320,14 +6304,6 @@ react-clone-referenced-element@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/react-clone-referenced-element/-/react-clone-referenced-element-1.0.1.tgz#2bba8c69404c5e4a944398600bcc4c941f860682"
-react-custom-scrollbars@^4.2.1:
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/react-custom-scrollbars/-/react-custom-scrollbars-4.2.1.tgz#830fd9502927e97e8a78c2086813899b2a8b66db"
- dependencies:
- dom-css "^2.0.0"
- prop-types "^15.5.10"
- raf "^3.1.0"
-
react-deep-force-update@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/react-deep-force-update/-/react-deep-force-update-1.1.1.tgz#bcd31478027b64b3339f108921ab520b4313dc2c"
@@ -7823,26 +7799,10 @@ to-array@0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890"
-to-camel-case@1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/to-camel-case/-/to-camel-case-1.0.0.tgz#1a56054b2f9d696298ce66a60897322b6f423e46"
- dependencies:
- to-space-case "^1.0.0"
-
to-fast-properties@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
-to-no-case@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/to-no-case/-/to-no-case-1.0.2.tgz#c722907164ef6b178132c8e69930212d1b4aa16a"
-
-to-space-case@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/to-space-case/-/to-space-case-1.0.0.tgz#b052daafb1b2b29dc770cea0163e5ec0ebc9fc17"
- dependencies:
- to-no-case "^1.0.0"
-
to-utf8@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/to-utf8/-/to-utf8-0.0.1.tgz#d17aea72ff2fba39b9e43601be7b3ff72e089852"