mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Shared UX] Reduce React.lazy usage; fix Discover Empty State load (#132758)
* [Shared UX] Reduce React.lazy usage; fix Discover Empty State load * Addressing feedback * We can optimize the calls by replacing methods with impls that return already-retrieved values.
This commit is contained in:
parent
30c4db69b7
commit
537d812a56
17 changed files with 142 additions and 233 deletions
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export { DataViewIllustration } from './data_view_illustration';
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { EuiPanel } from '@elastic/eui';
|
||||
|
||||
import { withSuspense } from '@kbn/shared-ux-utility';
|
||||
|
||||
export const LazyDataViewIllustration = React.lazy(() =>
|
||||
import('./data_view_illustration').then(({ DataViewIllustration }) => ({
|
||||
default: DataViewIllustration,
|
||||
}))
|
||||
);
|
||||
|
||||
export const DataViewIllustration = withSuspense(
|
||||
LazyDataViewIllustration,
|
||||
<EuiPanel color="subdued" style={{ width: 226, height: 206 }} />
|
||||
);
|
|
@ -9,38 +9,10 @@
|
|||
import React from 'react';
|
||||
import { withSuspense } from '@kbn/shared-ux-utility';
|
||||
|
||||
export const LazyToolbarButton = React.lazy(() =>
|
||||
import('./toolbar').then(({ ToolbarButton }) => ({
|
||||
default: ToolbarButton,
|
||||
}))
|
||||
);
|
||||
|
||||
/**
|
||||
* A `ToolbarButton` component that is wrapped by the `withSuspense` HOC. This component can
|
||||
* be used directly by consumers and will load the `LazyToolbarButton` component lazily with
|
||||
* a predefined fallback and error boundary.
|
||||
*/
|
||||
export const ToolbarButton = withSuspense(LazyToolbarButton);
|
||||
|
||||
/**
|
||||
* An example of the toolbar button and popover
|
||||
*/
|
||||
export { AddFromLibraryButton, ToolbarPopover } from './toolbar';
|
||||
|
||||
/**
|
||||
* The Lazily-loaded `IconButtonGroup` component. Consumers should use `React.Suspense` or the
|
||||
* `withSuspense` HOC to load this component.
|
||||
*/
|
||||
export const LazyIconButtonGroup = React.lazy(() =>
|
||||
import('./toolbar').then(({ IconButtonGroup }) => ({
|
||||
default: IconButtonGroup,
|
||||
}))
|
||||
);
|
||||
|
||||
/**
|
||||
* The IconButtonGroup component that is wrapped by the `withSuspence` HOC.
|
||||
*/
|
||||
export const IconButtonGroup = withSuspense(LazyIconButtonGroup);
|
||||
export { ToolbarButton, IconButtonGroup, AddFromLibraryButton, ToolbarPopover } from './toolbar';
|
||||
export { KibanaPageTemplateSolutionNav } from './page_template/solution_nav';
|
||||
export type { KibanaPageTemplateProps } from './page_template';
|
||||
export { KibanaPageTemplate } from './page_template';
|
||||
|
||||
/**
|
||||
* A `KibanaNoDataPage` component, with service hooks. Consumers should use `React.Suspennse` or the
|
||||
|
@ -58,35 +30,3 @@ export const KibanaNoDataPageLazy = React.lazy(() =>
|
|||
* a predefined fallback and error boundary.
|
||||
*/
|
||||
export const KibanaNoDataPage = withSuspense(KibanaNoDataPageLazy);
|
||||
|
||||
/**
|
||||
* The lazily loaded `KibanaPageTemplate` component that is wrapped by the `withSuspense` HOC. Consumers should use
|
||||
* `React.Suspense` or `withSuspense` HOC to load this component.
|
||||
*/
|
||||
export const KibanaPageTemplateLazy = React.lazy(() =>
|
||||
import('./page_template').then(({ KibanaPageTemplate }) => ({
|
||||
default: KibanaPageTemplate,
|
||||
}))
|
||||
);
|
||||
|
||||
/**
|
||||
* A `KibanaPageTemplate` component that is wrapped by the `withSuspense` HOC. This component can
|
||||
* be used directly by consumers and will load the `KibanaPageTemplateLazy` component lazily with
|
||||
* a predefined fallback and error boundary.
|
||||
*/
|
||||
export const KibanaPageTemplate = withSuspense(KibanaPageTemplateLazy);
|
||||
|
||||
/**
|
||||
* A `KibanaPageTemplateProps` type.
|
||||
*/
|
||||
export type { KibanaPageTemplateProps } from './page_template';
|
||||
|
||||
/**
|
||||
* The lazily loaded `KibanaPageTemplateSolutionNav` component that is wrapped by the `withSuspense` HOC. Consumers should use
|
||||
* `React.Suspense` or `withSuspense` HOC to load this component.
|
||||
*/
|
||||
export const KibanaPageTemplateSolutionNavLazy = React.lazy(() =>
|
||||
import('./page_template/solution_nav').then(({ KibanaPageTemplateSolutionNav }) => ({
|
||||
default: KibanaPageTemplateSolutionNav,
|
||||
}))
|
||||
);
|
||||
|
|
|
@ -7,7 +7,7 @@ exports[`NoDataPage render 1`] = `
|
|||
<EuiText
|
||||
textAlign="center"
|
||||
>
|
||||
<ForwardRef
|
||||
<KibanaSolutionAvatar
|
||||
iconType="logoKibana"
|
||||
name="Analytics"
|
||||
size="xxl"
|
||||
|
|
|
@ -237,7 +237,7 @@ exports[`KibanaPageTemplateSolutionNav renders with icon 1`] = `
|
|||
size="xs"
|
||||
>
|
||||
<h2>
|
||||
<ForwardRef
|
||||
<KibanaSolutionAvatar
|
||||
className="kbnPageTemplateSolutionNav__avatar"
|
||||
iconType="logoElastic"
|
||||
name="Solution"
|
||||
|
|
|
@ -6,24 +6,5 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { withSuspense } from '@kbn/shared-ux-utility';
|
||||
|
||||
export { KibanaSolutionAvatar } from './solution_avatar';
|
||||
export type { KibanaSolutionAvatarProps } from './solution_avatar';
|
||||
|
||||
/**
|
||||
* The Lazily-loaded `KibanaSolutionAvatar` component. Consumers should use `React.Suspense` or
|
||||
* the withSuspense` HOC to load this component.
|
||||
*/
|
||||
export const KibanaSolutionAvatarLazy = React.lazy(() =>
|
||||
import('./solution_avatar').then(({ KibanaSolutionAvatar }) => ({
|
||||
default: KibanaSolutionAvatar,
|
||||
}))
|
||||
);
|
||||
|
||||
/**
|
||||
* A `KibanaSolutionAvatar` component that is wrapped by the `withSuspense` HOC. This component can
|
||||
* be used directly by consumers and will load the `KibanaPageTemplateSolutionNavAvatarLazy` component lazily with
|
||||
* a predefined fallback and error boundary.
|
||||
*/
|
||||
export const KibanaSolutionAvatar = withSuspense(KibanaSolutionAvatarLazy);
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { withSuspense } from '@kbn/shared-ux-utility';
|
||||
|
||||
export { ExitFullScreenButtonKibanaProvider, ExitFullScreenButtonProvider } from './services';
|
||||
|
||||
/**
|
||||
* Lazy-loaded pure component. Must be wrapped in `React.Suspense`.
|
||||
*/
|
||||
export const LazyExitFullScreenButtonComponent = React.lazy(() =>
|
||||
import('./exit_full_screen_button.component').then(({ ExitFullScreenButton }) => ({
|
||||
default: ExitFullScreenButton,
|
||||
}))
|
||||
);
|
||||
|
||||
/**
|
||||
* A pure component that resembles a button to exit full screen mode.
|
||||
*/
|
||||
export const ExitFullScreenButtonComponent = withSuspense(LazyExitFullScreenButtonComponent);
|
||||
|
||||
/**
|
||||
* Lazy-loaded connected component. Must be wrapped in `React.Suspense` and a Provider.
|
||||
*/
|
||||
export const LazyExitFullScreenButton = React.lazy(() =>
|
||||
import('./exit_full_screen_button').then(({ ExitFullScreenButton }) => ({
|
||||
default: ExitFullScreenButton,
|
||||
}))
|
||||
);
|
||||
|
||||
/**
|
||||
* A component that can be used to exit full screen mode in Kibana. Requires a Provider for
|
||||
* relevant services.
|
||||
*/
|
||||
export const ExitFullScreenButton = withSuspense(LazyExitFullScreenButton);
|
11
packages/shared-ux/button/exit_full_screen/src/index.tsx
Normal file
11
packages/shared-ux/button/exit_full_screen/src/index.tsx
Normal file
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export { ExitFullScreenButtonKibanaProvider, ExitFullScreenButtonProvider } from './services';
|
||||
export { ExitFullScreenButton as ExitFullScreenButtonComponent } from './exit_full_screen_button.component';
|
||||
export { ExitFullScreenButton } from './exit_full_screen_button';
|
|
@ -6,22 +6,5 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { withSuspense } from '@kbn/shared-ux-utility';
|
||||
|
||||
export { AnalyticsNoDataPageProvider, AnalyticsNoDataPageKibanaProvider } from './services';
|
||||
|
||||
/**
|
||||
* Lazy-loaded connected component. Must be wrapped in `React.Suspense`.
|
||||
*/
|
||||
export const LazyAnalyticsNoDataPage = React.lazy(() =>
|
||||
import('./analytics_no_data_page').then(({ AnalyticsNoDataPage }) => ({
|
||||
default: AnalyticsNoDataPage,
|
||||
}))
|
||||
);
|
||||
|
||||
/**
|
||||
* An entire page that can be displayed when Kibana "has no data", specifically for Analytics.
|
||||
* Requires a Provider for relevant services.
|
||||
*/
|
||||
export const AnalyticsNoDataPage = withSuspense(LazyAnalyticsNoDataPage);
|
||||
export { AnalyticsNoDataPage } from './analytics_no_data_page';
|
||||
|
|
12
packages/shared-ux/prompt/no_data_views/src/index.ts
Normal file
12
packages/shared-ux/prompt/no_data_views/src/index.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export { NoDataViewsPromptKibanaProvider, NoDataViewsPromptProvider } from './services';
|
||||
export type { NoDataViewsPromptKibanaServices, NoDataViewsPromptServices } from './services';
|
||||
export { NoDataViewsPrompt } from './no_data_views';
|
||||
export { NoDataViewsPrompt as NoDataViewsPromptComponent } from './no_data_views.component';
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { withSuspense } from '@kbn/shared-ux-utility';
|
||||
|
||||
export { NoDataViewsPromptKibanaProvider, NoDataViewsPromptProvider } from './services';
|
||||
export type { NoDataViewsPromptKibanaServices, NoDataViewsPromptServices } from './services';
|
||||
|
||||
/**
|
||||
* The Lazily-loaded `NoDataViewsPrompt` component. Consumers should use `React.Suspennse` or the
|
||||
* `withSuspense` HOC to load this component.
|
||||
*/
|
||||
export const NoDataViewsPromptLazy = React.lazy(() =>
|
||||
import('./no_data_views').then(({ NoDataViewsPrompt }) => ({
|
||||
default: NoDataViewsPrompt,
|
||||
}))
|
||||
);
|
||||
|
||||
/**
|
||||
* A `NoDataViewsPrompt` component that is wrapped by the `withSuspense` HOC. This component can
|
||||
* be used directly by consumers and will load the `NoDataViewsPromptLazy` component lazily with
|
||||
* a predefined fallback and error boundary.
|
||||
*/
|
||||
export const NoDataViewsPrompt = withSuspense(NoDataViewsPromptLazy);
|
||||
|
||||
/**
|
||||
* A pure `NoDataViewsPrompt` component, with no services hooks. Consumers should use `React.Suspennse` or the
|
||||
* `withSuspense` HOC to load this component.
|
||||
*/
|
||||
export const NoDataViewsPromptComponentLazy = React.lazy(() =>
|
||||
import('./no_data_views.component').then(({ NoDataViewsPrompt: Component }) => ({
|
||||
default: Component,
|
||||
}))
|
||||
);
|
||||
|
||||
/**
|
||||
* A pure `NoDataViewsPrompt` component, with no services hooks. The component is wrapped by the `withSuspense` HOC.
|
||||
* This component can be used directly by consumers and will load the `NoDataViewsComponentLazy` lazily with
|
||||
* a predefined fallback and error boundary.
|
||||
*/
|
||||
export const NoDataViewsPromptComponent = withSuspense(NoDataViewsPromptComponentLazy);
|
|
@ -9,11 +9,11 @@
|
|||
import React from 'react';
|
||||
import { css } from '@emotion/react';
|
||||
|
||||
import { EuiButton, EuiEmptyPrompt, EuiEmptyPromptProps, EuiPanel } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { EuiButton, EuiEmptyPrompt, EuiEmptyPromptProps } from '@elastic/eui';
|
||||
import { withSuspense } from '@kbn/shared-ux-utility';
|
||||
|
||||
import { DataViewIllustration } from './data_view_illustration';
|
||||
import { DocumentationLink } from './documentation_link';
|
||||
|
||||
export interface Props {
|
||||
|
@ -87,9 +87,20 @@ export const NoDataViewsPrompt = ({
|
|||
</p>
|
||||
);
|
||||
|
||||
const icon = <DataViewIllustration />;
|
||||
const footer = dataViewsDocLink ? <DocumentationLink href={dataViewsDocLink} /> : undefined;
|
||||
|
||||
// Load this illustration lazily
|
||||
const Illustration = withSuspense(
|
||||
React.lazy(() =>
|
||||
import('./data_view_illustration').then(({ DataViewIllustration }) => {
|
||||
return { default: DataViewIllustration };
|
||||
})
|
||||
),
|
||||
<EuiPanel color="subdued" style={{ width: 226, height: 206 }} />
|
||||
);
|
||||
|
||||
const icon = <Illustration />;
|
||||
|
||||
return (
|
||||
<EuiEmptyPrompt
|
||||
data-test-subj="noDataViewsPrompt"
|
||||
|
|
|
@ -57,6 +57,8 @@ export function DiscoverMainRoute() {
|
|||
const [indexPatternList, setIndexPatternList] = useState<Array<SavedObject<DataViewAttributes>>>(
|
||||
[]
|
||||
);
|
||||
const [hasESData, setHasESData] = useState(false);
|
||||
const [hasUserDataView, setHasUserDataView] = useState(false);
|
||||
const [showNoDataPage, setShowNoDataPage] = useState<boolean>(false);
|
||||
const { id } = useParams<DiscoverLandingParams>();
|
||||
|
||||
|
@ -69,23 +71,33 @@ export function DiscoverMainRoute() {
|
|||
const loadDefaultOrCurrentIndexPattern = useCallback(
|
||||
async (searchSource: ISearchSource) => {
|
||||
try {
|
||||
const hasUserDataView = await data.dataViews.hasData.hasUserDataView().catch(() => false);
|
||||
const hasEsData = await data.dataViews.hasData.hasESData().catch(() => false);
|
||||
if (!hasUserDataView || !hasEsData) {
|
||||
const hasUserDataViewValue = await data.dataViews.hasData
|
||||
.hasUserDataView()
|
||||
.catch(() => false);
|
||||
|
||||
const hasESDataValue = await data.dataViews.hasData.hasESData().catch(() => false);
|
||||
|
||||
setHasUserDataView(hasUserDataViewValue);
|
||||
setHasESData(hasESDataValue);
|
||||
|
||||
if (!hasUserDataViewValue || !hasESDataValue) {
|
||||
setShowNoDataPage(true);
|
||||
return;
|
||||
}
|
||||
|
||||
const defaultDataView = await data.dataViews.getDefaultDataView();
|
||||
|
||||
if (!defaultDataView) {
|
||||
setShowNoDataPage(true);
|
||||
return;
|
||||
}
|
||||
|
||||
const { appStateContainer } = getState({ history, uiSettings: config });
|
||||
const { index } = appStateContainer.getState();
|
||||
const ip = await loadIndexPattern(index || '', data.dataViews, config);
|
||||
|
||||
const ipList = ip.list as Array<SavedObject<DataViewAttributes>>;
|
||||
const indexPatternData = await resolveIndexPattern(ip, searchSource, toastNotifications);
|
||||
const indexPatternData = resolveIndexPattern(ip, searchSource, toastNotifications);
|
||||
|
||||
setIndexPatternList(ipList);
|
||||
|
||||
|
@ -189,9 +201,20 @@ export function DiscoverMainRoute() {
|
|||
if (showNoDataPage) {
|
||||
const analyticsServices = {
|
||||
coreStart: core,
|
||||
dataViews: data.dataViews,
|
||||
dataViews: {
|
||||
...data.dataViews,
|
||||
hasData: {
|
||||
...data.dataViews.hasData,
|
||||
|
||||
// We've already called this, so we can optimize the analytics services to
|
||||
// use the already-retrieved data to avoid a double-call.
|
||||
hasESData: () => Promise.resolve(hasESData),
|
||||
hasUserDataView: () => Promise.resolve(hasUserDataView),
|
||||
},
|
||||
},
|
||||
dataViewEditor,
|
||||
};
|
||||
|
||||
return (
|
||||
<AnalyticsNoDataPageKibanaProvider {...analyticsServices}>
|
||||
<AnalyticsNoDataPage onDataViewCreated={onDataViewCreated} />
|
||||
|
@ -204,7 +227,7 @@ export function DiscoverMainRoute() {
|
|||
}
|
||||
|
||||
if (!indexPattern || !savedSearch) {
|
||||
return <LoadingIndicator />;
|
||||
return <LoadingIndicator type="elastic" />;
|
||||
}
|
||||
|
||||
return <DiscoverMainAppMemoized indexPatternList={indexPatternList} savedSearch={savedSearch} />;
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Loading indicator renders correctly 1`] = `
|
||||
exports[`Loading indicator default renders correctly 1`] = `
|
||||
<LoadingIndicator>
|
||||
<EuiFlexGroup
|
||||
alignItems="center"
|
||||
gutterSize="none"
|
||||
justifyContent="spaceAround"
|
||||
>
|
||||
<div
|
||||
className="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--alignItemsCenter euiFlexGroup--justifyContentSpaceAround euiFlexGroup--directionRow euiFlexGroup--responsive"
|
||||
className="euiFlexGroup euiFlexGroup--alignItemsCenter euiFlexGroup--justifyContentSpaceAround euiFlexGroup--directionRow euiFlexGroup--responsive"
|
||||
>
|
||||
<EuiFlexItem
|
||||
grow={false}
|
||||
|
@ -28,3 +29,45 @@ exports[`Loading indicator renders correctly 1`] = `
|
|||
</EuiFlexGroup>
|
||||
</LoadingIndicator>
|
||||
`;
|
||||
|
||||
exports[`Loading indicator elastic renders correctly 1`] = `
|
||||
<LoadingIndicator
|
||||
type="elastic"
|
||||
>
|
||||
<EuiFlexGroup
|
||||
alignItems="center"
|
||||
gutterSize="none"
|
||||
justifyContent="spaceAround"
|
||||
>
|
||||
<div
|
||||
className="euiFlexGroup euiFlexGroup--alignItemsCenter euiFlexGroup--justifyContentSpaceAround euiFlexGroup--directionRow euiFlexGroup--responsive"
|
||||
>
|
||||
<EuiFlexItem
|
||||
grow={false}
|
||||
>
|
||||
<div
|
||||
className="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<EuiLoadingElastic
|
||||
size="xxl"
|
||||
>
|
||||
<span
|
||||
className="euiLoadingElastic euiLoadingElastic--xxLarge"
|
||||
>
|
||||
<EuiIcon
|
||||
size="xxl"
|
||||
type="logoElastic"
|
||||
>
|
||||
<span
|
||||
data-euiicon-type="logoElastic"
|
||||
size="xxl"
|
||||
/>
|
||||
</EuiIcon>
|
||||
</span>
|
||||
</EuiLoadingElastic>
|
||||
</div>
|
||||
</EuiFlexItem>
|
||||
</div>
|
||||
</EuiFlexGroup>
|
||||
</LoadingIndicator>
|
||||
`;
|
||||
|
|
|
@ -10,8 +10,12 @@ import React from 'react';
|
|||
import { mount } from 'enzyme';
|
||||
|
||||
describe('Loading indicator', () => {
|
||||
it('renders correctly', () => {
|
||||
it('default renders correctly', () => {
|
||||
const component = mount(<LoadingIndicator />);
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
it('elastic renders correctly', () => {
|
||||
const component = mount(<LoadingIndicator type="elastic" />);
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,14 +5,18 @@
|
|||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner } from '@elastic/eui';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner, EuiLoadingElastic } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
|
||||
export const LoadingIndicator = () => {
|
||||
interface Props {
|
||||
type?: 'spinner' | 'elastic';
|
||||
}
|
||||
|
||||
export const LoadingIndicator = ({ type = 'spinner' }: Props) => {
|
||||
return (
|
||||
<EuiFlexGroup justifyContent="spaceAround" alignItems="center">
|
||||
<EuiFlexGroup justifyContent="spaceAround" alignItems="center" gutterSize="none">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiLoadingSpinner size="l" />
|
||||
{type === 'spinner' ? <EuiLoadingSpinner size="l" /> : <EuiLoadingElastic size="xxl" />}
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
|
|
|
@ -18,7 +18,7 @@ exports[`it renders without crashing 1`] = `
|
|||
<EuiSpacer
|
||||
size="xxl"
|
||||
/>
|
||||
<ForwardRef
|
||||
<KibanaSolutionAvatar
|
||||
name="Elastic"
|
||||
size="xl"
|
||||
/>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue