Merge pull request #11456 from alexanderzobnin/fix-11053

Migrating to baron scrollbar WIP
This commit is contained in:
Daniel Lee 2018-04-12 14:56:04 +02:00 committed by GitHub
commit b481e1515d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 403 additions and 77 deletions

View File

@ -136,6 +136,7 @@
"angular-route": "^1.6.6", "angular-route": "^1.6.6",
"angular-sanitize": "^1.6.6", "angular-sanitize": "^1.6.6",
"babel-polyfill": "^6.26.0", "babel-polyfill": "^6.26.0",
"baron": "^3.0.3",
"brace": "^0.10.0", "brace": "^0.10.0",
"classnames": "^2.2.5", "classnames": "^2.2.5",
"clipboard": "^1.7.1", "clipboard": "^1.7.1",
@ -151,7 +152,6 @@
"moment": "^2.18.1", "moment": "^2.18.1",
"mousetrap": "^1.6.0", "mousetrap": "^1.6.0",
"mousetrap-global-bind": "^1.1.0", "mousetrap-global-bind": "^1.1.0",
"perfect-scrollbar": "^1.2.0",
"prop-types": "^15.6.0", "prop-types": "^15.6.0",
"react": "^16.2.0", "react": "^16.2.0",
"react-dom": "^16.2.0", "react-dom": "^16.2.0",

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import PerfectScrollbar from 'perfect-scrollbar'; import baron from 'baron';
export interface Props { export interface Props {
children: any; children: any;
@ -8,31 +8,36 @@ export interface Props {
export default class ScrollBar extends React.Component<Props, any> { export default class ScrollBar extends React.Component<Props, any> {
private container: any; private container: any;
private ps: PerfectScrollbar; private scrollbar: baron;
constructor(props) { constructor(props) {
super(props); super(props);
} }
componentDidMount() { componentDidMount() {
this.ps = new PerfectScrollbar(this.container, { this.scrollbar = baron({
wheelPropagation: true, root: this.container.parentElement,
scroller: this.container,
bar: '.baron__bar',
barOnCls: '_scrollbar',
scrollingCls: '_scrolling',
track: '.baron__track',
}); });
} }
componentDidUpdate() { componentDidUpdate() {
this.ps.update(); this.scrollbar.update();
} }
componentWillUnmount() { componentWillUnmount() {
this.ps.destroy(); this.scrollbar.dispose();
} }
// methods can be invoked by outside // methods can be invoked by outside
setScrollTop(top) { setScrollTop(top) {
if (this.container) { if (this.container) {
this.container.scrollTop = top; this.container.scrollTop = top;
this.ps.update(); this.scrollbar.update();
return true; return true;
} }
@ -42,7 +47,7 @@ export default class ScrollBar extends React.Component<Props, any> {
setScrollLeft(left) { setScrollLeft(left) {
if (this.container) { if (this.container) {
this.container.scrollLeft = left; this.container.scrollLeft = left;
this.ps.update(); this.scrollbar.update();
return true; return true;
} }
@ -55,8 +60,14 @@ export default class ScrollBar extends React.Component<Props, any> {
render() { render() {
return ( return (
<div className={this.props.className} ref={this.handleRef}> <div className="baron baron__root baron__clipper">
{this.props.children} <div className={this.props.className + ' baron__scroller'} ref={this.handleRef}>
{this.props.children}
</div>
<div className="baron__track">
<div className="baron__bar" />
</div>
</div> </div>
); );
} }

View File

@ -167,6 +167,7 @@ export function grafanaAppDirective(playlistSrv, contextSrv, $timeout, $rootScop
if (sidemenuHidden) { if (sidemenuHidden) {
sidemenuHidden = false; sidemenuHidden = false;
body.addClass('sidemenu-open'); body.addClass('sidemenu-open');
appEvents.emit('toggle-inactive-mode');
$timeout(function() { $timeout(function() {
$rootScope.$broadcast('render'); $rootScope.$broadcast('render');
}, 100); }, 100);

View File

@ -0,0 +1,41 @@
import coreModule from 'app/core/core_module';
import appEvents from 'app/core/app_events';
export function pageScrollbar() {
return {
restrict: 'A',
link: function(scope, elem, attrs) {
let lastPos = 0;
appEvents.on(
'dash-scroll',
evt => {
if (evt.restore) {
elem[0].scrollTop = lastPos;
return;
}
lastPos = elem[0].scrollTop;
if (evt.animate) {
elem.animate({ scrollTop: evt.pos }, 500);
} else {
elem[0].scrollTop = evt.pos;
}
},
scope
);
scope.$on('$routeChangeSuccess', () => {
lastPos = 0;
elem[0].scrollTop = 0;
elem[0].focus();
});
elem[0].tabIndex = -1;
elem[0].focus();
},
};
}
coreModule.directive('pageScrollbar', pageScrollbar);

View File

@ -1,15 +1,44 @@
import PerfectScrollbar from 'perfect-scrollbar'; import $ from 'jquery';
import baron from 'baron';
import coreModule from 'app/core/core_module'; import coreModule from 'app/core/core_module';
import appEvents from 'app/core/app_events'; import appEvents from 'app/core/app_events';
const scrollBarHTML = `
<div class="baron__track">
<div class="baron__bar"></div>
</div>
`;
const scrollRootClass = 'baron baron__root';
const scrollerClass = 'baron__scroller';
export function geminiScrollbar() { export function geminiScrollbar() {
return { return {
restrict: 'A', restrict: 'A',
link: function(scope, elem, attrs) { link: function(scope, elem, attrs) {
let scrollbar = new PerfectScrollbar(elem[0], { let scrollRoot = elem.parent();
wheelPropagation: true, let scroller = elem;
wheelSpeed: 3,
}); if (attrs.grafanaScrollbar && attrs.grafanaScrollbar === 'scrollonroot') {
scrollRoot = scroller;
}
scrollRoot.addClass(scrollRootClass);
$(scrollBarHTML).appendTo(scrollRoot);
elem.addClass(scrollerClass);
let scrollParams = {
root: scrollRoot[0],
scroller: scroller[0],
bar: '.baron__bar',
barOnCls: '_scrollbar',
scrollingCls: '_scrolling',
track: '.baron__track',
direction: 'v',
};
let scrollbar = baron(scrollParams);
let lastPos = 0; let lastPos = 0;
appEvents.on( appEvents.on(
@ -31,13 +60,24 @@ export function geminiScrollbar() {
scope scope
); );
// force updating dashboard width
appEvents.on('toggle-sidemenu', forceUpdate, scope);
appEvents.on('toggle-sidemenu-hidden', forceUpdate, scope);
appEvents.on('toggle-view-mode', forceUpdate, scope);
appEvents.on('toggle-kiosk-mode', forceUpdate, scope);
appEvents.on('toggle-inactive-mode', forceUpdate, scope);
function forceUpdate() {
scrollbar.scroll();
}
scope.$on('$routeChangeSuccess', () => { scope.$on('$routeChangeSuccess', () => {
lastPos = 0; lastPos = 0;
elem[0].scrollTop = 0; elem[0].scrollTop = 0;
}); });
scope.$on('$destroy', () => { scope.$on('$destroy', () => {
scrollbar.destroy(); scrollbar.dispose();
}); });
}, },
}; };

View File

@ -19,6 +19,7 @@
<div class="search-dropdown"> <div class="search-dropdown">
<div class="search-dropdown__col_1"> <div class="search-dropdown__col_1">
<div class="search-results-scroller">
<div class="search-results-container" grafana-scrollbar> <div class="search-results-container" grafana-scrollbar>
<h6 ng-show="!ctrl.isLoading && ctrl.results.length === 0">No dashboards matching your query were found.</h6> <h6 ng-show="!ctrl.isLoading && ctrl.results.length === 0">No dashboards matching your query were found.</h6>
<dashboard-search-results <dashboard-search-results
@ -27,6 +28,7 @@
on-folder-expanding="ctrl.folderExpanding()" on-folder-expanding="ctrl.folderExpanding()"
on-folder-expanded="ctrl.folderExpanded($folder)" /> on-folder-expanded="ctrl.folderExpanded($folder)" />
</div> </div>
</div>
</div> </div>
<div class="search-dropdown__col_2"> <div class="search-dropdown__col_2">

View File

@ -47,6 +47,7 @@ import { NavModelSrv, NavModel } from './nav_model_srv';
import { userPicker } from './components/user_picker'; import { userPicker } from './components/user_picker';
import { teamPicker } from './components/team_picker'; import { teamPicker } from './components/team_picker';
import { geminiScrollbar } from './components/scroll/scroll'; import { geminiScrollbar } from './components/scroll/scroll';
import { pageScrollbar } from './components/scroll/page_scroll';
import { gfPageDirective } from './components/gf_page'; import { gfPageDirective } from './components/gf_page';
import { orgSwitcher } from './components/org_switcher'; import { orgSwitcher } from './components/org_switcher';
import { profiler } from './profiler'; import { profiler } from './profiler';
@ -85,6 +86,7 @@ export {
userPicker, userPicker,
teamPicker, teamPicker,
geminiScrollbar, geminiScrollbar,
pageScrollbar,
gfPageDirective, gfPageDirective,
orgSwitcher, orgSwitcher,
manageDashboardsDirective, manageDashboardsDirective,

View File

@ -103,7 +103,7 @@ export class AddPanelPanel extends React.Component<AddPanelPanelProps, AddPanelP
render() { render() {
return ( return (
<div className="panel-container"> <div className="panel-container add-panel-container">
<div className="add-panel"> <div className="add-panel">
<div className="add-panel__header"> <div className="add-panel__header">
<i className="gicon gicon-add-panel" /> <i className="gicon gicon-add-panel" />

View File

@ -196,9 +196,10 @@ export class DashboardViewState {
this.oldTimeRange = ctrl.range; this.oldTimeRange = ctrl.range;
this.fullscreenPanel = panelScope; this.fullscreenPanel = panelScope;
// Firefox doesn't return scrollTop postion properly if 'dash-scroll' is emitted after setViewMode()
this.$scope.appEvent('dash-scroll', { animate: false, pos: 0 });
this.dashboard.setViewMode(ctrl.panel, true, ctrl.editMode); this.dashboard.setViewMode(ctrl.panel, true, ctrl.editMode);
this.$scope.appEvent('panel-fullscreen-enter', { panelId: ctrl.panel.id }); this.$scope.appEvent('panel-fullscreen-enter', { panelId: ctrl.panel.id });
this.$scope.appEvent('dash-scroll', { animate: false, pos: 0 });
} }
registerPanel(panelScope) { registerPanel(panelScope) {

View File

@ -1,6 +1,7 @@
import angular from 'angular'; import angular from 'angular';
import $ from 'jquery';
import Drop from 'tether-drop'; import Drop from 'tether-drop';
import PerfectScrollbar from 'perfect-scrollbar'; import baron from 'baron';
var module = angular.module('grafana.directives'); var module = angular.module('grafana.directives');
@ -86,6 +87,9 @@ module.directive('grafanaPanel', function($rootScope, $document, $timeout) {
function panelHeightUpdated() { function panelHeightUpdated() {
panelContent.css({ height: ctrl.height + 'px' }); panelContent.css({ height: ctrl.height + 'px' });
}
function resizeScrollableContent() {
if (panelScrollbar) { if (panelScrollbar) {
panelScrollbar.update(); panelScrollbar.update();
} }
@ -100,9 +104,30 @@ module.directive('grafanaPanel', function($rootScope, $document, $timeout) {
// update scrollbar after mounting // update scrollbar after mounting
ctrl.events.on('component-did-mount', () => { ctrl.events.on('component-did-mount', () => {
if (ctrl.__proto__.constructor.scrollable) { if (ctrl.__proto__.constructor.scrollable) {
panelScrollbar = new PerfectScrollbar(panelContent[0], { const scrollRootClass = 'baron baron__root baron__clipper panel-content--scrollable';
wheelPropagation: true, const scrollerClass = 'baron__scroller';
const scrollBarHTML = `
<div class="baron__track">
<div class="baron__bar"></div>
</div>
`;
let scrollRoot = panelContent;
let scroller = panelContent.find(':first').find(':first');
scrollRoot.addClass(scrollRootClass);
$(scrollBarHTML).appendTo(scrollRoot);
scroller.addClass(scrollerClass);
panelScrollbar = baron({
root: scrollRoot[0],
scroller: scroller[0],
bar: '.baron__bar',
barOnCls: '_scrollbar',
scrollingCls: '_scrolling',
}); });
panelScrollbar.scroll();
} }
}); });
@ -110,6 +135,7 @@ module.directive('grafanaPanel', function($rootScope, $document, $timeout) {
ctrl.calculatePanelHeight(); ctrl.calculatePanelHeight();
panelHeightUpdated(); panelHeightUpdated();
$timeout(() => { $timeout(() => {
resizeScrollableContent();
ctrl.render(); ctrl.render();
}); });
}); });
@ -199,7 +225,7 @@ module.directive('grafanaPanel', function($rootScope, $document, $timeout) {
} }
if (panelScrollbar) { if (panelScrollbar) {
panelScrollbar.update(); panelScrollbar.dispose();
} }
}); });
}, },

View File

@ -198,7 +198,9 @@ export class QueryVariable implements Variable {
} }
}); });
} else if (sortType === 3) { } else if (sortType === 3) {
options = _.sortBy(options, opt => { return _.toLower(opt.text); }); options = _.sortBy(options, opt => {
return _.toLower(opt.text);
});
} }
if (reverseSort) { if (reverseSort) {

View File

@ -1,18 +1,18 @@
<div dash-class ng-if="ctrl.dashboard"> <div dash-class ng-if="ctrl.dashboard">
<dashnav dashboard="ctrl.dashboard"></dashnav> <dashnav dashboard="ctrl.dashboard"></dashnav>
<div class="scroll-canvas scroll-canvas--dashboard" grafana-scrollbar> <div class="scroll-canvas scroll-canvas--dashboard" page-scrollbar>
<dashboard-settings dashboard="ctrl.dashboard" <dashboard-settings dashboard="ctrl.dashboard"
ng-if="ctrl.dashboardViewState.state.editview" ng-if="ctrl.dashboardViewState.state.editview"
class="dashboard-settings"> class="dashboard-settings">
</dashboard-settings> </dashboard-settings>
<div class="dashboard-container"> <div class="dashboard-container">
<dashboard-submenu ng-if="ctrl.dashboard.meta.submenuEnabled" dashboard="ctrl.dashboard"> <dashboard-submenu ng-if="ctrl.dashboard.meta.submenuEnabled" dashboard="ctrl.dashboard">
</dashboard-submenu> </dashboard-submenu>
<dashboard-grid get-panel-container="ctrl.getPanelContainer"> <dashboard-grid get-panel-container="ctrl.getPanelContainer">
</dashboard-grid> </dashboard-grid>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,17 +1,19 @@
<div class="dashlist" ng-repeat="group in ctrl.groups"> <div>
<div class="dashlist-section" ng-if="group.show"> <div class="dashlist" ng-repeat="group in ctrl.groups">
<h6 class="dashlist-section-header" ng-show="ctrl.panel.headings"> <div class="dashlist-section" ng-if="group.show">
{{group.header}} <h6 class="dashlist-section-header" ng-show="ctrl.panel.headings">
</h6> {{group.header}}
<div class="dashlist-item" ng-repeat="dash in group.list"> </h6>
<a class="dashlist-link dashlist-link-{{dash.type}}" href="{{dash.url}}"> <div class="dashlist-item" ng-repeat="dash in group.list">
<span class="dashlist-title"> <a class="dashlist-link dashlist-link-{{dash.type}}" href="{{dash.url}}">
{{dash.title}} <span class="dashlist-title">
</span> {{dash.title}}
<span class="dashlist-star" ng-click="ctrl.starDashboard(dash, $event)"> </span>
<i class="fa" ng-class="{'fa-star': dash.isStarred, 'fa-star-o': dash.isStarred === false}"></i> <span class="dashlist-star" ng-click="ctrl.starDashboard(dash, $event)">
</span> <i class="fa" ng-class="{'fa-star': dash.isStarred, 'fa-star-o': dash.isStarred === false}"></i>
</a> </span>
</a>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,7 +1,7 @@
import angular from 'angular'; import angular from 'angular';
import _ from 'lodash'; import _ from 'lodash';
import $ from 'jquery'; import $ from 'jquery';
import PerfectScrollbar from 'perfect-scrollbar'; import baron from 'baron';
var module = angular.module('grafana.directives'); var module = angular.module('grafana.directives');
@ -16,11 +16,10 @@ module.directive('graphLegend', function(popoverSrv, $timeout) {
var i; var i;
var legendScrollbar; var legendScrollbar;
const legendRightDefaultWidth = 10; const legendRightDefaultWidth = 10;
let legendElem = elem.parent();
scope.$on('$destroy', function() { scope.$on('$destroy', function() {
if (legendScrollbar) { destroyScrollbar();
legendScrollbar.destroy();
}
}); });
ctrl.events.on('render-legend', () => { ctrl.events.on('render-legend', () => {
@ -112,7 +111,7 @@ module.directive('graphLegend', function(popoverSrv, $timeout) {
} }
function render() { function render() {
let legendWidth = elem.width(); let legendWidth = legendElem.width();
if (!ctrl.panel.legend.show) { if (!ctrl.panel.legend.show) {
elem.empty(); elem.empty();
firstRender = true; firstRender = true;
@ -134,8 +133,8 @@ module.directive('graphLegend', function(popoverSrv, $timeout) {
// Set width so it works with IE11 // Set width so it works with IE11
var width: any = panel.legend.rightSide && panel.legend.sideWidth ? panel.legend.sideWidth + 'px' : ''; var width: any = panel.legend.rightSide && panel.legend.sideWidth ? panel.legend.sideWidth + 'px' : '';
var ieWidth: any = panel.legend.rightSide && panel.legend.sideWidth ? panel.legend.sideWidth - 1 + 'px' : ''; var ieWidth: any = panel.legend.rightSide && panel.legend.sideWidth ? panel.legend.sideWidth - 1 + 'px' : '';
elem.css('min-width', width); legendElem.css('min-width', width);
elem.css('width', ieWidth); legendElem.css('width', ieWidth);
elem.toggleClass('graph-legend-table', panel.legend.alignAsTable === true); elem.toggleClass('graph-legend-table', panel.legend.alignAsTable === true);
@ -241,8 +240,10 @@ module.directive('graphLegend', function(popoverSrv, $timeout) {
tbodyElem.append(tableHeaderElem); tbodyElem.append(tableHeaderElem);
tbodyElem.append(seriesElements); tbodyElem.append(seriesElements);
elem.append(tbodyElem); elem.append(tbodyElem);
tbodyElem.wrap('<div class="graph-legend-scroll"></div>');
} else { } else {
elem.append(seriesElements); elem.append('<div class="graph-legend-scroll"></div>');
elem.find('.graph-legend-scroll').append(seriesElements);
} }
if (!panel.legend.rightSide || (panel.legend.rightSide && legendWidth !== legendRightDefaultWidth)) { if (!panel.legend.rightSide || (panel.legend.rightSide && legendWidth !== legendRightDefaultWidth)) {
@ -253,23 +254,45 @@ module.directive('graphLegend', function(popoverSrv, $timeout) {
} }
function addScrollbar() { function addScrollbar() {
const scrollbarOptions = { const scrollRootClass = 'baron baron__root';
// Number of pixels the content height can surpass the container height without enabling the scroll bar. const scrollerClass = 'baron__scroller';
scrollYMarginOffset: 2, const scrollBarHTML = `
suppressScrollX: true, <div class="baron__track">
wheelPropagation: true, <div class="baron__bar"></div>
</div>
`;
let scrollRoot = elem;
let scroller = elem.find('.graph-legend-scroll');
// clear existing scroll bar track to prevent duplication
scrollRoot.find('.baron__track').remove();
scrollRoot.addClass(scrollRootClass);
$(scrollBarHTML).appendTo(scrollRoot);
scroller.addClass(scrollerClass);
let scrollbarParams = {
root: scrollRoot[0],
scroller: scroller[0],
bar: '.baron__bar',
track: '.baron__track',
barOnCls: '_scrollbar',
scrollingCls: '_scrolling',
}; };
if (!legendScrollbar) { if (!legendScrollbar) {
legendScrollbar = new PerfectScrollbar(elem[0], scrollbarOptions); legendScrollbar = baron(scrollbarParams);
} else { } else {
legendScrollbar.update(); destroyScrollbar();
legendScrollbar = baron(scrollbarParams);
} }
legendScrollbar.scroll();
} }
function destroyScrollbar() { function destroyScrollbar() {
if (legendScrollbar) { if (legendScrollbar) {
legendScrollbar.destroy(); legendScrollbar.dispose();
legendScrollbar = undefined; legendScrollbar = undefined;
} }
} }

View File

@ -3,7 +3,9 @@ var template = `
<div class="graph-panel__chart" grafana-graph ng-dblclick="ctrl.zoomOut()"> <div class="graph-panel__chart" grafana-graph ng-dblclick="ctrl.zoomOut()">
</div> </div>
<div class="graph-legend" graph-legend></div> <div class="graph-legend">
<div class="graph-legend-content" graph-legend></div>
</div>
</div> </div>
`; `;

View File

@ -1,5 +1,13 @@
.add-panel-container {
height: 100%;
}
.add-panel { .add-panel {
height: 100%; height: 100%;
.baron__root {
height: calc(100% - 43px);
}
} }
.add-panel__header { .add-panel__header {
@ -39,7 +47,6 @@
flex-direction: row; flex-direction: row;
flex-wrap: wrap; flex-wrap: wrap;
overflow: auto; overflow: auto;
height: calc(100% - 43px);
align-content: flex-start; align-content: flex-start;
justify-content: space-around; justify-content: space-around;
position: relative; position: relative;

View File

@ -49,6 +49,7 @@
} }
.graph-legend { .graph-legend {
display: flex;
flex: 0 1 auto; flex: 0 1 auto;
max-height: 30%; max-height: 30%;
margin: 0; margin: 0;
@ -56,11 +57,27 @@
padding-top: 6px; padding-top: 6px;
position: relative; position: relative;
// fix for Firefox (white stripe on the right of scrollbar)
width: calc(100% - 1px);
.popover-content { .popover-content {
padding: 0; padding: 0;
} }
} }
.graph-legend-content {
position: relative;
// fix for Firefox (white stripe on the right of scrollbar)
width: calc(100% - 1px);
}
.graph-legend-scroll {
position: relative;
overflow: auto !important;
padding: 1px;
}
.graph-legend-icon { .graph-legend-icon {
position: relative; position: relative;
padding-right: 4px; padding-right: 4px;
@ -115,8 +132,20 @@
// fix for phantomjs // fix for phantomjs
.body--phantomjs { .body--phantomjs {
.graph-panel--legend-right { .graph-panel--legend-right {
.graph-legend {
display: inline-block;
}
.graph-panel__chart {
display: flex;
}
.graph-legend-table { .graph-legend-table {
display: table; display: table;
.graph-legend-scroll {
display: table;
}
} }
} }
} }
@ -124,9 +153,9 @@
.graph-legend-table { .graph-legend-table {
tbody { tbody {
display: block; display: block;
position: relative;
overflow-y: auto; overflow-y: auto;
overflow-x: hidden; overflow-x: hidden;
height: 100%;
padding-bottom: 1px; padding-bottom: 1px;
padding-right: 5px; padding-right: 5px;
padding-left: 5px; padding-left: 5px;

View File

@ -9,6 +9,11 @@
-ms-touch-action: auto; -ms-touch-action: auto;
} }
// ._scrollbar {
// overflow-x: hidden !important;
// overflow-y: auto;
// }
/* /*
* Scrollbar rail styles * Scrollbar rail styles
*/ */
@ -101,7 +106,7 @@
opacity: 0.9; opacity: 0.9;
} }
// Srollbars // Scrollbars
// //
::-webkit-scrollbar { ::-webkit-scrollbar {
@ -172,3 +177,120 @@
border-top: 1px solid $scrollbarBorder; border-top: 1px solid $scrollbarBorder;
border-left: 1px solid $scrollbarBorder; border-left: 1px solid $scrollbarBorder;
} }
// Baron styles
.baron {
// display: inline-block; // this brakes phantomjs rendering (width becomes 0)
overflow: hidden;
}
// Fix for side menu on mobile devices
.main-view.baron {
width: unset;
}
.baron__clipper {
position: relative;
overflow: hidden;
}
.baron__scroller {
overflow-y: scroll;
-ms-overflow-style: none;
-moz-box-sizing: border-box;
box-sizing: border-box;
margin: 0;
border: 0;
padding: 0;
width: 100%;
height: 100%;
-webkit-overflow-scrolling: touch;
/* remove line to customize scrollbar in iOs */
}
.baron__scroller::-webkit-scrollbar {
width: 0;
height: 0;
}
.baron__track {
display: none;
position: absolute;
top: 0;
right: 0;
bottom: 0;
}
.baron._scrollbar .baron__track {
display: block;
}
.baron__free {
position: absolute;
top: 0;
bottom: 0;
right: 0;
}
.baron__bar {
display: none;
position: absolute;
right: 0;
z-index: 1;
// width: 10px;
background: #999;
// height: 15px;
width: 15px;
transition: background-color 0.2s linear, opacity 0.2s linear;
opacity: 0;
}
.baron._scrollbar .baron__bar {
display: block;
@include gradient-vertical($scrollbarBackground, $scrollbarBackground2);
border-radius: 6px;
width: 6px;
/* there must be 'right' for ps__thumb-y */
right: 0px;
/* please don't change 'position' */
position: absolute;
// background-color: transparent;
// opacity: 0.6;
&:hover,
&:focus {
// background-color: transparent;
opacity: 0.9;
}
}
.panel-hover-highlight .baron__track .baron__bar {
opacity: 0.6;
}
.baron._scrolling > .baron__track .baron__bar {
opacity: 0.9;
}
// fix for phantomjs
.body--phantomjs .baron__track .baron__bar {
opacity: 0 !important;
}
.baron__control {
display: none;
}
.baron.panel-content--scrollable {
// Width needs to be set to prevent content width issues
// Set to less than 100% for fixing Firefox issue (white stripe on the right of scrollbar)
width: calc(100% - 2px);
.baron__scroller {
padding-top: 1px;
}
}

View File

@ -102,14 +102,21 @@
} }
} }
.search-results-scroller {
display: flex;
position: relative;
}
.search-results-container { .search-results-container {
height: 100%;
display: block; display: block;
padding: $spacer; padding: $spacer;
position: relative; position: relative;
flex-grow: 10; flex-grow: 10;
margin-bottom: 1rem; margin-bottom: 1rem;
// Fix for search scroller in mobile view
height: unset;
.label-tag { .label-tag {
margin-left: 6px; margin-left: 6px;
font-size: 11px; font-size: 11px;

View File

@ -28,12 +28,20 @@
width: 100%; width: 100%;
overflow: auto; overflow: auto;
height: 100%; height: 100%;
-webkit-overflow-scrolling: touch;
&--dashboard { &--dashboard {
height: calc(100% - 56px); height: calc(100% - 56px);
} }
} }
// fix for phantomjs
.body--phantomjs {
.scroll-canvas {
overflow: hidden;
}
}
.page-body { .page-body {
padding-top: $spacer*2; padding-top: $spacer*2;
min-height: 500px; min-height: 500px;

View File

@ -16,7 +16,7 @@
<link rel="icon" type="image/png" href="public/img/fav32.png"> <link rel="icon" type="image/png" href="public/img/fav32.png">
<link rel="mask-icon" href="public/img/grafana_mask_icon.svg" color="#F05A28"> <link rel="mask-icon" href="public/img/grafana_mask_icon.svg" color="#F05A28">
<link rel="apple-touch-icon" href="public/img/fav32.png"> <link rel="apple-touch-icon" href="public/img/fav32.png">
</head> </head>
<body ng-cloak class="theme-[[ .Theme ]]"> <body ng-cloak class="theme-[[ .Theme ]]">
@ -40,7 +40,7 @@
</div> </div>
<div class="main-view"> <div class="main-view">
<div class="scroll-canvas" grafana-scrollbar> <div class="scroll-canvas" page-scrollbar>
<div ng-view></div> <div ng-view></div>
<footer class="footer"> <footer class="footer">

View File

@ -1162,6 +1162,10 @@ balanced-match@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
baron@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/baron/-/baron-3.0.3.tgz#0f0a08a567062882e130a0ecfd41a46d52103f4a"
base64-arraybuffer@0.1.5: base64-arraybuffer@0.1.5:
version "0.1.5" version "0.1.5"
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8" resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8"
@ -7503,10 +7507,6 @@ pend@~1.2.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
perfect-scrollbar@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/perfect-scrollbar/-/perfect-scrollbar-1.2.0.tgz#ad23a2529c17f4535f21d1486f8bc3046e31a9d2"
performance-now@^0.2.0: performance-now@^0.2.0:
version "0.2.0" version "0.2.0"
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5"