diff --git a/client/src/javascript/components/general/ListViewport.tsx b/client/src/javascript/components/general/ListViewport.tsx index 2dc5a250..a140958b 100644 --- a/client/src/javascript/components/general/ListViewport.tsx +++ b/client/src/javascript/components/general/ListViewport.tsx @@ -1,9 +1,54 @@ import {FixedSizeList} from 'react-window'; -import {useWindowHeight} from '@react-hook/window-size'; +import {OverlayScrollbarsComponent} from 'overlayscrollbars-react'; +import {useMediaQuery} from '@react-hook/media-query'; +import {useWindowSize} from '@react-hook/window-size'; import * as React from 'react'; import type {ListChildComponentProps} from 'react-window'; +const Overflow = React.forwardRef>( + (props: React.ComponentProps<'div'>, ref) => { + const {children, className, onScroll} = props; + const osRef = React.useRef(null); + + React.useEffect(() => { + const scrollbarRef = osRef.current; + + if (scrollbarRef == null) { + return () => { + // do nothing. + }; + } + + const viewport = scrollbarRef.osInstance()?.getElements().viewport as HTMLDivElement; + + const refCallback = ref as React.RefCallback; + refCallback(viewport); + + if (onScroll) { + viewport.addEventListener('scroll', (e) => onScroll((e as unknown) as React.UIEvent), { + passive: true, + }); + } + + return () => { + if (onScroll) { + viewport.removeEventListener('scroll', (e) => onScroll((e as unknown) as React.UIEvent)); + } + }; + }, [onScroll]); + + return ( + + {children} + + ); + }, +); + interface ListViewportProps { className: string; itemRenderer: React.FC; @@ -14,16 +59,18 @@ interface ListViewportProps { const ListViewport = React.forwardRef((props: ListViewportProps, ref) => { const {className, itemRenderer, itemSize, listLength, outerRef} = props; - const windowHeight = useWindowHeight(); + const [windowWidth, windowHeight] = useWindowSize(); + const isDarkTheme = useMediaQuery('(prefers-color-scheme: dark)'); return ( 720 ? Overflow : undefined} // Don't use custom scrollbar on smaller screens ref={ref} outerRef={outerRef}> {itemRenderer} diff --git a/client/src/javascript/components/sidebar/Sidebar.tsx b/client/src/javascript/components/sidebar/Sidebar.tsx index 26f50073..57504b89 100644 --- a/client/src/javascript/components/sidebar/Sidebar.tsx +++ b/client/src/javascript/components/sidebar/Sidebar.tsx @@ -1,3 +1,6 @@ +import {OverlayScrollbarsComponent} from 'overlayscrollbars-react'; + +import DiskUsage from './DiskUsage'; import FeedsButton from './FeedsButton'; import LogoutButton from './LogoutButton'; import NotificationsButton from './NotificationsButton'; @@ -9,11 +12,11 @@ import StatusFilters from './StatusFilters'; import TagFilters from './TagFilters'; import TrackerFilters from './TrackerFilters'; import TransferData from './TransferData'; -import DiskUsage from './DiskUsage'; const Sidebar = () => { return ( -
+ @@ -27,7 +30,7 @@ const Sidebar = () => { -
+
); }; diff --git a/client/src/javascript/components/views/TorrentClientOverview.tsx b/client/src/javascript/components/views/TorrentClientOverview.tsx index 1b19bc24..b2121cf7 100644 --- a/client/src/javascript/components/views/TorrentClientOverview.tsx +++ b/client/src/javascript/components/views/TorrentClientOverview.tsx @@ -8,6 +8,8 @@ import FloodActions from '../../actions/FloodActions'; import Sidebar from '../sidebar/Sidebar'; import TorrentList from '../torrent-list/TorrentList'; +import 'overlayscrollbars/css/OverlayScrollbars.css'; + const Alerts = lazy(() => import('../alerts/Alerts')); const Modals = lazy(() => import('../modals/Modals')); diff --git a/client/src/sass/base/_main.scss b/client/src/sass/base/_main.scss index 9d3b8f5a..397f570f 100644 --- a/client/src/sass/base/_main.scss +++ b/client/src/sass/base/_main.scss @@ -5,30 +5,3 @@ body { ul { list-style: none; } - -* { - scrollbar-width: thin; -} - -::-webkit-scrollbar { - height: 6px; - width: 6px; -} - -::-webkit-scrollbar-corner { - background: none; -} - -::-webkit-scrollbar-track { - opacity: 0; -} - -::-webkit-scrollbar-thumb { - border-radius: 4px; - background: #8d8d8d; -} - -::-webkit-scrollbar-thumb:hover { - border-radius: 4px; - background: lighten(#8d8d8d, 10%); -} diff --git a/client/src/sass/components/_scrollbars.scss b/client/src/sass/components/_scrollbars.scss index bf7e61bc..db44a51f 100644 --- a/client/src/sass/components/_scrollbars.scss +++ b/client/src/sass/components/_scrollbars.scss @@ -1,45 +1,127 @@ -$scrollbar--thumb--background--inactive: rgba(#1a2f3d, 0.3); -$scrollbar--thumb--background--hover: rgba(#1a2f3d, 0.6); -$scrollbar--thumb--background--inverted--inactive: rgba(#e9eef2, 0.3); -$scrollbar--thumb--background--inverted--hover: rgba(#e9eef2, 0.6); - -.scrollbars { - &__thumb { - background: $scrollbar--thumb--background--inactive; - border-radius: 10px; - cursor: pointer; - opacity: 0; - transition: background 0.25s, opacity 0.5s; - z-index: 2; - - &:active { - opacity: 1; - } - - &:hover, - &:active { - background: $scrollbar--thumb--background--hover; - } - - &--surrogate { - display: block; - height: 100%; - width: 100%; - } - - .is-inverted & { - background: $scrollbar--thumb--background--inverted--inactive; - - &:hover, - &:active { - background: $scrollbar--thumb--background--inverted--hover; - } - } - } - - &:hover { - .scrollbars__thumb { - opacity: 1; - } - } +* { + scrollbar-width: thin; +} + +::-webkit-scrollbar { + height: 6px; + width: 6px; +} + +::-webkit-scrollbar-corner { + background: none; +} + +::-webkit-scrollbar-track { + opacity: 0; +} + +::-webkit-scrollbar-thumb { + border-radius: 4px; + background: #8d8d8d; +} + +::-webkit-scrollbar-thumb:hover { + border-radius: 4px; + background: lighten(#8d8d8d, 10%); +} + +.os-theme-thin > .os-scrollbar-horizontal { + right: 14px; + height: 14px; + padding: 0px 6px; +} + +.os-theme-thin > .os-scrollbar-vertical { + bottom: 14px; + width: 14px; + padding: 6px 0px; +} + +.os-theme-thin.os-host-rtl > .os-scrollbar-horizontal { + left: 14px; + right: 0; +} + +.os-theme-thin > .os-scrollbar-corner { + height: 14px; + width: 14px; + background-color: transparent; +} + +.os-theme-thin > .os-scrollbar > .os-scrollbar-track { + background: transparent; +} + +.os-theme-thin > .os-scrollbar-horizontal > .os-scrollbar-track:before, +.os-theme-thin > .os-scrollbar-vertical > .os-scrollbar-track:before { + content: ''; + display: block; + position: absolute; + background: rgba(255, 255, 255, 0.15); +} + +.os-theme-thin > .os-scrollbar-horizontal > .os-scrollbar-track:before, +.os-theme-thin > .os-scrollbar-horizontal > .os-scrollbar-track > .os-scrollbar-handle:before { + left: 0; + right: 0; + height: 2px; + top: 50%; + margin-top: -1px; +} + +.os-theme-thin > .os-scrollbar-vertical > .os-scrollbar-track:before, +.os-theme-thin > .os-scrollbar-vertical > .os-scrollbar-track > .os-scrollbar-handle:before { + top: 0; + bottom: 0; + width: 2px; + left: 50%; + margin-left: -1px; +} + +.os-theme-thin > .os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle:before { + content: ''; + display: block; + position: absolute; + background: rgba(255, 255, 255, 0.5); + border-radius: 10px; +} + +.os-theme-thin > .os-scrollbar-horizontal > .os-scrollbar-track > .os-scrollbar-handle:hover:before, +.os-theme-thin > .os-scrollbar-horizontal > .os-scrollbar-track > .os-scrollbar-handle.active:before { + height: 4px; + margin-top: -2px; +} + +.os-theme-thin > .os-scrollbar-vertical > .os-scrollbar-track > .os-scrollbar-handle:hover:before, +.os-theme-thin > .os-scrollbar-vertical > .os-scrollbar-track > .os-scrollbar-handle.active:before { + width: 4px; + margin-left: -2px; +} + +.os-theme-thin > .os-scrollbar-horizontal > .os-scrollbar-track > .os-scrollbar-handle:hover:before, +.os-theme-thin > .os-scrollbar-vertical > .os-scrollbar-track > .os-scrollbar-handle:hover:before { + background: rgba(255, 255, 255, 0.7); +} + +.os-theme-thin > .os-scrollbar-horizontal > .os-scrollbar-track > .os-scrollbar-handle.active:before, +.os-theme-thin > .os-scrollbar-vertical > .os-scrollbar-track > .os-scrollbar-handle.active:before { + background: #fff; +} + +.os-theme-thin > .os-scrollbar-horizontal > .os-scrollbar-track > .os-scrollbar-handle { + height: 100%; + min-width: 30px; +} + +.os-theme-thin > .os-scrollbar-vertical > .os-scrollbar-track > .os-scrollbar-handle { + width: 100%; + min-height: 30px; +} + +.os-theme-thin.os-host-transition > .os-scrollbar-horizontal > .os-scrollbar-track > .os-scrollbar-handle:before { + transition: height 0.3s, margin-top 0.3s, background 0.2s; +} + +.os-theme-thin.os-host-transition > .os-scrollbar-vertical > .os-scrollbar-track > .os-scrollbar-handle:before { + transition: width 0.3s, margin-left 0.3s, background 0.2s; } diff --git a/client/src/sass/style.scss.d.ts b/client/src/sass/style.scss.d.ts index 961f3b74..7d0a6b4d 100644 --- a/client/src/sass/style.scss.d.ts +++ b/client/src/sass/style.scss.d.ts @@ -375,10 +375,16 @@ declare const styles: { readonly 'progress-bar__fill': string; readonly 'progress-bar__fill__wrapper': string; readonly 'candy-stripe': string; - readonly scrollbars__thumb: string; - readonly 'scrollbars__thumb--surrogate': string; - readonly 'is-inverted': string; - readonly scrollbars: string; + readonly 'os-theme-thin': string; + readonly 'os-scrollbar-horizontal': string; + readonly 'os-scrollbar-vertical': string; + readonly 'os-host-rtl': string; + readonly 'os-scrollbar-corner': string; + readonly 'os-scrollbar': string; + readonly 'os-scrollbar-track': string; + readonly 'os-scrollbar-handle': string; + readonly active: string; + readonly 'os-host-transition': string; readonly search: string; readonly textbox: string; readonly 'is-in-use': string; diff --git a/package-lock.json b/package-lock.json index d3d19a41..fbf6fbb9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "@babel/preset-react": "^7.10.4", "@babel/preset-typescript": "^7.12.0", "@formatjs/cli": "^2.13.2", + "@react-hook/media-query": "^1.1.1", "@react-hook/window-size": "^3.0.7", "@types/argon2-browser": "^1.12.0", "@types/async": "^3.2.3", @@ -46,6 +47,7 @@ "@types/morgan": "^1.9.1", "@types/nedb": "^1.8.11", "@types/node": "^12.12.67", + "@types/overlayscrollbars": "^1.12.0", "@types/passport": "^1.0.4", "@types/passport-jwt": "^3.0.3", "@types/react": "^16.9.52", @@ -121,6 +123,8 @@ "nedb": "^1.8.0", "node-sass": "^4.13.0", "optimize-css-assets-webpack-plugin": "^5.0.4", + "overlayscrollbars": "^1.13.0", + "overlayscrollbars-react": "^0.2.2", "pascal-case": "^3.1.1", "passport": "^0.4.1", "passport-jwt": "^4.0.0", @@ -2278,6 +2282,15 @@ "react": ">=16.8" } }, + "node_modules/@react-hook/media-query": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@react-hook/media-query/-/media-query-1.1.1.tgz", + "integrity": "sha512-VM14wDOX5CW5Dn6b2lTiMd79BFMTut9AZj2+vIRT3LCKgMCYmdqruTtzDPSnIVDQdtxdPgtOzvU9oK20LopuOw==", + "dev": true, + "peerDependencies": { + "react": ">=16.8" + } + }, "node_modules/@react-hook/passive-layout-effect": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@react-hook/passive-layout-effect/-/passive-layout-effect-1.2.1.tgz", @@ -3085,6 +3098,12 @@ "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", "dev": true }, + "node_modules/@types/overlayscrollbars": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/@types/overlayscrollbars/-/overlayscrollbars-1.12.0.tgz", + "integrity": "sha512-h/pScHNKi4mb+TrJGDon8Yb06ujFG0mSg12wIO0sWMUF3dQIe2ExRRdNRviaNt9IjxIiOfnRr7FsQAdHwK4sMg==", + "dev": true + }, "node_modules/@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", @@ -15783,6 +15802,22 @@ "os-tmpdir": "^1.0.0" } }, + "node_modules/overlayscrollbars": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/overlayscrollbars/-/overlayscrollbars-1.13.0.tgz", + "integrity": "sha512-p8oHrMeRAKxXDMPI/EBNITj/zTVHKNnAnM59Im+xnoZUlV07FyTg46wom2286jJlXGGfcPFG/ba5NUiCwWNd4w==", + "dev": true + }, + "node_modules/overlayscrollbars-react": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/overlayscrollbars-react/-/overlayscrollbars-react-0.2.2.tgz", + "integrity": "sha512-sRJDaKIxD+No6ygMRaCxejuIH2CksSCUTfaDOzDhPt22lI3IPZq/+Ifw2RT4j+U7hgXLn9P5QqA00f2bsZVwPA==", + "dev": true, + "peerDependencies": { + "overlayscrollbars": "^1.10.0", + "react": "^16.4.0" + } + }, "node_modules/p-each-series": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.1.0.tgz", @@ -29589,13 +29624,22 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/@react-hook/latest/-/latest-1.0.3.tgz", "integrity": "sha512-dy6duzl+JnAZcDbNTfmaP3xHiKtbXYOaz3G51MGVljh548Y8MWzTr+PHLOfvpypEVW9zwvl+VyKjbWKEVbV1Rg==", - "dev": true + "dev": true, + "requires": {} + }, + "@react-hook/media-query": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@react-hook/media-query/-/media-query-1.1.1.tgz", + "integrity": "sha512-VM14wDOX5CW5Dn6b2lTiMd79BFMTut9AZj2+vIRT3LCKgMCYmdqruTtzDPSnIVDQdtxdPgtOzvU9oK20LopuOw==", + "dev": true, + "requires": {} }, "@react-hook/passive-layout-effect": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@react-hook/passive-layout-effect/-/passive-layout-effect-1.2.1.tgz", "integrity": "sha512-IwEphTD75liO8g+6taS+4oqz+nnroocNfWVHWz7j+N+ZO2vYrc6PV1q7GQhuahL0IOR7JccFTsFKQ/mb6iZWAg==", - "dev": true + "dev": true, + "requires": {} }, "@react-hook/throttle": { "version": "2.2.0", @@ -30364,6 +30408,12 @@ "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", "dev": true }, + "@types/overlayscrollbars": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/@types/overlayscrollbars/-/overlayscrollbars-1.12.0.tgz", + "integrity": "sha512-h/pScHNKi4mb+TrJGDon8Yb06ujFG0mSg12wIO0sWMUF3dQIe2ExRRdNRviaNt9IjxIiOfnRr7FsQAdHwK4sMg==", + "dev": true + }, "@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", @@ -31028,7 +31078,8 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true + "dev": true, + "requires": {} }, "acorn-walk": { "version": "7.2.0", @@ -31076,13 +31127,15 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", - "dev": true + "dev": true, + "requires": {} }, "ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true + "dev": true, + "requires": {} }, "alphanum-sort": { "version": "1.0.2", @@ -35247,7 +35300,8 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz", "integrity": "sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ==", - "dev": true + "dev": true, + "requires": {} }, "eslint-scope": { "version": "5.1.1", @@ -37348,7 +37402,8 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.0.0.tgz", "integrity": "sha512-aF2Cf/CkEZrI/vsu5WI/I+akFgdbwQHVE9YRZxATrhH4PVIe6a3BIjwjEcW+z+jP/hNh+YvM3lAAn1wJQ6opSg==", - "dev": true + "dev": true, + "requires": {} }, "ieee754": { "version": "1.2.1", @@ -38333,7 +38388,8 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", - "dev": true + "dev": true, + "requires": {} }, "jest-regex-util": { "version": "26.0.0", @@ -39330,7 +39386,8 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.3.0.tgz", "integrity": "sha512-/V1MnLL/rgJ3jkMWo84UR+K+jF1cxNG1a+KwqeXqTIJ+jtA8aWSHuigx8lTzauiIjBDbwF3NcWQMotd0Dm39jA==", - "dev": true + "dev": true, + "requires": {} }, "marked": { "version": "0.8.2", @@ -39775,7 +39832,8 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/mobx-react-lite/-/mobx-react-lite-3.0.1.tgz", "integrity": "sha512-Ue8uGgT5iOjMyNf5ptoFW7BTvyLIwggzIkoFpwORrqf73TPqu47iLpz/DNvaba3v40kSsEpp050qYroMNuA1xw==", - "dev": true + "dev": true, + "requires": {} }, "morgan": { "version": "1.10.0", @@ -40699,6 +40757,19 @@ "os-tmpdir": "^1.0.0" } }, + "overlayscrollbars": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/overlayscrollbars/-/overlayscrollbars-1.13.0.tgz", + "integrity": "sha512-p8oHrMeRAKxXDMPI/EBNITj/zTVHKNnAnM59Im+xnoZUlV07FyTg46wom2286jJlXGGfcPFG/ba5NUiCwWNd4w==", + "dev": true + }, + "overlayscrollbars-react": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/overlayscrollbars-react/-/overlayscrollbars-react-0.2.2.tgz", + "integrity": "sha512-sRJDaKIxD+No6ygMRaCxejuIH2CksSCUTfaDOzDhPt22lI3IPZq/+Ifw2RT4j+U7hgXLn9P5QqA00f2bsZVwPA==", + "dev": true, + "requires": {} + }, "p-each-series": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.1.0.tgz", @@ -42593,7 +42664,8 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true + "dev": true, + "requires": {} }, "postcss-modules-local-by-default": { "version": "4.0.0", @@ -48497,7 +48569,8 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/use-long-press/-/use-long-press-1.0.4.tgz", "integrity": "sha512-Lw70Sfjut//hEsm/La/ik/5aL042No+4c5AzIb4FhCslLiuVdD8AN2nxRckeJMWBU/88xOwPZ+x+CD5Tjk6sPA==", - "dev": true + "dev": true, + "requires": {} }, "utf8-byte-length": { "version": "1.0.4", @@ -50254,7 +50327,8 @@ "version": "7.3.1", "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==", - "dev": true + "dev": true, + "requires": {} }, "xml-name-validator": { "version": "3.0.0", diff --git a/package.json b/package.json index 1a84f536..88ca8a57 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,7 @@ "@babel/preset-react": "^7.10.4", "@babel/preset-typescript": "^7.12.0", "@formatjs/cli": "^2.13.2", + "@react-hook/media-query": "^1.1.1", "@react-hook/window-size": "^3.0.7", "@types/argon2-browser": "^1.12.0", "@types/async": "^3.2.3", @@ -85,6 +86,7 @@ "@types/morgan": "^1.9.1", "@types/nedb": "^1.8.11", "@types/node": "^12.12.67", + "@types/overlayscrollbars": "^1.12.0", "@types/passport": "^1.0.4", "@types/passport-jwt": "^3.0.3", "@types/react": "^16.9.52", @@ -160,6 +162,8 @@ "nedb": "^1.8.0", "node-sass": "^4.13.0", "optimize-css-assets-webpack-plugin": "^5.0.4", + "overlayscrollbars": "^1.13.0", + "overlayscrollbars-react": "^0.2.2", "pascal-case": "^3.1.1", "passport": "^0.4.1", "passport-jwt": "^4.0.0",