Skip to content

Commit

Permalink
[Serverless/Chrome] App menu bar fixes (#162002)
Browse files Browse the repository at this point in the history
## Summary

Closes #161889
Closes #162935

This PR gives the correct look and feel to the app menu bar.

1. The bar appears to the right of the side panel
2. The bar has fixed position below the fixed EuiHeader
3. Page content flows after the the bar

### Testing
1. Run `yarn es snapshot` in a terminal pane
2. Run `yarn serverless` in another pane
3. Log into the Kibana UI and check different forms of the menu bar
4. Use the dev-project switcher to test other solution projects
5. Test with a header banner:
    ```
    #!/bin/bash
    HOST=http://elastic:changeme@localhost:5601
    curl -X POST "$HOST/internal/kibana/settings" \
     -H 'kbn-xsrf: true' \
     -H 'X-Elastic-Internal-Origin: Kibana' \
     -H 'Content-Type: application/json' \
     -d '{
       "changes": {
         "banners:placement": "top",
"banners:textContent": "Prefix. **SIMPLE BANNER MESSAGE CONTENT**.
Suffix."
       }
     }'
    ```
    Set `banners:placement` to `null` to turn off the header banner.

**Known issue:** in some Observability project pages, the app menu bar
may appear as an empty div. This is explained in the [serverless project
layout
documentation](https://docs.elastic.dev/kibana-dev-docs/serverless-project-navigation#header-action-menu):
> **Note** The display of the toolbar container is conditional, based on
whether there is toolbar content to show. Make sure to pass undefined to
setHeaderActionMenu if there is no application content to show. In
classic layout, passing an empty span or div element suffices to "clear"
the toolbar, but in serverless projects it will cause a large empty
container to show below the header.

### Screenshots
_Will not be updated past a5222e428814c9d2211f4c14fe160dbea93f3e1b_

| |  |
|---|---| 
| **Project layout in Observability app** |
https://github.com/elastic/kibana/assets/908371/9fb8f57a-3de9-49e8-9d6d-d10fa83a3c83
|
| **Project layout in Observability app w/ header banner** |
https://github.com/elastic/kibana/assets/908371/19a0bf68-0df7-4f08-b987-125abe9e5680
|
| **Project layout in Security app** |
https://github.com/elastic/kibana/assets/908371/af1940fa-9d48-48a4-b675-0b3c8bcffc39
|
| **Project layout in Security app w/ header banner** |
https://github.com/elastic/kibana/assets/908371/d962952a-1d21-4bb3-8992-cafe4aed82a4
|

### Checklist

Delete any items that are not applicable to this PR.

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [x] Any UI touched in this PR is usable by keyboard only (learn more
about [keyboard accessibility](https://webaim.org/techniques/keyboard/))
- [x] Any UI touched in this PR does not create any new axe failures
(run axe in browser:
[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),
[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))
- [x] This renders correctly on smaller devices using a responsive
layout. (You can test this [in your
browser](https://www.browserstack.com/guide/responsive-testing-on-local-server))
- [x] This was checked for [cross-browser
compatibility](https://www.elastic.co/support/matrix#matrix_browsers)

---------

Co-authored-by: Cee Chen <[email protected]>
Co-authored-by: Kibana Machine <[email protected]>
  • Loading branch information
3 people authored Aug 11, 2023
1 parent 99db840 commit 2465550
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* 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 { useEuiTheme } from '@elastic/eui';
import { css } from '@emotion/react';
import { MountPoint } from '@kbn/core-mount-utils-browser';
import React from 'react';
import { HeaderActionMenu } from '../header/header_action_menu';

interface AppMenuBarProps {
isOpen: boolean;
headerActionMenuMounter: { mount: MountPoint<HTMLElement> | undefined };
}
export const AppMenuBar = ({ headerActionMenuMounter }: AppMenuBarProps) => {
const { euiTheme } = useEuiTheme();
return (
<div
className="header__actionMenu"
data-test-subj="kibanaProjectHeaderActionMenu"
css={css`
z-index: ${euiTheme.levels.header};
background: ${euiTheme.colors.emptyShade};
border-bottom: ${euiTheme.border.thin};
display: flex;
justify-content: end;
align-items: center;
padding: ${euiTheme.size.s};
margin-bottom: -${euiTheme.border.width.thin};
/* fixates the elements position in the viewport, removes the element from the flow of the page */
position: sticky;
/* position below the primary fixed EuiHeader in the viewport */
top: 48px;
`}
>
<HeaderActionMenu mounter={headerActionMenuMounter} />
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,13 @@ import React, { createRef, useCallback, useState } from 'react';
import useLocalStorage from 'react-use/lib/useLocalStorage';
import useObservable from 'react-use/lib/useObservable';
import { debounceTime, Observable, of } from 'rxjs';
import { HeaderActionMenu, useHeaderActionMenuMounter } from '../header/header_action_menu';
import { useHeaderActionMenuMounter } from '../header/header_action_menu';
import { HeaderBreadcrumbs } from '../header/header_breadcrumbs';
import { HeaderHelpMenu } from '../header/header_help_menu';
import { HeaderNavControls } from '../header/header_nav_controls';
import { HeaderTopBanner } from '../header/header_top_banner';
import { ScreenReaderRouteAnnouncements, SkipToMainContent } from '../header/screen_reader_a11y';
import { AppMenuBar } from './app_menu';
import { ProjectNavigation } from './navigation';

const headerCss = {
Expand Down Expand Up @@ -270,23 +271,12 @@ export const ProjectHeader = ({
</EuiHeaderSectionItem>
</EuiHeaderSection>
</EuiHeader>

<EuiHeader
position="fixed"
className="header__secondBar"
data-test-subj="kibanaProjectHeaderActionMenu"
>
<EuiHeaderSection />
{headerActionMenuMounter.mount && (
<EuiHeaderSection side="right">
<EuiHeaderSectionItem>
<HeaderActionMenu mounter={headerActionMenuMounter} />
</EuiHeaderSectionItem>
</EuiHeaderSection>
)}
</EuiHeader>
</div>
</header>

{headerActionMenuMounter.mount && (
<AppMenuBar isOpen={isOpen ?? false} headerActionMenuMounter={headerActionMenuMounter} />
)}
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export const ProjectNavigation: React.FC<ProjectNavigationProps> = ({

return (
<EuiCollapsibleNav
className="projectLayoutSideNav"
css={collabsibleNavCSS}
isOpen={isVisible}
showButtonIfDocked={true}
Expand Down
21 changes: 20 additions & 1 deletion src/core/public/styles/chrome/_banner.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
width: 100%;
}

// overriding `top` positioning of the chrome headers when the top banner is present.
// overriding `top` positioning of the chrome headers
.kbnBody--hasHeaderBanner .header__bars {
.header__firstBar {
top: $kbnHeaderBannerHeight;
Expand All @@ -21,3 +21,22 @@
top: $kbnHeaderBannerHeight + $euiHeaderHeightCompensation;
}
}

// overriding padding on the body element added by EUI
.kbnBody.kbnBody--hasHeaderBanner.kbnBody--projectLayout.euiBody--headerIsFixed {
padding-top: $kbnHeaderBannerHeight + $euiHeaderHeightCompensation;

// overriding `top` positioning of the project side nav, and flyouts
// overriding `top` positioning of the project app menu toolbar
&.euiBody--headerIsFixed .euiCollapsibleNav,
&.euiBody--headerIsFixed:not(.euiDataGrid__restrictBody) .euiFlyout,
.header__actionMenu {
top: $kbnHeaderBannerHeight + $euiHeaderHeightCompensation;
}

// overriding `height` calculation of the project side nav, and flyouts
&.euiBody--headerIsFixed .euiCollapsibleNav,
&.euiBody--headerIsFixed:not(.euiDataGrid__restrictBody) .euiFlyout {
height: calc(100% - #{$kbnHeaderBannerHeight + $euiHeaderHeightCompensation});
}
}
3 changes: 3 additions & 0 deletions src/core/public/styles/rendering/_base.scss
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@
&.kbnBody--chromeHidden {
@include kbnAffordForHeader(0);
}
&.kbnBody--projectLayout {
@include kbnAffordForHeader($euiHeaderHeightCompensation);
}
&.kbnBody--chromeHidden.kbnBody--hasHeaderBanner {
@include kbnAffordForHeader($kbnHeaderBannerHeight);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,17 @@ const PageOverlayGlobalStyles = createGlobalStyle<{ theme: EuiTheme }>`
body.${PAGE_OVERLAY_DOCUMENT_BODY_FULLSCREEN_CLASSNAME} {
${FULL_SCREEN_CONTENT_OVERRIDES_CSS_STYLESHEET}
}
//-------------------------------------------------------------------------------------------
// Style overrides for when Page Overlay is displayed in serverless project
//-------------------------------------------------------------------------------------------
// With serverless, there is 1 less header displayed, thus the display of the page overlay
// need to be adjusted slightly so that it still display below the header
//-------------------------------------------------------------------------------------------
body.kbnBody.kbnBody--projectLayout:not(.${PAGE_OVERLAY_DOCUMENT_BODY_FULLSCREEN_CLASSNAME}) .${PAGE_OVERLAY_CSS_CLASSNAME} {
top: ${({ theme: { eui } }) => eui.euiHeaderHeightCompensation};
height: calc(100% - (${({ theme: { eui } }) => eui.euiHeaderHeightCompensation}));
}
`;

const setDocumentBodyOverlayIsVisible = () => {
Expand Down

0 comments on commit 2465550

Please sign in to comment.