From 7bf6904119e9cbfc8e115211a1b14f3fc4bb2a88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 15 Aug 2017 11:51:47 +0200 Subject: [PATCH] ux: scrollbar stuff --- package.json | 1 + public/app/core/components/scroll/scroll.ts | 230 ++---------------- public/app/core/core.ts | 2 + .../features/dashboard/dashnav/dashnav.html | 1 + public/app/headers/common.d.ts | 5 + public/app/system.conf.js | 6 +- public/sass/_grafana.scss | 1 + public/sass/components/_scrollbar.scss | 148 +++++++++++ public/sass/layout/_page.scss | 3 - tasks/options/copy.js | 2 +- tasks/options/watch.js | 1 + yarn.lock | 36 ++- 12 files changed, 206 insertions(+), 230 deletions(-) create mode 100644 public/sass/components/_scrollbar.scss diff --git a/package.json b/package.json index e70633ac9a8..4b29ebdccfb 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "dependencies": { "eventemitter3": "^2.0.2", "gaze": "^1.1.2", + "gemini-scrollbar": "^1.5.2", "grunt-jscs": "3.0.1", "grunt-sass-lint": "^0.2.2", "grunt-sync": "^0.6.2", diff --git a/public/app/core/components/scroll/scroll.ts b/public/app/core/components/scroll/scroll.ts index 914f3ba2dd9..06bdcb8c864 100644 --- a/public/app/core/components/scroll/scroll.ts +++ b/public/app/core/components/scroll/scroll.ts @@ -1,211 +1,19 @@ -// /// -// -// import _ from 'lodash'; -// -// var objectAssign = require('object-assign'); -// var Emitter = require('tiny-emitter'); -// var Lethargy = require('lethargy').Lethargy; -// var support = require('./support'); -// var clone = require('./clone'); -// var bindAll = require('bindall-standalone'); -// var EVT_ID = 'virtualscroll'; -// -// var keyCodes = { -// LEFT: 37, -// UP: 38, -// RIGHT: 39, -// DOWN: 40 -// }; -// -// function VirtualScroll(this: any, options) { -// _.bindAll(this, '_onWheel', '_onMouseWheel', '_onTouchStart', '_onTouchMove', '_onKeyDown'); -// -// this.el = window; -// if (options && options.el) { -// this.el = options.el; -// delete options.el; -// } -// -// this.options = _.assign({ -// mouseMultiplier: 1, -// touchMultiplier: 2, -// firefoxMultiplier: 15, -// keyStep: 120, -// preventTouch: false, -// unpreventTouchClass: 'vs-touchmove-allowed', -// limitInertia: false -// }, options); -// -// if (this.options.limitInertia) this._lethargy = new Lethargy(); -// -// this._emitter = new Emitter(); -// this._event = { -// y: 0, -// x: 0, -// deltaX: 0, -// deltaY: 0 -// }; -// -// this.touchStartX = null; -// this.touchStartY = null; -// this.bodyTouchAction = null; -// } -// -// VirtualScroll.prototype._notify = function(e) { -// var evt = this._event; -// evt.x += evt.deltaX; -// evt.y += evt.deltaY; -// -// this._emitter.emit(EVT_ID, { -// x: evt.x, -// y: evt.y, -// deltaX: evt.deltaX, -// deltaY: evt.deltaY, -// originalEvent: e -// }); -// }; -// -// VirtualScroll.prototype._onWheel = function(e) { -// var options = this.options; -// if (this._lethargy && this._lethargy.check(e) === false) return; -// -// var evt = this._event; -// -// // In Chrome and in Firefox (at least the new one) -// evt.deltaX = e.wheelDeltaX || e.deltaX * -1; -// evt.deltaY = e.wheelDeltaY || e.deltaY * -1; -// -// // for our purpose deltamode = 1 means user is on a wheel mouse, not touch pad -// // real meaning: https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent#Delta_modes -// if(support.isFirefox && e.deltaMode == 1) { -// evt.deltaX *= options.firefoxMultiplier; -// evt.deltaY *= options.firefoxMultiplier; -// } -// -// evt.deltaX *= options.mouseMultiplier; -// evt.deltaY *= options.mouseMultiplier; -// -// this._notify(e); -// }; -// -// VirtualScroll.prototype._onMouseWheel = function(e) { -// if (this.options.limitInertia && this._lethargy.check(e) === false) return; -// -// var evt = this._event; -// -// // In Safari, IE and in Chrome if 'wheel' isn't defined -// evt.deltaX = (e.wheelDeltaX) ? e.wheelDeltaX : 0; -// evt.deltaY = (e.wheelDeltaY) ? e.wheelDeltaY : e.wheelDelta; -// -// this._notify(e); -// }; -// -// VirtualScroll.prototype._onTouchStart = function(e) { -// var t = (e.targetTouches) ? e.targetTouches[0] : e; -// this.touchStartX = t.pageX; -// this.touchStartY = t.pageY; -// }; -// -// VirtualScroll.prototype._onTouchMove = function(e) { -// var options = this.options; -// if(options.preventTouch -// && !e.target.classList.contains(options.unpreventTouchClass)) { -// e.preventDefault(); -// } -// -// var evt = this._event; -// -// var t = (e.targetTouches) ? e.targetTouches[0] : e; -// -// evt.deltaX = (t.pageX - this.touchStartX) * options.touchMultiplier; -// evt.deltaY = (t.pageY - this.touchStartY) * options.touchMultiplier; -// -// this.touchStartX = t.pageX; -// this.touchStartY = t.pageY; -// -// this._notify(e); -// }; -// -// VirtualScroll.prototype._onKeyDown = function(e) { -// var evt = this._event; -// evt.deltaX = evt.deltaY = 0; -// -// switch(e.keyCode) { -// case keyCodes.LEFT: -// case keyCodes.UP: -// evt.deltaY = this.options.keyStep; -// break; -// -// case keyCodes.RIGHT: -// case keyCodes.DOWN: -// evt.deltaY = - this.options.keyStep; -// break; -// -// default: -// return; -// } -// -// this._notify(e); -// }; -// -// VirtualScroll.prototype._bind = function() { -// if(support.hasWheelEvent) this.el.addEventListener('wheel', this._onWheel); -// if(support.hasMouseWheelEvent) this.el.addEventListener('mousewheel', this._onMouseWheel); -// -// if(support.hasTouch) { -// this.el.addEventListener('touchstart', this._onTouchStart); -// this.el.addEventListener('touchmove', this._onTouchMove); -// } -// -// if(support.hasPointer && support.hasTouchWin) { -// this.bodyTouchAction = document.body.style.msTouchAction; -// document.body.style.msTouchAction = 'none'; -// this.el.addEventListener('MSPointerDown', this._onTouchStart, true); -// this.el.addEventListener('MSPointerMove', this._onTouchMove, true); -// } -// -// if(support.hasKeyDown) document.addEventListener('keydown', this._onKeyDown); -// }; -// -// VirtualScroll.prototype._unbind = function() { -// if(support.hasWheelEvent) this.el.removeEventListener('wheel', this._onWheel); -// if(support.hasMouseWheelEvent) this.el.removeEventListener('mousewheel', this._onMouseWheel); -// -// if(support.hasTouch) { -// this.el.removeEventListener('touchstart', this._onTouchStart); -// this.el.removeEventListener('touchmove', this._onTouchMove); -// } -// -// if(support.hasPointer && support.hasTouchWin) { -// document.body.style.msTouchAction = this.bodyTouchAction; -// this.el.removeEventListener('MSPointerDown', this._onTouchStart, true); -// this.el.removeEventListener('MSPointerMove', this._onTouchMove, true); -// } -// -// if(support.hasKeyDown) document.removeEventListener('keydown', this._onKeyDown); -// }; -// -// VirtualScroll.prototype.on = function(cb, ctx) { -// this._emitter.on(EVT_ID, cb, ctx); -// -// var events = this._emitter.e; -// if (events && events[EVT_ID] && events[EVT_ID].length === 1) this._bind(); -// }; -// -// VirtualScroll.prototype.off = function(cb, ctx) { -// this._emitter.off(EVT_ID, cb, ctx); -// -// var events = this._emitter.e; -// if (!events[EVT_ID] || events[EVT_ID].length <= 0) this._unbind(); -// }; -// -// VirtualScroll.prototype.reset = function() { -// var evt = this._event; -// evt.x = 0; -// evt.y = 0; -// }; -// -// VirtualScroll.prototype.destroy = function() { -// this._emitter.off(); -// this._unbind(); -// }; +/// + +import GeminiScrollbar from 'gemini-scrollbar'; +import coreModule from 'app/core/core_module'; +import _ from 'lodash'; + +export function geminiScrollbar() { + return { + restrict: 'A', + link: function(scope, elem, attrs) { + var myScrollbar = new GeminiScrollbar({ + autoshow: false, + element: elem[0] + }).create(); + } + }; +} + +coreModule.directive('geminiScrollbar', geminiScrollbar); diff --git a/public/app/core/core.ts b/public/app/core/core.ts index 92db42be8c4..fed63f37955 100644 --- a/public/app/core/core.ts +++ b/public/app/core/core.ts @@ -51,6 +51,7 @@ import {JsonExplorer} from './components/json_explorer/json_explorer'; import {NavModelSrv, NavModel} from './nav_model_srv'; import {userPicker} from './components/user_picker'; import {userGroupPicker} from './components/user_group_picker'; +import {geminiScrollbar} from './components/scroll/scroll'; export { arrayJoin, @@ -81,4 +82,5 @@ export { NavModel, userPicker, userGroupPicker, + geminiScrollbar, }; diff --git a/public/app/features/dashboard/dashnav/dashnav.html b/public/app/features/dashboard/dashnav/dashnav.html index 9fe6cfb9a1e..e8114e0298f 100644 --- a/public/app/features/dashboard/dashnav/dashnav.html +++ b/public/app/features/dashboard/dashnav/dashnav.html @@ -81,3 +81,4 @@ + diff --git a/public/app/headers/common.d.ts b/public/app/headers/common.d.ts index 9ea5e96654d..ec80c01407d 100644 --- a/public/app/headers/common.d.ts +++ b/public/app/headers/common.d.ts @@ -72,3 +72,8 @@ declare module 'd3' { var d3: any; export default d3; } + +declare module 'gemini-scrollbar' { + var d3: any; + export default d3; +} diff --git a/public/app/system.conf.js b/public/app/system.conf.js index 816cba4fb42..0a89f6f58b9 100644 --- a/public/app/system.conf.js +++ b/public/app/system.conf.js @@ -2,7 +2,7 @@ System.config({ defaultJSExtenions: true, baseURL: 'public', paths: { - 'virtual-scroll': 'vendor/npm/virtual-scroll/src/index.js', + 'gemini-scrollbar': 'vendor/npm/gemini-scrollbar/index.js', 'mousetrap': 'vendor/npm/mousetrap/mousetrap.js', 'remarkable': 'vendor/npm/remarkable/dist/remarkable.js', 'tether': 'vendor/npm/tether/dist/js/tether.js', @@ -56,10 +56,6 @@ System.config({ }, meta: { - 'vendor/npm/virtual-scroll/src/indx.js': { - format: 'cjs', - exports: 'VirtualScroll', - }, 'vendor/angular/angular.js': { format: 'global', deps: ['jquery'], diff --git a/public/sass/_grafana.scss b/public/sass/_grafana.scss index f22036dd266..e965baf9cbe 100644 --- a/public/sass/_grafana.scss +++ b/public/sass/_grafana.scss @@ -31,6 +31,7 @@ @import "layout/page"; // COMPONENTS +@import "components/scrollbar"; @import "components/cards"; @import "components/buttons"; @import "components/navs"; diff --git a/public/sass/components/_scrollbar.scss b/public/sass/components/_scrollbar.scss new file mode 100644 index 00000000000..b16acb75475 --- /dev/null +++ b/public/sass/components/_scrollbar.scss @@ -0,0 +1,148 @@ +/** + * gemini-scrollbar + * @version 1.5.2 + * @link http://noeldelgado.github.io/gemini-scrollbar/ + * @license MIT + */ + +/* disable selection while dragging */ +.gm-scrollbar-disable-selection { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +/* fallback for native floating scrollbars */ +.gm-prevented { + -webkit-overflow-scrolling: touch; +} +.gm-prevented > .gm-scrollbar { + display: none; +} + +/* actual gemini-scrollbar styles */ +.gm-scrollbar-container { + position: relative; + overflow: hidden!important; + width: 100%; + height: 100%; +} + +.gm-scrollbar { + position: absolute; + right: 2px; + bottom: 2px; + z-index: 1; + border-radius: 3px; +} + +.gm-scrollbar.-vertical { + width: 6px; + top: 2px; +} + +.gm-scrollbar.-horizontal { + height: 6px; + left: 2px; +} + +.gm-scrollbar .thumb { + position: relative; + display: block; + width: 0; + height: 0; + cursor: pointer; + border-radius: inherit; + background-color: lighten($body-bg, 10%); + transform: translate3d(0,0,0); +} + +.gm-scrollbar .thumb:hover, +.gm-scrollbar .thumb:active { + background-color: lighten($body-bg, 20%); +} + +.gm-scrollbar.-vertical .thumb { + width: 100%; +} + +.gm-scrollbar.-horizontal .thumb { + height: 100%; +} + +.gm-scrollbar-container .gm-scroll-view { + width: 100%; + height: 100%; + overflow: scroll; + transform: translate3d(0,0,0); + -webkit-overflow-scrolling: touch; +} + +/* @option: autoshow */ +.gm-scrollbar-container.gm-autoshow .gm-scrollbar { + opacity: 0; + transition: opacity 120ms ease-out; +} +.gm-scrollbar-container.gm-autoshow:hover > .gm-scrollbar, +.gm-scrollbar-container.gm-autoshow:active > .gm-scrollbar, +.gm-scrollbar-container.gm-autoshow:focus > .gm-scrollbar { + opacity: 1; + transition: opacity 340ms ease-out; +} + +.gm-resize-trigger { + position: absolute; + display: block; + top: 0; + left: 0; + height: 100%; + width: 100%; + overflow: hidden; + pointer-events: none; + z-index: -1; + opacity: 0; +} + + +// // Srollbars +// // +// +// ::-webkit-scrollbar { +// width: 8px; +// height: 8px; +// } +// +// ::-webkit-scrollbar:hover { +// height: 8px; +// } +// +// ::-webkit-scrollbar-button:start:decrement, +// ::-webkit-scrollbar-button:end:increment { display: none; } +// ::-webkit-scrollbar-button:horizontal:decrement { display: none; } +// ::-webkit-scrollbar-button:horizontal:increment { display: none; } +// ::-webkit-scrollbar-button:vertical:decrement { display: none; } +// ::-webkit-scrollbar-button:vertical:increment { display: none; } +// ::-webkit-scrollbar-button:horizontal:decrement:active { background-image: none; } +// ::-webkit-scrollbar-button:horizontal:increment:active { background-image: none; } +// ::-webkit-scrollbar-button:vertical:decrement:active { background-image: none; } +// ::-webkit-scrollbar-button:vertical:increment:active {background-image: none; } +// ::-webkit-scrollbar-track-piece { background-color: transparent; } +// +// ::-webkit-scrollbar-thumb:vertical { +// height: 50px; +// background: -webkit-gradient(linear, left top, right top, color-stop(0%, $scrollbarBackground), color-stop(100%, $scrollbarBackground2)); +// border: 1px solid $scrollbarBorder; +// border-top: 1px solid $scrollbarBorder; +// border-left: 1px solid $scrollbarBorder; +// } +// +// ::-webkit-scrollbar-thumb:horizontal { +// width: 50px; +// background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, $scrollbarBackground), color-stop(100%, $scrollbarBackground2)); +// border: 1px solid $scrollbarBorder; +// border-top: 1px solid $scrollbarBorder; +// border-left: 1px solid $scrollbarBorder; +// } diff --git a/public/sass/layout/_page.scss b/public/sass/layout/_page.scss index d823a8e457f..199bf876628 100644 --- a/public/sass/layout/_page.scss +++ b/public/sass/layout/_page.scss @@ -26,9 +26,6 @@ overflow: auto; } -.page-header-inner { -} - .page-body { @include media-breakpoint-up(md) { display: flex; diff --git a/tasks/options/copy.js b/tasks/options/copy.js index 59921576da3..ba8b70f8674 100644 --- a/tasks/options/copy.js +++ b/tasks/options/copy.js @@ -32,7 +32,7 @@ module.exports = function(config) { 'tether-drop/**/*', 'remarkable/dist/*', 'remarkable/dist/*', - 'virtual-scroll/**/*', + 'gemini-scrollbar/*.js', 'mousetrap/**/*', ], dest: '<%= srcDir %>/vendor/npm' diff --git a/tasks/options/watch.js b/tasks/options/watch.js index f7bea8af721..c3449524243 100644 --- a/tasks/options/watch.js +++ b/tasks/options/watch.js @@ -24,6 +24,7 @@ module.exports = function(config, grunt) { gaze([ config.srcDir + '/sass/**/*', config.srcDir + '/app/**/*', + config.srcDir + '/vendor/npm/gemini-scrollbar/*.js', ], function(err, watcher) { console.log('Gaze watchers setup'); diff --git a/yarn.lock b/yarn.lock index a9100c88e10..db2f5db1f53 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1601,6 +1601,10 @@ gaze@^1.0.0, gaze@^1.1.2: dependencies: globule "^1.0.0" +gemini-scrollbar@^1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/gemini-scrollbar/-/gemini-scrollbar-1.5.2.tgz#06528e49afe155c45ce9f7c9ee754a9e6f4ed341" + generate-function@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" @@ -1926,12 +1930,12 @@ grunt-sass-lint@^0.2.2: dependencies: sass-lint "^1.10.2" -grunt-sass@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/grunt-sass/-/grunt-sass-1.2.1.tgz#fb87b6caac46fb32d45177fd2e4b6ff7468c1919" +grunt-sass@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/grunt-sass/-/grunt-sass-2.0.0.tgz#9074cf9d7b4592e20f7788caa727b8f9aa06b60a" dependencies: each-async "^1.0.0" - node-sass "^3.7.0" + node-sass "^4.0.0" object-assign "^4.0.1" grunt-string-replace@~1.3.1: @@ -2816,6 +2820,10 @@ lodash.keys@^3.0.0: lodash.isarguments "^3.0.0" lodash.isarray "^3.0.0" +lodash.mergewith@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz#150cf0a16791f5903b8891eab154609274bdea55" + lodash@3.7.x: version "3.7.0" resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.7.0.tgz#3678bd8ab995057c07ade836ed2ef087da811d45" @@ -3151,9 +3159,9 @@ node-pre-gyp@^0.6.29: tar "~2.2.1" tar-pack "~3.3.0" -node-sass@^3.7.0: - version "3.13.1" - resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-3.13.1.tgz#7240fbbff2396304b4223527ed3020589c004fc2" +node-sass@^4.0.0: + version "4.5.3" + resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.5.3.tgz#d09c9d1179641239d1b97ffc6231fdcec53e1568" dependencies: async-foreach "^0.1.3" chalk "^1.1.1" @@ -3164,13 +3172,15 @@ node-sass@^3.7.0: in-publish "^2.0.0" lodash.assign "^4.2.0" lodash.clonedeep "^4.3.2" + lodash.mergewith "^4.6.0" meow "^3.7.0" mkdirp "^0.5.1" nan "^2.3.2" node-gyp "^3.3.1" npmlog "^4.0.0" - request "^2.61.0" + request "^2.79.0" sass-graph "^2.1.1" + stdout-stream "^1.4.0" "nomnom@>= 1.5.x": version "1.8.1" @@ -3627,7 +3637,7 @@ readable-stream@1.1: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^2.0.0, "readable-stream@^2.0.0 || ^1.1.13", readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5: +readable-stream@^2.0.0, "readable-stream@^2.0.0 || ^1.1.13", readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5: version "2.2.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.2.tgz#a9e6fec3c7dda85f8bb1b3ba7028604556fc825e" dependencies: @@ -3745,7 +3755,7 @@ request-progress@~2.0.1: dependencies: throttleit "^1.0.0" -request@2, request@^2.61.0, request@^2.79.0, request@~2.79.0: +request@2, request@^2.79.0, request@~2.79.0: version "2.79.0" resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" dependencies: @@ -4117,6 +4127,12 @@ statuses@1, "statuses@>= 1.3.1 < 2", statuses@~1.3.0: version "1.3.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" +stdout-stream@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.0.tgz#a2c7c8587e54d9427ea9edb3ac3f2cd522df378b" + dependencies: + readable-stream "^2.0.1" + stream-buffers@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/stream-buffers/-/stream-buffers-2.2.0.tgz#91d5f5130d1cef96dcfa7f726945188741d09ee4"