Fix AppContainer layout (#101793) (#101939)

* Fixing app_container
* Use EUI mixin  `euiHeaderAffordForFixed()` to maintain parity
* Adding `aria-busy` when `showSpinner`
* i18n for the loading aria-label
This commit is contained in:
Caroline Horn 2021-06-10 16:27:58 -04:00 committed by GitHub
parent 7a3f111059
commit 2acaa2375a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 25 additions and 44 deletions

View file

@ -96,7 +96,7 @@ describe('AppRouter', () => {
expect(app1.mounter.mount).toHaveBeenCalled();
expect(dom?.html()).toMatchInlineSnapshot(`
"<div class=\\"appContainer__loading\\"><span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span></div><div><div>
"<span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge appContainer__loading\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span><div class=\\"kbnAppWrapper\\" aria-busy=\\"false\\"><div>
basename: /app/app1
html: <span>App 1</span>
</div></div>"
@ -108,7 +108,7 @@ describe('AppRouter', () => {
expect(app1Unmount).toHaveBeenCalled();
expect(app2.mounter.mount).toHaveBeenCalled();
expect(dom?.html()).toMatchInlineSnapshot(`
"<div class=\\"appContainer__loading\\"><span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span></div><div><div>
"<span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge appContainer__loading\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span><div class=\\"kbnAppWrapper\\" aria-busy=\\"false\\"><div>
basename: /app/app2
html: <div>App 2</div>
</div></div>"
@ -122,7 +122,7 @@ describe('AppRouter', () => {
expect(standardApp.mounter.mount).toHaveBeenCalled();
expect(dom?.html()).toMatchInlineSnapshot(`
"<div class=\\"appContainer__loading\\"><span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span></div><div><div>
"<span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge appContainer__loading\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span><div class=\\"kbnAppWrapper\\" aria-busy=\\"false\\"><div>
basename: /app/app1
html: <span>App 1</span>
</div></div>"
@ -134,7 +134,7 @@ describe('AppRouter', () => {
expect(standardAppUnmount).toHaveBeenCalled();
expect(chromelessApp.mounter.mount).toHaveBeenCalled();
expect(dom?.html()).toMatchInlineSnapshot(`
"<div class=\\"appContainer__loading\\"><span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span></div><div><div>
"<span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge appContainer__loading\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span><div class=\\"kbnAppWrapper\\" aria-busy=\\"false\\"><div>
basename: /chromeless-a/path
html: <div>Chromeless A</div>
</div></div>"
@ -146,7 +146,7 @@ describe('AppRouter', () => {
expect(chromelessAppUnmount).toHaveBeenCalled();
expect(standardApp.mounter.mount).toHaveBeenCalledTimes(2);
expect(dom?.html()).toMatchInlineSnapshot(`
"<div class=\\"appContainer__loading\\"><span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span></div><div><div>
"<span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge appContainer__loading\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span><div class=\\"kbnAppWrapper\\" aria-busy=\\"false\\"><div>
basename: /app/app1
html: <span>App 1</span>
</div></div>"
@ -160,7 +160,7 @@ describe('AppRouter', () => {
expect(chromelessAppA.mounter.mount).toHaveBeenCalled();
expect(dom?.html()).toMatchInlineSnapshot(`
"<div class=\\"appContainer__loading\\"><span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span></div><div><div>
"<span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge appContainer__loading\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span><div class=\\"kbnAppWrapper\\" aria-busy=\\"false\\"><div>
basename: /chromeless-a/path
html: <div>Chromeless A</div>
</div></div>"
@ -172,7 +172,7 @@ describe('AppRouter', () => {
expect(chromelessAppAUnmount).toHaveBeenCalled();
expect(chromelessAppB.mounter.mount).toHaveBeenCalled();
expect(dom?.html()).toMatchInlineSnapshot(`
"<div class=\\"appContainer__loading\\"><span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span></div><div><div>
"<span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge appContainer__loading\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span><div class=\\"kbnAppWrapper\\" aria-busy=\\"false\\"><div>
basename: /chromeless-b/path
html: <div>Chromeless B</div>
</div></div>"
@ -184,7 +184,7 @@ describe('AppRouter', () => {
expect(chromelessAppBUnmount).toHaveBeenCalled();
expect(chromelessAppA.mounter.mount).toHaveBeenCalledTimes(2);
expect(dom?.html()).toMatchInlineSnapshot(`
"<div class=\\"appContainer__loading\\"><span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span></div><div><div>
"<span class=\\"euiLoadingElastic euiLoadingElastic--xxLarge appContainer__loading\\" aria-label=\\"Loading application\\"><span data-euiicon-type=\\"logoElastic\\"></span></span><div class=\\"kbnAppWrapper\\" aria-busy=\\"false\\"><div>
basename: /chromeless-a/path
html: <div>Chromeless A</div>
</div></div>"

View file

@ -1,5 +1,5 @@
.appContainer__loading {
position: fixed;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);

View file

@ -5,6 +5,7 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import './app_container.scss';
import React, {
Fragment,
@ -16,11 +17,12 @@ import React, {
} from 'react';
import { EuiLoadingElastic } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import type { MountPoint } from '../../types';
import { AppLeaveHandler, AppStatus, AppUnmount, Mounter } from '../types';
import { AppNotFound } from './app_not_found_screen';
import { ScopedHistory } from '../scoped_history';
import './app_container.scss';
import { APP_WRAPPER_CLASS } from '../../../utils';
interface Props {
/** Path application is mounted on without the global basePath */
@ -107,12 +109,16 @@ export const AppContainer: FunctionComponent<Props> = ({
return (
<Fragment>
{appNotFound && <AppNotFound />}
{showSpinner && (
<div className="appContainer__loading">
<EuiLoadingElastic aria-label="Loading application" size="xxl" />
</div>
{showSpinner && !appNotFound && (
<EuiLoadingElastic
className="appContainer__loading"
aria-label={i18n.translate('core.application.appContainer.loadingAriaLabel', {
defaultMessage: 'Loading application',
})}
size="xxl"
/>
)}
<div key={appId} ref={elementRef} />
<div className={APP_WRAPPER_CLASS} key={appId} ref={elementRef} aria-busy={showSpinner} />
</Fragment>
);
};

View file

@ -35,27 +35,12 @@
position: relative; // This is temporary for apps that relied on this being present on `.application`
}
// TODO: This is problematic because it doesn't stay in line with EUI:
// adapted from euiHeaderAffordForFixed as we need to handle the top banner
@mixin kbnAffordForHeader($headerHeight) {
padding-top: $headerHeight;
@include euiHeaderAffordForFixed($headerHeight);
#app-fixed-viewport {
top: $headerHeight;
}
.euiFlyout,
.euiCollapsibleNav {
top: $headerHeight;
height: calc(100% - #{$headerHeight});
}
@include euiBreakpoint('m', 'l', 'xl') {
.euiPageSideBar--sticky {
max-height: calc(100vh - #{$headerHeight});
top: #{$headerHeight};
}
}
}
.kbnBody {

View file

@ -52,7 +52,6 @@ const InlineStyles: FC<{ darkMode: boolean }> = ({ darkMode }) => {
.kbnWelcomeView {
line-height: 1.5;
background-color: ${darkMode ? '#1D1E24' : '#FFF'};
height: 100%;
display: -webkit-box;
display: -webkit-flex;

View file

@ -207,10 +207,7 @@ export class SecurityPageObject extends FtrService {
}
if (expectedResult === 'chrome') {
await this.find.byCssSelector(
'[data-test-subj="kibanaChrome"] .kbnAppWrapper:not(.kbnAppWrapper--hiddenChrome)',
20000
);
await this.find.byCssSelector('[data-test-subj="userMenuButton"]', 20000);
this.log.debug(`Finished login process currentUrl = ${await this.browser.getCurrentUrl()}`);
}
}

View file

@ -43,10 +43,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
deployment.getHostPort() + '/app/management/security/users#some=hash-value'
);
await find.byCssSelector(
'[data-test-subj="kibanaChrome"] .kbnAppWrapper:not(.kbnAppWrapper--hiddenChrome)',
20000
);
await find.byCssSelector('[data-test-subj="userMenuButton"]', 20000);
// We need to make sure that both path and hash are respected.
const currentURL = parse(await browser.getCurrentUrl());

View file

@ -43,10 +43,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
deployment.getHostPort() + '/app/management/security/users#some=hash-value'
);
await find.byCssSelector(
'[data-test-subj="kibanaChrome"] .kbnAppWrapper:not(.kbnAppWrapper--hiddenChrome)',
20000
);
await find.byCssSelector('[data-test-subj="userMenuButton"]', 20000);
// We need to make sure that both path and hash are respected.
const currentURL = parse(await browser.getCurrentUrl());