diff --git a/packages/grafana-ui/src/components/LoadingBar/LoadingBar.tsx b/packages/grafana-ui/src/components/LoadingBar/LoadingBar.tsx index 071af2ecec2..2134f39f87d 100644 --- a/packages/grafana-ui/src/components/LoadingBar/LoadingBar.tsx +++ b/packages/grafana-ui/src/components/LoadingBar/LoadingBar.tsx @@ -1,24 +1,28 @@ import { css, keyframes } from '@emotion/css'; import React, { CSSProperties } from 'react'; +import { GrafanaTheme2 } from '@grafana/data'; + import { useStyles2 } from '../../themes'; export interface LoadingBarProps { width: number; + delay?: number; ariaLabel?: string; } +const BAR_WIDTH = 28; const MILLISECONDS_PER_PIXEL = 2.4; const MIN_DURATION_MS = 500; const MAX_DURATION_MS = 4000; +const DEFAULT_ANIMATION_DELAY = 300; +const MAX_TRANSLATE_X = (100 / BAR_WIDTH) * 100; -export function LoadingBar({ width, ariaLabel = 'Loading bar' }: LoadingBarProps) { - const styles = useStyles2(getStyles); +export function LoadingBar({ width, delay = DEFAULT_ANIMATION_DELAY, ariaLabel = 'Loading bar' }: LoadingBarProps) { const durationMs = Math.min(Math.max(Math.round(width * MILLISECONDS_PER_PIXEL), MIN_DURATION_MS), MAX_DURATION_MS); + const styles = useStyles2((theme) => getStyles(theme, delay, durationMs)); const containerStyles: CSSProperties = { - width: '100%', - animation: `${styles.animation} ${durationMs}ms infinite linear`, - willChange: 'transform', + overflow: 'hidden', }; return ( @@ -28,20 +32,30 @@ export function LoadingBar({ width, ariaLabel = 'Loading bar' }: LoadingBarProps ); } -const getStyles = () => { +const getStyles = (_theme: GrafanaTheme2, delay: number, duration: number) => { + const animation = keyframes({ + '0%': { + transform: 'translateX(-100%)', + }, + // this gives us a delay between iterations + '85%, 100%': { + transform: `translateX(${MAX_TRANSLATE_X}%)`, + }, + }); + return { - animation: keyframes({ - '0%': { - transform: 'translateX(-50%)', - }, - '100%': { - transform: `translateX(100%)`, - }, - }), bar: css({ - width: '28%', + width: BAR_WIDTH + '%', height: 1, background: 'linear-gradient(90deg, rgba(110, 159, 255, 0) 0%, #6E9FFF 80.75%, rgba(110, 159, 255, 0) 100%)', + transform: 'translateX(-100%)', + animationName: animation, + // an initial delay to prevent the loader from showing if the response is faster than the delay + animationDelay: `${delay}ms`, + animationDuration: `${duration}ms`, + animationTimingFunction: 'linear', + animationIterationCount: 'infinite', + willChange: 'transform', }), }; }; diff --git a/packages/grafana-ui/src/components/PanelChrome/PanelChrome.tsx b/packages/grafana-ui/src/components/PanelChrome/PanelChrome.tsx index 90da9adfd77..705f376f84e 100644 --- a/packages/grafana-ui/src/components/PanelChrome/PanelChrome.tsx +++ b/packages/grafana-ui/src/components/PanelChrome/PanelChrome.tsx @@ -395,7 +395,6 @@ const getStyles = (theme: GrafanaTheme2) => { position: 'absolute', top: 0, width: '100%', - overflow: 'hidden', }), containNone: css({ contain: 'none',