diff --git a/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.test.tsx b/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.test.tsx index 4edcf7313db..32375a5dc29 100644 --- a/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.test.tsx +++ b/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.test.tsx @@ -1,6 +1,6 @@ import React from 'react'; import renderer from 'react-test-renderer'; -import CustomScrollbar from './CustomScrollbar'; +import { CustomScrollbar } from './CustomScrollbar'; describe('CustomScrollbar', () => { it('renders correctly', () => { diff --git a/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.tsx b/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.tsx index 8e79a21fbbd..509a3681a4f 100644 --- a/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.tsx +++ b/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.tsx @@ -1,19 +1,21 @@ -import React, { Component } from 'react'; +import React, { FC, useCallback, useEffect, useRef } from 'react'; import isNil from 'lodash/isNil'; import classNames from 'classnames'; +import { css } from 'emotion'; import Scrollbars from 'react-custom-scrollbars'; +import { useStyles } from '../../themes'; +import { GrafanaTheme } from '@grafana/data'; interface Props { className?: string; autoHide?: boolean; autoHideTimeout?: number; - autoHideDuration?: number; autoHeightMax?: string; hideTracksWhenNotNeeded?: boolean; hideHorizontalTrack?: boolean; hideVerticalTrack?: boolean; scrollTop?: number; - setScrollTop: (event: any) => void; + setScrollTop?: (event: any) => void; autoHeightMin?: number | string; updateAfterMountMs?: number; } @@ -21,122 +23,152 @@ interface Props { /** * Wraps component into component from `react-custom-scrollbars` */ -export class CustomScrollbar extends Component { - static defaultProps: Partial = { - autoHide: false, - autoHideTimeout: 200, - autoHideDuration: 200, - setScrollTop: () => {}, - hideTracksWhenNotNeeded: false, - autoHeightMin: '0', - autoHeightMax: '100%', +export const CustomScrollbar: FC = ({ + autoHide = false, + autoHideTimeout = 200, + setScrollTop, + className, + autoHeightMin = '0', + autoHeightMax = '100%', + hideTracksWhenNotNeeded = false, + hideHorizontalTrack, + hideVerticalTrack, + updateAfterMountMs, + scrollTop, + children, +}) => { + const ref = useRef(null); + const styles = useStyles(getStyles); + + const updateScroll = () => { + if (ref.current && !isNil(scrollTop)) { + ref.current.scrollTop(scrollTop); + } }; - private ref: React.RefObject; + useEffect(() => { + updateScroll(); + }); - constructor(props: Props) { - super(props); - this.ref = React.createRef(); + /** + * Special logic for doing a update a few milliseconds after mount to check for + * updated height due to dynamic content + */ + if (updateAfterMountMs) { + useEffect(() => { + setTimeout(() => { + const scrollbar = ref.current as any; + if (scrollbar?.update) { + scrollbar.update(); + } + }, updateAfterMountMs); + }, []); } - updateScroll() { - const ref = this.ref.current; - const { scrollTop } = this.props; - - if (ref && !isNil(scrollTop)) { - ref.scrollTop(scrollTop); - } - } - - componentDidMount() { - this.updateScroll(); - - // this logic is to make scrollbar visible when content is added body after mount - if (this.props.updateAfterMountMs) { - setTimeout(() => this.updateAfterMount(), this.props.updateAfterMountMs); - } - } - - updateAfterMount() { - if (this.ref && this.ref.current) { - const scrollbar = this.ref.current as any; - if (scrollbar.update) { - scrollbar.update(); - } - } - } - - componentDidUpdate() { - this.updateScroll(); - } - - renderTrack = (track: 'track-vertical' | 'track-horizontal', hideTrack: boolean | undefined, passedProps: any) => { + function renderTrack(className: string, hideTrack: boolean | undefined, passedProps: any) { if (passedProps.style && hideTrack) { passedProps.style.display = 'none'; } - return
; - }; - - renderThumb = (thumb: 'thumb-horizontal' | 'thumb-vertical', passedProps: any) => { - return
; - }; - - renderTrackHorizontal = (passedProps: any) => { - return this.renderTrack('track-horizontal', this.props.hideHorizontalTrack, passedProps); - }; - - renderTrackVertical = (passedProps: any) => { - return this.renderTrack('track-vertical', this.props.hideVerticalTrack, passedProps); - }; - - renderThumbHorizontal = (passedProps: any) => { - return this.renderThumb('thumb-horizontal', passedProps); - }; - - renderThumbVertical = (passedProps: any) => { - return this.renderThumb('thumb-vertical', passedProps); - }; - - renderView = (passedProps: any) => { - return
; - }; - - render() { - const { - className, - children, - autoHeightMax, - autoHeightMin, - setScrollTop, - autoHide, - autoHideTimeout, - hideTracksWhenNotNeeded, - } = this.props; - - return ( - - {children} - - ); + return
; } -} + + const renderTrackHorizontal = useCallback( + (passedProps: any) => { + return renderTrack('track-horizontal', hideHorizontalTrack, passedProps); + }, + [hideHorizontalTrack] + ); + + const renderTrackVertical = useCallback( + (passedProps: any) => { + return renderTrack('track-vertical', hideVerticalTrack, passedProps); + }, + [hideVerticalTrack] + ); + + const renderThumbHorizontal = useCallback((passedProps: any) => { + return
; + }, []); + + const renderThumbVertical = useCallback((passedProps: any) => { + return
; + }, []); + + const renderView = useCallback((passedProps: any) => { + return
; + }, []); + + return ( + + {children} + + ); +}; export default CustomScrollbar; + +const getStyles = (theme: GrafanaTheme) => { + return { + customScrollbar: css` + // Fix for Firefox. For some reason sometimes .view container gets a height of its content, but in order to + // make scroll working it should fit outer container size (scroll appears only when inner container size is + // greater than outer one). + display: flex; + flex-grow: 1; + .scrollbar-view { + display: flex; + flex-grow: 1; + flex-direction: column; + } + .track-vertical { + border-radius: ${theme.border.radius.md}; + width: ${theme.spacing.sm} !important; + right: 0px; + bottom: ${theme.spacing.xxs}; + top: ${theme.spacing.xxs}; + } + .track-horizontal { + border-radius: ${theme.border.radius.md}; + height: ${theme.spacing.sm} !important; + right: ${theme.spacing.xxs}; + bottom: ${theme.spacing.xxs}; + left: ${theme.spacing.xxs}; + } + .thumb-vertical { + background: ${theme.colors.bg3}; + border-radius: ${theme.border.radius.md}; + opacity: 0; + } + .thumb-horizontal { + background: ${theme.colors.bg3}; + border-radius: ${theme.border.radius.md}; + opacity: 0; + } + &:hover { + .thumb-vertical, + .thumb-horizontal { + opacity: 1; + transition: opacity 0.3s ease-in-out; + } + } + `, + }; +}; diff --git a/packages/grafana-ui/src/components/CustomScrollbar/_CustomScrollbar.scss b/packages/grafana-ui/src/components/CustomScrollbar/_CustomScrollbar.scss deleted file mode 100644 index fd846025534..00000000000 --- a/packages/grafana-ui/src/components/CustomScrollbar/_CustomScrollbar.scss +++ /dev/null @@ -1,57 +0,0 @@ -.custom-scrollbar { - // Fix for Firefox. For some reason sometimes .view container gets a height of its content, but in order to - // make scroll working it should fit outer container size (scroll appears only when inner container size is - // greater than outer one). - display: flex; - flex-grow: 1; - - .view { - display: flex; - flex-grow: 1; - flex-direction: column; - } - - .track-vertical { - border-radius: 3px; - width: 8px !important; - right: 2px; - bottom: 2px; - top: 2px; - } - - .track-horizontal { - border-radius: 3px; - height: 8px !important; - - right: 2px; - bottom: 2px; - left: 2px; - } - - .thumb-vertical { - @include gradient-vertical($scrollbarBackground, $scrollbarBackground2); - border-radius: 6px; - opacity: 0; - } - - .thumb-horizontal { - @include gradient-horizontal($scrollbarBackground, $scrollbarBackground2); - border-radius: 6px; - opacity: 0; - } - - &:hover { - .thumb-vertical, - .thumb-horizontal { - opacity: 0.8; - transition: opacity 0.3s ease-in-out; - } - } - - // page scrollbar should stick to left side to aid hitting it - &--page { - .track-vertical { - right: 0; - } - } -} diff --git a/packages/grafana-ui/src/components/CustomScrollbar/__snapshots__/CustomScrollbar.test.tsx.snap b/packages/grafana-ui/src/components/CustomScrollbar/__snapshots__/CustomScrollbar.test.tsx.snap index dd3f59ad1e1..f709b0e6786 100644 --- a/packages/grafana-ui/src/components/CustomScrollbar/__snapshots__/CustomScrollbar.test.tsx.snap +++ b/packages/grafana-ui/src/components/CustomScrollbar/__snapshots__/CustomScrollbar.test.tsx.snap @@ -2,7 +2,7 @@ exports[`CustomScrollbar renders correctly 1`] = `
{ const { navModel, children, ...otherProps } = this.props; return (
- +
{children} diff --git a/public/app/features/dashboard/containers/DashboardPage.tsx b/public/app/features/dashboard/containers/DashboardPage.tsx index 2cdb866b6c1..502bea5ad5c 100644 --- a/public/app/features/dashboard/containers/DashboardPage.tsx +++ b/public/app/features/dashboard/containers/DashboardPage.tsx @@ -316,7 +316,6 @@ export class DashboardPage extends PureComponent { scrollTop={updateScrollTop} hideHorizontalTrack={true} updateAfterMountMs={500} - className="custom-scrollbar--page" >
{initError && this.renderInitFailedState()} diff --git a/public/app/features/dashboard/containers/__snapshots__/DashboardPage.test.tsx.snap b/public/app/features/dashboard/containers/__snapshots__/DashboardPage.test.tsx.snap index 7f43d1abe91..b81673b2996 100644 --- a/public/app/features/dashboard/containers/__snapshots__/DashboardPage.test.tsx.snap +++ b/public/app/features/dashboard/containers/__snapshots__/DashboardPage.test.tsx.snap @@ -106,14 +106,8 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1` className="dashboard-scroll" > @@ -481,14 +475,8 @@ exports[`DashboardPage When dashboard has editview url state should render setti className="dashboard-scroll" > diff --git a/public/app/features/explore/Wrapper.tsx b/public/app/features/explore/Wrapper.tsx index 469f92c5a29..eac32ca2f2e 100644 --- a/public/app/features/explore/Wrapper.tsx +++ b/public/app/features/explore/Wrapper.tsx @@ -31,7 +31,7 @@ export class Wrapper extends Component { return (
- +
diff --git a/public/app/features/query/components/QueryGroup.tsx b/public/app/features/query/components/QueryGroup.tsx index 8f4727e4b65..086561780e9 100644 --- a/public/app/features/query/components/QueryGroup.tsx +++ b/public/app/features/query/components/QueryGroup.tsx @@ -337,13 +337,7 @@ export class QueryGroup extends PureComponent { const styles = getStyles(); return ( - +
{this.renderTopSection(styles)} {dsSettings && (