diff --git a/public/app/core/components/BouncingLoader/BouncingLoader.tsx b/public/app/core/components/BouncingLoader/BouncingLoader.tsx new file mode 100644 index 00000000000..21e76010532 --- /dev/null +++ b/public/app/core/components/BouncingLoader/BouncingLoader.tsx @@ -0,0 +1,95 @@ +import { css, keyframes } from '@emotion/css'; +import React from 'react'; + +import { GrafanaTheme2 } from '@grafana/data'; +import { useStyles2 } from '@grafana/ui'; + +import { t } from '../../internationalization'; + +export function BouncingLoader() { + const styles = useStyles2(getStyles); + + return ( +
+
+ +
+
+ ); +} + +const fadeIn = keyframes({ + '0%': { + opacity: 0, + animationTimingFunction: 'cubic-bezier(0, 0, 0.5, 1)', + }, + '100%': { + opacity: 1, + }, +}); + +const bounce = keyframes({ + 'from, to': { + transform: 'translateY(0px)', + animationTimingFunction: 'cubic-bezier(0.3, 0, 0.1, 1)', + }, + '50%': { + transform: 'translateY(-50px)', + animationTimingFunction: 'cubic-bezier(0.9, 0, 0.7, 1)', + }, +}); + +const squash = keyframes({ + '0%': { + transform: 'scaleX(1.3) scaleY(0.8)', + animationTimingFunction: 'cubic-bezier(0.3, 0, 0.1, 1)', + }, + '15%': { + transform: 'scaleX(0.75) scaleY(1.25)', + animationTimingFunction: 'cubic-bezier(0, 0, 0.7, 0.75)', + }, + '55%': { + transform: 'scaleX(1.05) scaleY(0.95)', + animationTimingFunction: 'cubic-bezier(0.9, 0, 1, 1)', + }, + '95%': { + transform: 'scaleX(0.75) scaleY(1.25)', + animationTimingFunction: 'cubic-bezier(0, 0, 0, 1)', + }, + '100%': { + transform: 'scaleX(1.3) scaleY(0.8)', + animationTimingFunction: 'cubic-bezier(0, 0, 0.7, 1)', + }, +}); + +const getStyles = (theme: GrafanaTheme2) => ({ + container: css({ + opacity: 0, + animationName: fadeIn, + animationIterationCount: 1, + animationDuration: '0.9s', + animationDelay: '0.5s', + animationFillMode: 'forwards', + }), + + bounce: css({ + textAlign: 'center', + animationName: bounce, + animationDuration: '0.9s', + animationIterationCount: 'infinite', + }), + + logo: css({ + display: 'inline-block', + animationName: squash, + animationDuration: '0.9s', + animationIterationCount: 'infinite', + width: '60px', + height: '60px', + }), +}); diff --git a/public/app/core/navigation/GrafanaRoute.test.tsx b/public/app/core/navigation/GrafanaRoute.test.tsx index 46c99b24139..d599a8479f2 100644 --- a/public/app/core/navigation/GrafanaRoute.test.tsx +++ b/public/app/core/navigation/GrafanaRoute.test.tsx @@ -53,7 +53,7 @@ describe('GrafanaRoute', () => { setup({ route: { component: PageComponent, path: '' } }); - expect(await screen.findByText('Loading...')).toBeInTheDocument(); + expect(await screen.findByLabelText('Loading')).toBeInTheDocument(); }); it('Shows error on page error', async () => { diff --git a/public/app/core/navigation/GrafanaRouteLoading.tsx b/public/app/core/navigation/GrafanaRouteLoading.tsx index 558c264b0ed..3e3675f691f 100644 --- a/public/app/core/navigation/GrafanaRouteLoading.tsx +++ b/public/app/core/navigation/GrafanaRouteLoading.tsx @@ -1,19 +1,27 @@ -import { css } from '@emotion/css'; +import { css, cx } from '@emotion/css'; import React from 'react'; -import { LoadingPlaceholder, useStyles2 } from '@grafana/ui'; +import { GrafanaTheme2 } from '@grafana/data'; +import { config } from '@grafana/runtime'; +import { useStyles2 } from '@grafana/ui'; + +import { BouncingLoader } from '../components/BouncingLoader/BouncingLoader'; export function GrafanaRouteLoading() { const styles = useStyles2(getStyles); return ( -
- +
+
); } -const getStyles = () => ({ +const getStyles = (theme: GrafanaTheme2) => ({ loadingPage: css({ height: '100%', flexDrection: 'column', @@ -21,4 +29,7 @@ const getStyles = () => ({ justifyContent: 'center', alignItems: 'center', }), + loadingPageDockedNav: css({ + backgroundColor: theme.colors.background.primary, + }), }); diff --git a/public/locales/de-DE/grafana.json b/public/locales/de-DE/grafana.json index 12c63683cc5..24d3db1e7fb 100644 --- a/public/locales/de-DE/grafana.json +++ b/public/locales/de-DE/grafana.json @@ -25,6 +25,9 @@ "user": "Nutzer" } }, + "bouncing-loader": { + "label": "" + }, "browse-dashboards": { "action": { "cancel-button": "Abbrechen", diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index 8b9203d23db..a896c5eeec2 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -25,6 +25,9 @@ "user": "User" } }, + "bouncing-loader": { + "label": "Loading" + }, "browse-dashboards": { "action": { "cancel-button": "Cancel", diff --git a/public/locales/es-ES/grafana.json b/public/locales/es-ES/grafana.json index 24e9f4fe743..7918f969323 100644 --- a/public/locales/es-ES/grafana.json +++ b/public/locales/es-ES/grafana.json @@ -25,6 +25,9 @@ "user": "Usuario" } }, + "bouncing-loader": { + "label": "" + }, "browse-dashboards": { "action": { "cancel-button": "Cancelar", diff --git a/public/locales/fr-FR/grafana.json b/public/locales/fr-FR/grafana.json index 6e2789b7d7a..be7d281b615 100644 --- a/public/locales/fr-FR/grafana.json +++ b/public/locales/fr-FR/grafana.json @@ -25,6 +25,9 @@ "user": "Utilisateur" } }, + "bouncing-loader": { + "label": "" + }, "browse-dashboards": { "action": { "cancel-button": "Annuler", diff --git a/public/locales/pseudo-LOCALE/grafana.json b/public/locales/pseudo-LOCALE/grafana.json index 14d7b18e01f..64de0a87f32 100644 --- a/public/locales/pseudo-LOCALE/grafana.json +++ b/public/locales/pseudo-LOCALE/grafana.json @@ -25,6 +25,9 @@ "user": "Ůşęř" } }, + "bouncing-loader": { + "label": "Ŀőäđįʼnģ" + }, "browse-dashboards": { "action": { "cancel-button": "Cäʼnčęľ", diff --git a/public/locales/zh-Hans/grafana.json b/public/locales/zh-Hans/grafana.json index 2de1e243909..2cb76ab32ae 100644 --- a/public/locales/zh-Hans/grafana.json +++ b/public/locales/zh-Hans/grafana.json @@ -25,6 +25,9 @@ "user": "用户" } }, + "bouncing-loader": { + "label": "" + }, "browse-dashboards": { "action": { "cancel-button": "取消", diff --git a/public/views/index.html b/public/views/index.html index a9a811b0ef8..9993f0e2afa 100644 --- a/public/views/index.html +++ b/public/views/index.html @@ -50,7 +50,7 @@ animation-name: preloader-fade-in; animation-iteration-count: 1; animation-duration: 0.9s; - animation-delay: 1.35s; + animation-delay: 0.5s; animation-fill-mode: forwards; } @@ -81,7 +81,7 @@ opacity: 0; animation-name: preloader-fade-in; animation-duration: 0.9s; - animation-delay: 1.8s; + animation-delay: 0.5s; animation-fill-mode: forwards; } @@ -172,10 +172,9 @@
- +
-
Loading Grafana

If you're seeing this Grafana has failed to load its application files