[App Search] DataPanel & LoadingOverlay component tweaks (#94251)

* DataPanel: fix icons showing unaligned & w/ too much flex space

* LoadingOverlay: add new loading component w/ overlay

- should have an opacity'd overlay to hide content underneath
- specify z-index

* DataPanel: add flag to display a LoadingOverlay

- update CSS to contain LoadingOverlay
- add isLoading prop
This commit is contained in:
Constance 2021-03-10 08:40:27 -08:00 committed by GitHub
parent 804c862c8e
commit dcaa3f6464
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 64 additions and 10 deletions

View file

@ -1,4 +1,7 @@
.dataPanel {
position: relative;
overflow: hidden;
// TODO: This CSS can be removed once EUI supports tables in `subdued` panels
&--filled {
.euiTable {

View file

@ -11,6 +11,8 @@ import { shallow } from 'enzyme';
import { EuiIcon, EuiButton } from '@elastic/eui';
import { LoadingOverlay } from '../../../shared/loading';
import { DataPanel } from './data_panel';
describe('DataPanel', () => {
@ -80,6 +82,18 @@ describe('DataPanel', () => {
expect(wrapper.prop('className')).toEqual('dataPanel dataPanel--filled');
});
it('renders a loading overlay based on isLoading flag', () => {
const wrapper = shallow(<DataPanel title={<h1>Test</h1>} />);
expect(wrapper.prop('aria-busy')).toBeFalsy();
expect(wrapper.find(LoadingOverlay)).toHaveLength(0);
wrapper.setProps({ isLoading: true });
expect(wrapper.prop('aria-busy')).toBeTruthy();
expect(wrapper.find(LoadingOverlay)).toHaveLength(1);
});
it('passes class names', () => {
const wrapper = shallow(<DataPanel title={<h1>Test</h1>} className="testing" />);

View file

@ -19,6 +19,8 @@ import {
EuiTitle,
} from '@elastic/eui';
import { LoadingOverlay } from '../../../shared/loading';
import './data_panel.scss';
interface Props {
@ -27,6 +29,7 @@ interface Props {
iconType?: string;
action?: React.ReactNode;
filled?: boolean;
isLoading?: boolean;
className?: string;
}
@ -36,6 +39,7 @@ export const DataPanel: React.FC<Props> = ({
iconType,
action,
filled,
isLoading,
className,
children,
...props // e.g., data-test-subj
@ -45,29 +49,36 @@ export const DataPanel: React.FC<Props> = ({
});
return (
<EuiPanel {...props} color={filled ? 'subdued' : 'plain'} className={classes} hasShadow={false}>
<EuiPanel
{...props}
color={filled ? 'subdued' : 'plain'}
className={classes}
hasShadow={false}
aria-busy={isLoading}
>
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center" responsive={false}>
<EuiFlexItem>
<EuiFlexGroup>
<EuiFlexGroup gutterSize="s" alignItems="center" responsive={false}>
{iconType && (
<EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiIcon type={iconType} />
</EuiFlexItem>
)}
<EuiFlexItem>
<EuiTitle size="xs">{title}</EuiTitle>
{subtitle && (
<EuiText size="s" color="subdued">
<p>{subtitle}</p>
</EuiText>
)}
</EuiFlexItem>
</EuiFlexGroup>
{subtitle && (
<EuiText size="s" color="subdued">
<p>{subtitle}</p>
</EuiText>
)}
</EuiFlexItem>
{action && <EuiFlexItem grow={false}>{action}</EuiFlexItem>}
</EuiFlexGroup>
<EuiSpacer />
{children}
{isLoading && <LoadingOverlay />}
</EuiPanel>
);
};

View file

@ -5,4 +5,4 @@
* 2.0.
*/
export { Loading } from './loading';
export { Loading, LoadingOverlay } from './loading';

View file

@ -6,8 +6,19 @@
*/
.enterpriseSearchLoading {
z-index: $euiZLevel2;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%);
}
.enterpriseSearchLoadingOverlay {
z-index: $euiZLevel1;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba($euiColorEmptyShade, .75);
}

View file

@ -11,11 +11,20 @@ import { shallow } from 'enzyme';
import { EuiLoadingSpinner } from '@elastic/eui';
import { Loading } from './';
import { Loading, LoadingOverlay } from './';
describe('Loading', () => {
it('renders', () => {
const wrapper = shallow(<Loading />);
expect(wrapper.hasClass('enterpriseSearchLoading')).toBe(true);
expect(wrapper.find(EuiLoadingSpinner)).toHaveLength(1);
});
});
describe('LoadingOverlay', () => {
it('renders', () => {
const wrapper = shallow(<LoadingOverlay />);
expect(wrapper.hasClass('enterpriseSearchLoadingOverlay')).toBe(true);
expect(wrapper.find(Loading)).toHaveLength(1);
});
});

View file

@ -16,3 +16,9 @@ export const Loading: React.FC = () => (
<EuiLoadingSpinner size="xl" />
</div>
);
export const LoadingOverlay: React.FC = () => (
<div className="enterpriseSearchLoadingOverlay">
<Loading />
</div>
);