mirror of
https://github.com/zoriya/flood.git
synced 2025-12-20 14:15:15 +00:00
Add custom scrollbar to sidepanel and torrent list
This commit is contained in:
@@ -61,7 +61,13 @@ body {
|
|||||||
&__list {
|
&__list {
|
||||||
|
|
||||||
&__wrapper {
|
&__wrapper {
|
||||||
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|
||||||
|
&--custom-scroll {
|
||||||
|
flex: 1;
|
||||||
|
height: auto !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
35
client/source/sass/components/_scrollbars.scss
Normal file
35
client/source/sass/components/_scrollbars.scss
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
.scrollbars {
|
||||||
|
|
||||||
|
&__thumb {
|
||||||
|
background: $scrollbar--thumb--background--inactive;
|
||||||
|
border-radius: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: 0;
|
||||||
|
transition: background 0.25s, opacity 0.25s;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:active {
|
||||||
|
background: $scrollbar--thumb--background--hover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-inverted & {
|
||||||
|
background: $scrollbar--thumb--background--inverted--inactive;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:active {
|
||||||
|
background: $scrollbar--thumb--background--inverted--hover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
|
||||||
|
.scrollbars__thumb {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,7 +34,6 @@
|
|||||||
list-style: none;
|
list-style: none;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
overflow: auto;
|
|
||||||
transition: opacity 1s;
|
transition: opacity 1s;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
@import "components/loading-indicator";
|
@import "components/loading-indicator";
|
||||||
@import "components/modals";
|
@import "components/modals";
|
||||||
@import "components/progress-bar";
|
@import "components/progress-bar";
|
||||||
|
@import "components/scrollbars";
|
||||||
@import "components/sidebar";
|
@import "components/sidebar";
|
||||||
@import "components/sidebar-filter";
|
@import "components/sidebar-filter";
|
||||||
@import "components/textbox-repeater";
|
@import "components/textbox-repeater";
|
||||||
|
|||||||
@@ -188,3 +188,9 @@ $directory-tree--icon--folder--open: rgba(#82aac5, 0.5);
|
|||||||
|
|
||||||
$directory-tree--file-details--foreground: #2b4456;
|
$directory-tree--file-details--foreground: #2b4456;
|
||||||
$directory-tree--file-details--hover--foreground: #527893;
|
$directory-tree--file-details--hover--foreground: #527893;
|
||||||
|
|
||||||
|
// scrollbars
|
||||||
|
$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);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import ClientStats from '../sidebar/TransferData';
|
import ClientStats from '../sidebar/TransferData';
|
||||||
|
import CustomScrollbars from '../ui/CustomScrollbars';
|
||||||
import SearchBox from '../forms/SearchBox';
|
import SearchBox from '../forms/SearchBox';
|
||||||
import SpeedLimitDropdown from '../sidebar/SpeedLimitDropdown';
|
import SpeedLimitDropdown from '../sidebar/SpeedLimitDropdown';
|
||||||
import StatusFilters from '../sidebar/StatusFilters';
|
import StatusFilters from '../sidebar/StatusFilters';
|
||||||
@@ -9,13 +10,13 @@ import TrackerFilters from '../sidebar/TrackerFilters';
|
|||||||
class Sidebar extends React.Component {
|
class Sidebar extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="application__sidebar">
|
<CustomScrollbars className="application__sidebar" inverted={true}>
|
||||||
<SpeedLimitDropdown />
|
<SpeedLimitDropdown />
|
||||||
<ClientStats />
|
<ClientStats />
|
||||||
<SearchBox />
|
<SearchBox />
|
||||||
<StatusFilters />
|
<StatusFilters />
|
||||||
<TrackerFilters />
|
<TrackerFilters />
|
||||||
</div>
|
</CustomScrollbars>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import CSSTransitionGroup from 'react-addons-css-transition-group';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
|
|
||||||
|
import CustomScrollbars from '../ui/CustomScrollbars';
|
||||||
import EventTypes from '../../constants/EventTypes';
|
import EventTypes from '../../constants/EventTypes';
|
||||||
import LoadingIndicator from '../ui/LoadingIndicator';
|
import LoadingIndicator from '../ui/LoadingIndicator';
|
||||||
import Torrent from './Torrent';
|
import Torrent from './Torrent';
|
||||||
@@ -164,7 +165,7 @@ export default class TorrentListContainer extends React.Component {
|
|||||||
setScrollPosition() {
|
setScrollPosition() {
|
||||||
if (this.refs.torrentList) {
|
if (this.refs.torrentList) {
|
||||||
this.setState({
|
this.setState({
|
||||||
scrollPosition: ReactDOM.findDOMNode(this.refs.torrentList).scrollTop
|
scrollPosition: this.refs.torrentList.refs.scrollbar.getScrollTop()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -172,7 +173,7 @@ export default class TorrentListContainer extends React.Component {
|
|||||||
setViewportHeight() {
|
setViewportHeight() {
|
||||||
if (this.refs.torrentList) {
|
if (this.refs.torrentList) {
|
||||||
this.setState({
|
this.setState({
|
||||||
viewportHeight: ReactDOM.findDOMNode(this.refs.torrentList).offsetHeight
|
viewportHeight: this.refs.torrentList.refs.scrollbar.getHeight()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -230,12 +231,14 @@ export default class TorrentListContainer extends React.Component {
|
|||||||
<CSSTransitionGroup
|
<CSSTransitionGroup
|
||||||
component="div"
|
component="div"
|
||||||
className="torrent__list__wrapper"
|
className="torrent__list__wrapper"
|
||||||
onScroll={this.handleScroll}
|
|
||||||
ref="torrentList"
|
|
||||||
transitionName="torrent__list--loading"
|
transitionName="torrent__list--loading"
|
||||||
transitionEnterTimeout={1000}
|
transitionEnterTimeout={1000}
|
||||||
transitionLeaveTimeout={1000}>
|
transitionLeaveTimeout={1000}>
|
||||||
|
<CustomScrollbars className="torrent__list__wrapper--custom-scroll"
|
||||||
|
ref="torrentList"
|
||||||
|
scrollHandler={this.handleScroll} key="torrent-list__scroll-wrapper">
|
||||||
{content}
|
{content}
|
||||||
|
</CustomScrollbars>
|
||||||
</CSSTransitionGroup>
|
</CSSTransitionGroup>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
43
client/source/scripts/components/ui/CustomScrollbars.js
Normal file
43
client/source/scripts/components/ui/CustomScrollbars.js
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import classnames from 'classnames';
|
||||||
|
import React from 'react';
|
||||||
|
import {Scrollbars} from 'react-custom-scrollbars';
|
||||||
|
|
||||||
|
export default class CustomScrollbar extends React.Component {
|
||||||
|
getHorizontalThumb(props) {
|
||||||
|
return (
|
||||||
|
<div {...props}
|
||||||
|
className="scrollbars__thumb scrollbars__thumb--horizontal"/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getVerticalThumb(props) {
|
||||||
|
return (
|
||||||
|
<div {...props}
|
||||||
|
className="scrollbars__thumb scrollbars__thumb--vertical"/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let classes = classnames('scrollbars', {
|
||||||
|
[this.props.className]: this.props.className,
|
||||||
|
'is-inverted': this.props.inverted
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Scrollbars
|
||||||
|
className={classes}
|
||||||
|
ref="scrollbar"
|
||||||
|
renderThumbHorizontal={this.getHorizontalThumb}
|
||||||
|
renderThumbVertical={this.getVerticalThumb}
|
||||||
|
onScroll={this.props.scrollHandler}>
|
||||||
|
{this.props.children}
|
||||||
|
</Scrollbars>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomScrollbar.defaultProps = {
|
||||||
|
className: '',
|
||||||
|
inverted: false,
|
||||||
|
scrollHandler: null
|
||||||
|
};
|
||||||
@@ -51,7 +51,8 @@ var webpackConfig = {
|
|||||||
loaders: [
|
loaders: [
|
||||||
{
|
{
|
||||||
test: /\.js$/,
|
test: /\.js$/,
|
||||||
loader: 'babel-loader?cacheDirectory'
|
loader: 'babel-loader?cacheDirectory',
|
||||||
|
exclude: /node_modules/
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
preLoaders: [
|
preLoaders: [
|
||||||
|
|||||||
@@ -33,9 +33,10 @@
|
|||||||
"passport": "^0.3.2",
|
"passport": "^0.3.2",
|
||||||
"passport-http": "^0.3.0",
|
"passport-http": "^0.3.0",
|
||||||
"q": "^1.2.0",
|
"q": "^1.2.0",
|
||||||
"react": "^0.14.3",
|
"react": "^0.14.7",
|
||||||
"react-addons-css-transition-group": "^0.14.3",
|
"react-addons-css-transition-group": "^0.14.7",
|
||||||
"react-dom": "^0.14.3",
|
"react-custom-scrollbars": "^2.3.0",
|
||||||
|
"react-dom": "^0.14.7",
|
||||||
"sax": "^0.6.1",
|
"sax": "^0.6.1",
|
||||||
"serve-favicon": "~2.2.0",
|
"serve-favicon": "~2.2.0",
|
||||||
"xmlbuilder": "^2.6.2",
|
"xmlbuilder": "^2.6.2",
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -613,7 +613,6 @@ body {
|
|||||||
z-index: 2; }
|
z-index: 2; }
|
||||||
.application__panel--torrent-list.is-open {
|
.application__panel--torrent-list.is-open {
|
||||||
-webkit-transform: translateX(85%);
|
-webkit-transform: translateX(85%);
|
||||||
-ms-transform: translateX(85%);
|
|
||||||
transform: translateX(85%); }
|
transform: translateX(85%); }
|
||||||
.application__panel--torrent-details {
|
.application__panel--torrent-details {
|
||||||
right: 15%;
|
right: 15%;
|
||||||
@@ -629,10 +628,20 @@ body {
|
|||||||
max-height: 35px; }
|
max-height: 35px; }
|
||||||
|
|
||||||
.torrent__list__wrapper {
|
.torrent__list__wrapper {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -webkit-flex;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
-webkit-box-flex: 1;
|
-webkit-box-flex: 1;
|
||||||
-webkit-flex: 1;
|
-webkit-flex: 1;
|
||||||
-ms-flex: 1;
|
-ms-flex: 1;
|
||||||
flex: 1; }
|
flex: 1; }
|
||||||
|
.torrent__list__wrapper--custom-scroll {
|
||||||
|
-webkit-box-flex: 1;
|
||||||
|
-webkit-flex: 1;
|
||||||
|
-ms-flex: 1;
|
||||||
|
flex: 1;
|
||||||
|
height: auto !important; }
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background: #1a2f3d; }
|
background: #1a2f3d; }
|
||||||
@@ -745,7 +754,6 @@ body {
|
|||||||
-webkit-transition: fill 0.25s;
|
-webkit-transition: fill 0.25s;
|
||||||
transition: fill 0.25s;
|
transition: fill 0.25s;
|
||||||
-webkit-transform: translateX(-50%) translateY(-50%);
|
-webkit-transform: translateX(-50%) translateY(-50%);
|
||||||
-ms-transform: translateX(-50%) translateY(-50%);
|
|
||||||
transform: translateX(-50%) translateY(-50%);
|
transform: translateX(-50%) translateY(-50%);
|
||||||
width: 30px; }
|
width: 30px; }
|
||||||
|
|
||||||
@@ -1095,7 +1103,6 @@ body {
|
|||||||
-webkit-transition: fill 0.25s;
|
-webkit-transition: fill 0.25s;
|
||||||
transition: fill 0.25s;
|
transition: fill 0.25s;
|
||||||
-webkit-transform: translate(-50%, -50%);
|
-webkit-transform: translate(-50%, -50%);
|
||||||
-ms-transform: translate(-50%, -50%);
|
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
width: 8px; }
|
width: 8px; }
|
||||||
|
|
||||||
@@ -1136,7 +1143,6 @@ body {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
-webkit-transform: translateY(0);
|
-webkit-transform: translateY(0);
|
||||||
-ms-transform: translateY(0);
|
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
width: 100%; }
|
width: 100%; }
|
||||||
.loading-indicator__bar:after {
|
.loading-indicator__bar:after {
|
||||||
@@ -1148,7 +1154,6 @@ body {
|
|||||||
display: block;
|
display: block;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
-webkit-transform: translateX(-100%);
|
-webkit-transform: translateX(-100%);
|
||||||
-ms-transform: translateX(-100%);
|
|
||||||
transform: translateX(-100%);
|
transform: translateX(-100%);
|
||||||
width: 25%; }
|
width: 25%; }
|
||||||
.loading-indicator__bar--1 {
|
.loading-indicator__bar--1 {
|
||||||
@@ -1156,7 +1161,6 @@ body {
|
|||||||
.loading-indicator__bar--2 {
|
.loading-indicator__bar--2 {
|
||||||
top: 50%;
|
top: 50%;
|
||||||
-webkit-transform: translateY(-50%);
|
-webkit-transform: translateY(-50%);
|
||||||
-ms-transform: translateY(-50%);
|
|
||||||
transform: translateY(-50%); }
|
transform: translateY(-50%); }
|
||||||
.loading-indicator__bar--2:after {
|
.loading-indicator__bar--2:after {
|
||||||
-webkit-animation-delay: 0.5s;
|
-webkit-animation-delay: 0.5s;
|
||||||
@@ -1189,7 +1193,6 @@ body {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: 10%;
|
top: 10%;
|
||||||
-webkit-transform: translate(-50%, 0);
|
-webkit-transform: translate(-50%, 0);
|
||||||
-ms-transform: translate(-50%, 0);
|
|
||||||
transform: translate(-50%, 0);
|
transform: translate(-50%, 0);
|
||||||
width: 500px; }
|
width: 500px; }
|
||||||
.modal__content--align-center {
|
.modal__content--align-center {
|
||||||
@@ -1258,6 +1261,25 @@ body {
|
|||||||
.has-error .progress-bar__fill {
|
.has-error .progress-bar__fill {
|
||||||
background: #e95779; }
|
background: #e95779; }
|
||||||
|
|
||||||
|
.scrollbars__thumb {
|
||||||
|
background: rgba(26, 47, 61, 0.3);
|
||||||
|
border-radius: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: 0;
|
||||||
|
-webkit-transition: background 0.25s, opacity 0.25s;
|
||||||
|
transition: background 0.25s, opacity 0.25s; }
|
||||||
|
.scrollbars__thumb:active {
|
||||||
|
opacity: 1; }
|
||||||
|
.scrollbars__thumb:hover, .scrollbars__thumb:active {
|
||||||
|
background: rgba(26, 47, 61, 0.6); }
|
||||||
|
.is-inverted .scrollbars__thumb {
|
||||||
|
background: rgba(233, 238, 242, 0.3); }
|
||||||
|
.is-inverted .scrollbars__thumb:hover, .is-inverted .scrollbars__thumb:active {
|
||||||
|
background: rgba(233, 238, 242, 0.6); }
|
||||||
|
|
||||||
|
.scrollbars:hover .scrollbars__thumb {
|
||||||
|
opacity: 1; }
|
||||||
|
|
||||||
.application__sidebar {
|
.application__sidebar {
|
||||||
box-shadow: 1px 0 rgba(6, 9, 11, 0.3);
|
box-shadow: 1px 0 rgba(6, 9, 11, 0.3);
|
||||||
color: #53718a;
|
color: #53718a;
|
||||||
@@ -1283,7 +1305,6 @@ body {
|
|||||||
-webkit-transition: fill 0.25s, opacity 0.25s;
|
-webkit-transition: fill 0.25s, opacity 0.25s;
|
||||||
transition: fill 0.25s, opacity 0.25s;
|
transition: fill 0.25s, opacity 0.25s;
|
||||||
-webkit-transform: translateY(-50%);
|
-webkit-transform: translateY(-50%);
|
||||||
-ms-transform: translateY(-50%);
|
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
width: 22px; }
|
width: 22px; }
|
||||||
.sidebar__item--search .textbox {
|
.sidebar__item--search .textbox {
|
||||||
@@ -1551,7 +1572,6 @@ body {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
-webkit-transform: translate(-50%, -50%);
|
-webkit-transform: translate(-50%, -50%);
|
||||||
-ms-transform: translate(-50%, -50%);
|
|
||||||
transform: translate(-50%, -50%); }
|
transform: translate(-50%, -50%); }
|
||||||
|
|
||||||
.torrent__list {
|
.torrent__list {
|
||||||
@@ -1562,7 +1582,6 @@ body {
|
|||||||
list-style: none;
|
list-style: none;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
overflow: auto;
|
|
||||||
-webkit-transition: opacity 1s;
|
-webkit-transition: opacity 1s;
|
||||||
transition: opacity 1s;
|
transition: opacity 1s;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
@@ -1646,6 +1665,7 @@ body {
|
|||||||
-webkit-box-align: end;
|
-webkit-box-align: end;
|
||||||
-webkit-align-items: flex-end;
|
-webkit-align-items: flex-end;
|
||||||
-ms-flex-align: end;
|
-ms-flex-align: end;
|
||||||
|
-ms-grid-row-align: flex-end;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
color: #807f7e;
|
color: #807f7e;
|
||||||
-webkit-box-flex: 1;
|
-webkit-box-flex: 1;
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user