mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 01:13:23 -04:00
# Backport This will backport the following commits from `main` to `8.x`: - [[SharedUX] Replace Sass with Emotion, Round 1 (#199885)](https://github.com/elastic/kibana/pull/199885) <!--- Backport version: 8.9.8 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Tim Sullivan","email":"tsullivan@users.noreply.github.com"},"sourceCommit":{"committedDate":"2024-12-04T17:39:22Z","message":"[SharedUX] Replace Sass with Emotion, Round 1 (#199885)\n\n## Summary\r\n\r\nPart of https://github.com/elastic/kibana-team/issues/1082\r\n\r\nSelects certain Sass files to replace with styles declared with Emotion.\r\nThis PR does not include any changes that would be noticeable by\r\nend-users. It changes the internals to use a different technology for\r\nstyling components.\r\n\r\n~~Some `className` attributes have been kept, because they are\r\nreferenced in JS and tests.~~ Update: all classNames that are no longer\r\nneeded for styling purposes have been removed.\r\n* If the className was needed for tests, it has been replaced with a\r\ntest-subj.\r\n* If the className was used as a selector in production code, it has\r\nbeen replaced with alternative JS.\r\n\r\n## References\r\n1. https://emotion.sh/docs/globals\r\n2. https://emotion.sh/docs/best-practices\r\n3.\r\nhttps://github.com/elastic/eui/discussions/6828#discussioncomment-10825360\r\n\r\n---------\r\n\r\nCo-authored-by: Jatin Kathuria <jatin.kathuria@elastic.co>","sha":"d86896bac0bbc5ed48b43e695e0a73c55b21450c","branchLabelMapping":{"^v9.0.0$":"main","^v8.18.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","backport missing","v9.0.0","backport:prev-minor"],"number":199885,"url":"https://github.com/elastic/kibana/pull/199885","mergeCommit":{"message":"[SharedUX] Replace Sass with Emotion, Round 1 (#199885)\n\n## Summary\r\n\r\nPart of https://github.com/elastic/kibana-team/issues/1082\r\n\r\nSelects certain Sass files to replace with styles declared with Emotion.\r\nThis PR does not include any changes that would be noticeable by\r\nend-users. It changes the internals to use a different technology for\r\nstyling components.\r\n\r\n~~Some `className` attributes have been kept, because they are\r\nreferenced in JS and tests.~~ Update: all classNames that are no longer\r\nneeded for styling purposes have been removed.\r\n* If the className was needed for tests, it has been replaced with a\r\ntest-subj.\r\n* If the className was used as a selector in production code, it has\r\nbeen replaced with alternative JS.\r\n\r\n## References\r\n1. https://emotion.sh/docs/globals\r\n2. https://emotion.sh/docs/best-practices\r\n3.\r\nhttps://github.com/elastic/eui/discussions/6828#discussioncomment-10825360\r\n\r\n---------\r\n\r\nCo-authored-by: Jatin Kathuria <jatin.kathuria@elastic.co>","sha":"d86896bac0bbc5ed48b43e695e0a73c55b21450c"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","labelRegex":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/199885","number":199885,"mergeCommit":{"message":"[SharedUX] Replace Sass with Emotion, Round 1 (#199885)\n\n## Summary\r\n\r\nPart of https://github.com/elastic/kibana-team/issues/1082\r\n\r\nSelects certain Sass files to replace with styles declared with Emotion.\r\nThis PR does not include any changes that would be noticeable by\r\nend-users. It changes the internals to use a different technology for\r\nstyling components.\r\n\r\n~~Some `className` attributes have been kept, because they are\r\nreferenced in JS and tests.~~ Update: all classNames that are no longer\r\nneeded for styling purposes have been removed.\r\n* If the className was needed for tests, it has been replaced with a\r\ntest-subj.\r\n* If the className was used as a selector in production code, it has\r\nbeen replaced with alternative JS.\r\n\r\n## References\r\n1. https://emotion.sh/docs/globals\r\n2. https://emotion.sh/docs/best-practices\r\n3.\r\nhttps://github.com/elastic/eui/discussions/6828#discussioncomment-10825360\r\n\r\n---------\r\n\r\nCo-authored-by: Jatin Kathuria <jatin.kathuria@elastic.co>","sha":"d86896bac0bbc5ed48b43e695e0a73c55b21450c"}}]}] BACKPORT-->
This commit is contained in:
parent
1d3bed7799
commit
d90731a1a3
14 changed files with 222 additions and 130 deletions
|
@ -1,31 +1,62 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`kbnLoadingIndicator is hidden by default 1`] = `
|
||||
<EuiIcon
|
||||
aria-label="Elastic Logo"
|
||||
className="chrHeaderLogo__cluster"
|
||||
data-test-subj="globalLoadingIndicator-hidden"
|
||||
size="l"
|
||||
type="logoElastic"
|
||||
/>
|
||||
<Fragment>
|
||||
<EmotionGlobal
|
||||
styles={
|
||||
Object {
|
||||
".euiHeaderSectionItem .euiButtonEmpty__text": Object {
|
||||
"display": "flex",
|
||||
},
|
||||
}
|
||||
}
|
||||
/>
|
||||
<EuiIcon
|
||||
aria-label="Elastic Logo"
|
||||
data-test-subj="globalLoadingIndicator-hidden"
|
||||
size="l"
|
||||
type="logoElastic"
|
||||
/>
|
||||
</Fragment>
|
||||
`;
|
||||
|
||||
exports[`kbnLoadingIndicator is visible when loadingCount is > 0 1`] = `
|
||||
<EuiIcon
|
||||
aria-label="Elastic Logo"
|
||||
className="chrHeaderLogo__cluster"
|
||||
data-test-subj="globalLoadingIndicator-hidden"
|
||||
size="l"
|
||||
type="logoElastic"
|
||||
/>
|
||||
<Fragment>
|
||||
<EmotionGlobal
|
||||
styles={
|
||||
Object {
|
||||
".euiHeaderSectionItem .euiButtonEmpty__text": Object {
|
||||
"display": "flex",
|
||||
},
|
||||
}
|
||||
}
|
||||
/>
|
||||
<EuiIcon
|
||||
aria-label="Elastic Logo"
|
||||
data-test-subj="globalLoadingIndicator-hidden"
|
||||
size="l"
|
||||
type="logoElastic"
|
||||
/>
|
||||
</Fragment>
|
||||
`;
|
||||
|
||||
exports[`kbnLoadingIndicator shows logo image when customLogo is set 1`] = `
|
||||
<EuiImage
|
||||
alt="logo"
|
||||
aria-label="User logo"
|
||||
data-test-subj="globalLoadingIndicator-hidden"
|
||||
size={24}
|
||||
src="customLogo"
|
||||
/>
|
||||
<Fragment>
|
||||
<EmotionGlobal
|
||||
styles={
|
||||
Object {
|
||||
".euiHeaderSectionItem .euiButtonEmpty__text": Object {
|
||||
"display": "flex",
|
||||
},
|
||||
}
|
||||
}
|
||||
/>
|
||||
<EuiImage
|
||||
alt="logo"
|
||||
aria-label="User logo"
|
||||
data-test-subj="globalLoadingIndicator-hidden"
|
||||
size={24}
|
||||
src="customLogo"
|
||||
/>
|
||||
</Fragment>
|
||||
`;
|
||||
|
|
|
@ -168,7 +168,7 @@ Array [
|
|||
>
|
||||
<ul
|
||||
aria-label="Recently viewed links"
|
||||
class="euiListGroup kbnCollapsibleNav__recentsListGroup emotion-euiListGroup-none"
|
||||
class="euiListGroup emotion-EuiListGroup"
|
||||
style="max-inline-size: none;"
|
||||
>
|
||||
<li
|
||||
|
@ -218,10 +218,10 @@ Array [
|
|||
class="euiHorizontalRule emotion-euiHorizontalRule-full"
|
||||
/>
|
||||
<div
|
||||
class="euiFlexItem kbnCollapsibleNav__solutions emotion-euiFlexItem-grow-1"
|
||||
class="euiFlexItem emotion-euiFlexItem-grow-1"
|
||||
>
|
||||
<div
|
||||
class="euiAccordion euiAccordion-isOpen euiCollapsibleNavGroup emotion-euiAccordion-euiCollapsibleNavGroup-isCollapsible-none"
|
||||
class="euiAccordion euiAccordion-isOpen euiCollapsibleNavGroup emotion-euiAccordion-EuiCollapsibleNavGroup"
|
||||
data-test-subj="collapsibleNavGroup-kibana"
|
||||
>
|
||||
<div
|
||||
|
@ -230,7 +230,7 @@ Array [
|
|||
<button
|
||||
aria-controls="generated-id"
|
||||
aria-expanded="true"
|
||||
class="euiAccordion__button kbnCollapsibleNav__solutionGroupButton emotion-euiAccordion__button"
|
||||
class="euiAccordion__button euiCollapsibleNavGroup__heading emotion-euiAccordion__button"
|
||||
id="generated-id"
|
||||
type="button"
|
||||
>
|
||||
|
@ -351,7 +351,7 @@ Array [
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="euiAccordion euiAccordion-isOpen euiCollapsibleNavGroup emotion-euiAccordion-euiCollapsibleNavGroup-isCollapsible-none"
|
||||
class="euiAccordion euiAccordion-isOpen euiCollapsibleNavGroup emotion-euiAccordion-EuiCollapsibleNavGroup"
|
||||
data-test-subj="collapsibleNavGroup-observability"
|
||||
>
|
||||
<div
|
||||
|
@ -360,7 +360,7 @@ Array [
|
|||
<button
|
||||
aria-controls="generated-id"
|
||||
aria-expanded="true"
|
||||
class="euiAccordion__button kbnCollapsibleNav__solutionGroupButton emotion-euiAccordion__button"
|
||||
class="euiAccordion__button euiCollapsibleNavGroup__heading emotion-euiAccordion__button"
|
||||
id="generated-id"
|
||||
type="button"
|
||||
>
|
||||
|
@ -464,7 +464,7 @@ Array [
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="euiAccordion euiAccordion-isOpen euiCollapsibleNavGroup emotion-euiAccordion-euiCollapsibleNavGroup-isCollapsible-none"
|
||||
class="euiAccordion euiAccordion-isOpen euiCollapsibleNavGroup emotion-euiAccordion-EuiCollapsibleNavGroup"
|
||||
data-test-subj="collapsibleNavGroup-securitySolution"
|
||||
>
|
||||
<div
|
||||
|
@ -473,7 +473,7 @@ Array [
|
|||
<button
|
||||
aria-controls="generated-id"
|
||||
aria-expanded="true"
|
||||
class="euiAccordion__button kbnCollapsibleNav__solutionGroupButton emotion-euiAccordion__button"
|
||||
class="euiAccordion__button euiCollapsibleNavGroup__heading emotion-euiAccordion__button"
|
||||
id="generated-id"
|
||||
type="button"
|
||||
>
|
||||
|
@ -560,7 +560,7 @@ Array [
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="euiAccordion euiAccordion-isOpen euiCollapsibleNavGroup emotion-euiAccordion-euiCollapsibleNavGroup-isCollapsible-none"
|
||||
class="euiAccordion euiAccordion-isOpen euiCollapsibleNavGroup emotion-euiAccordion-EuiCollapsibleNavGroup"
|
||||
data-test-subj="collapsibleNavGroup-management"
|
||||
>
|
||||
<div
|
||||
|
@ -569,7 +569,7 @@ Array [
|
|||
<button
|
||||
aria-controls="generated-id"
|
||||
aria-expanded="true"
|
||||
class="euiAccordion__button kbnCollapsibleNav__solutionGroupButton emotion-euiAccordion__button"
|
||||
class="euiAccordion__button euiCollapsibleNavGroup__heading emotion-euiAccordion__button"
|
||||
id="generated-id"
|
||||
type="button"
|
||||
>
|
||||
|
@ -858,7 +858,15 @@ exports[`CollapsibleNav renders the default nav 1`] = `
|
|||
<EuiCollapsibleNav
|
||||
aria-label="Primary"
|
||||
button={<button />}
|
||||
className="kbnCollapsibleNav"
|
||||
css={
|
||||
Object {
|
||||
"map": undefined,
|
||||
"name": "1pvcuvk",
|
||||
"next": undefined,
|
||||
"styles": "@media (max-height: 240px){overflow-y:auto;}",
|
||||
"toString": [Function],
|
||||
}
|
||||
}
|
||||
data-test-subj="collapsibleNav"
|
||||
id="collapsibe-nav"
|
||||
isOpen={false}
|
||||
|
@ -1045,7 +1053,15 @@ exports[`CollapsibleNav renders the default nav 2`] = `
|
|||
<EuiCollapsibleNav
|
||||
aria-label="Primary"
|
||||
button={<button />}
|
||||
className="kbnCollapsibleNav"
|
||||
css={
|
||||
Object {
|
||||
"map": undefined,
|
||||
"name": "1pvcuvk",
|
||||
"next": undefined,
|
||||
"styles": "@media (max-height: 240px){overflow-y:auto;}",
|
||||
"toString": [Function],
|
||||
}
|
||||
}
|
||||
data-test-subj="collapsibleNav"
|
||||
id="collapsibe-nav"
|
||||
isOpen={false}
|
||||
|
|
|
@ -56,12 +56,11 @@ Array [
|
|||
>
|
||||
<a
|
||||
aria-label="Elastic home"
|
||||
class="chrHeaderLogo"
|
||||
css="You have tried to stringify object returned from \`css\` function. It isn't supposed to be used directly (e.g. as value of the \`className\` prop), but rather handed to emotion so it can handle it (e.g. as value of \`css\` prop)."
|
||||
data-test-subj="logo"
|
||||
href="/"
|
||||
>
|
||||
<span
|
||||
class="chrHeaderLogo__cluster"
|
||||
data-euiicon-type="logoElastic"
|
||||
data-test-subj="globalLoadingIndicator-hidden"
|
||||
>
|
||||
|
@ -70,7 +69,8 @@ Array [
|
|||
<svg
|
||||
aria-hidden="true"
|
||||
aria-labelledby="elasticMark"
|
||||
class="chrHeaderLogo__mark"
|
||||
css="You have tried to stringify object returned from \`css\` function. It isn't supposed to be used directly (e.g. as value of the \`className\` prop), but rather handed to emotion so it can handle it (e.g. as value of \`css\` prop)."
|
||||
data-test-subj="logoMark"
|
||||
fill="none"
|
||||
height="19"
|
||||
width="64"
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
$screenHeightBreakpoint: $euiSize * 15;
|
||||
|
||||
.kbnCollapsibleNav {
|
||||
@media (max-height: $screenHeightBreakpoint) {
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.kbnCollapsibleNav__recentsListGroup {
|
||||
max-height: $euiSize * 10;
|
||||
margin-right: -$euiSizeS;
|
||||
@include euiYScroll;
|
||||
}
|
||||
|
||||
.kbnCollapsibleNav__solutions {
|
||||
@include euiYScroll;
|
||||
|
||||
/**
|
||||
* Allows the solutions nav group to be viewed on
|
||||
* very small screen sizes and when the browser Zoom is high
|
||||
*/
|
||||
@media (max-height: $screenHeightBreakpoint) {
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Increase the hit area of the link (anchor)
|
||||
* 2. Only show the text underline when hovering on the text/anchor portion
|
||||
*/
|
||||
|
||||
.kbnCollapsibleNav__solutionGroupButton {
|
||||
display: block; /* 1 */
|
||||
|
||||
&:hover {
|
||||
text-decoration: none; /* 2 */
|
||||
}
|
||||
}
|
||||
|
||||
.kbnCollapsibleNav__solutionGroupLink {
|
||||
display: block; /* 1 */
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline; /* 2 */
|
||||
}
|
||||
}
|
|
@ -7,7 +7,6 @@
|
|||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import './collapsible_nav.scss';
|
||||
import {
|
||||
EuiThemeProvider,
|
||||
EuiCollapsibleNav,
|
||||
|
@ -18,6 +17,7 @@ import {
|
|||
EuiListGroupItem,
|
||||
EuiCollapsibleNavProps,
|
||||
EuiButton,
|
||||
useEuiTheme,
|
||||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { groupBy, sortBy } from 'lodash';
|
||||
|
@ -36,6 +36,7 @@ import {
|
|||
createEuiButtonItem,
|
||||
createOverviewLink,
|
||||
} from './nav_link';
|
||||
import { getCollapsibleNavStyles } from './get_collapsible_nav_styles';
|
||||
|
||||
function getAllCategories(allCategorizedLinks: Record<string, ChromeNavLink[]>) {
|
||||
const allCategories = {} as Record<string, AppCategory | undefined>;
|
||||
|
@ -149,6 +150,7 @@ export function CollapsibleNav({
|
|||
...(needsIcon && { basePath }),
|
||||
});
|
||||
};
|
||||
const styles = getCollapsibleNavStyles(useEuiTheme());
|
||||
|
||||
return (
|
||||
<EuiCollapsibleNav
|
||||
|
@ -162,7 +164,7 @@ export function CollapsibleNav({
|
|||
button={button}
|
||||
ownFocus={false}
|
||||
size={248}
|
||||
className="kbnCollapsibleNav"
|
||||
css={styles.navCss}
|
||||
>
|
||||
{customNavLink && (
|
||||
<>
|
||||
|
@ -275,14 +277,14 @@ export function CollapsibleNav({
|
|||
color="subdued"
|
||||
gutterSize="none"
|
||||
size="s"
|
||||
className="kbnCollapsibleNav__recentsListGroup"
|
||||
css={styles.navRecentsListGroupCss}
|
||||
/>
|
||||
</EuiCollapsibleNavGroup>
|
||||
)}
|
||||
|
||||
<EuiHorizontalRule margin="none" />
|
||||
|
||||
<EuiFlexItem className="kbnCollapsibleNav__solutions">
|
||||
<EuiFlexItem css={styles.navSolutions}>
|
||||
{/* Kibana, Observability, Security, and Management sections */}
|
||||
{orderedCategories.map((categoryName) => {
|
||||
const category = categoryDictionary[categoryName]!;
|
||||
|
@ -294,11 +296,12 @@ export function CollapsibleNav({
|
|||
iconType={category.euiIconType}
|
||||
iconSize="m"
|
||||
buttonElement={overviewLink ? 'div' : 'button'}
|
||||
buttonClassName="kbnCollapsibleNav__solutionGroupButton"
|
||||
css={styles.navSolutionGroupButton}
|
||||
title={
|
||||
overviewLink ? (
|
||||
<a
|
||||
className="eui-textInheritColor kbnCollapsibleNav__solutionGroupLink"
|
||||
className="eui-textInheritColor"
|
||||
css={styles.navSolutionGroupLink}
|
||||
{...createOverviewLink({
|
||||
link: overviewLink,
|
||||
navigateToUrl,
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public
|
||||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import { UseEuiTheme, euiYScroll, mathWithUnits } from '@elastic/eui';
|
||||
import { css } from '@emotion/react';
|
||||
|
||||
export const getCollapsibleNavStyles = (euiThemeContext: UseEuiTheme) => {
|
||||
const { euiTheme } = euiThemeContext;
|
||||
const screenHeightBreakpoint = mathWithUnits(euiTheme.size.base, (x) => x * 15);
|
||||
const _euiYScroll = euiYScroll(euiThemeContext);
|
||||
|
||||
const navCss = css({
|
||||
[`@media (max-height: ${screenHeightBreakpoint})`]: {
|
||||
overflowY: 'auto',
|
||||
},
|
||||
});
|
||||
|
||||
const navRecentsListGroupCss = [
|
||||
css({
|
||||
maxHeight: `calc(${euiTheme.size.base} * 10)`,
|
||||
marginRight: `-${euiTheme.size.s}`,
|
||||
}),
|
||||
_euiYScroll,
|
||||
];
|
||||
|
||||
const navSolutions = [
|
||||
_euiYScroll,
|
||||
css({
|
||||
/**
|
||||
* Allows the solutions nav group to be viewed on
|
||||
* very small screen sizes and when the browser Zoom is high
|
||||
*/
|
||||
[`@media (max-height: ${screenHeightBreakpoint})`]: {
|
||||
flex: '1 0 auto',
|
||||
},
|
||||
}),
|
||||
];
|
||||
|
||||
/**
|
||||
* 1. Increase the hit area of the link (anchor)
|
||||
* 2. Only show the text underline when hovering on the text/anchor portion
|
||||
*/
|
||||
const navSolutionGroupButton = css({
|
||||
display: 'block' /* 1 */,
|
||||
|
||||
'&:hover': {
|
||||
textDecoration: 'none' /* 2 */,
|
||||
},
|
||||
});
|
||||
|
||||
const navSolutionGroupLink = css({
|
||||
display: 'block' /* 1 */,
|
||||
|
||||
'&:hover': {
|
||||
textDecoration: 'underline' /* 2 */,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
navCss,
|
||||
navRecentsListGroupCss,
|
||||
navSolutions,
|
||||
navSolutionGroupButton,
|
||||
navSolutionGroupLink,
|
||||
};
|
||||
};
|
|
@ -1,11 +0,0 @@
|
|||
.chrHeaderLogo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: $euiSizeXXL;
|
||||
padding-inline: $euiSizeS;
|
||||
}
|
||||
|
||||
.chrHeaderLogo__mark {
|
||||
margin-left: $euiSizeS;
|
||||
fill: $euiColorGhost;
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import './header_logo.scss';
|
||||
import { css } from '@emotion/react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React from 'react';
|
||||
import useObservable from 'react-use/lib/useObservable';
|
||||
|
@ -16,6 +16,7 @@ import Url from 'url';
|
|||
import { CustomBranding } from '@kbn/core-custom-branding-common';
|
||||
import type { HttpStart } from '@kbn/core-http-browser';
|
||||
import type { ChromeNavLink } from '@kbn/core-chrome-browser';
|
||||
import { useEuiTheme } from '@elastic/eui';
|
||||
import { ElasticMark } from './elastic_mark';
|
||||
import { LoadingIndicator } from '../loading_indicator';
|
||||
|
||||
|
@ -83,14 +84,29 @@ interface Props {
|
|||
}
|
||||
|
||||
export function HeaderLogo({ href, navigateToApp, loadingCount$, ...observables }: Props) {
|
||||
const { euiTheme } = useEuiTheme();
|
||||
const forceNavigation = useObservable(observables.forceNavigation$, false);
|
||||
const navLinks = useObservable(observables.navLinks$, []);
|
||||
const customBranding = useObservable(observables.customBranding$, {});
|
||||
const { customizedLogo, logo } = customBranding;
|
||||
|
||||
const styles = {
|
||||
logoCss: css({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
height: euiTheme.size.xxl,
|
||||
paddingInline: euiTheme.size.s,
|
||||
}),
|
||||
logoMarkCss: css({
|
||||
marginLeft: euiTheme.size.s,
|
||||
fill: euiTheme.colors.ghost,
|
||||
}),
|
||||
};
|
||||
|
||||
return (
|
||||
<a
|
||||
onClick={(e) => onClick(e, forceNavigation, navLinks, navigateToApp)}
|
||||
className="chrHeaderLogo"
|
||||
css={styles.logoCss}
|
||||
href={href}
|
||||
data-test-subj="logo"
|
||||
aria-label={i18n.translate('core.ui.chrome.headerGlobalNav.goHomePageIconAriaLabel', {
|
||||
|
@ -101,12 +117,13 @@ export function HeaderLogo({ href, navigateToApp, loadingCount$, ...observables
|
|||
{customizedLogo ? (
|
||||
<img
|
||||
src={customizedLogo}
|
||||
className="chrHeaderLogo__mark"
|
||||
data-test-subj="logoMark"
|
||||
css={styles.logoMarkCss}
|
||||
style={{ maxWidth: '200px', maxHeight: '84px' }}
|
||||
alt="custom mark"
|
||||
/>
|
||||
) : (
|
||||
<ElasticMark className="chrHeaderLogo__mark" aria-hidden={true} />
|
||||
<ElasticMark data-test-subj="logoMark" css={styles.logoMarkCss} aria-hidden={true} />
|
||||
)}
|
||||
</a>
|
||||
);
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
.kbnLoadingIndicator-hidden {
|
||||
visibility: hidden;
|
||||
animation-play-state: paused;
|
||||
}
|
|
@ -16,7 +16,9 @@ import { LoadingIndicator } from './loading_indicator';
|
|||
describe('kbnLoadingIndicator', () => {
|
||||
it('is hidden by default', () => {
|
||||
const wrapper = shallow(<LoadingIndicator loadingCount$={new BehaviorSubject(0)} />);
|
||||
expect(wrapper.prop('data-test-subj')).toBe('globalLoadingIndicator-hidden');
|
||||
expect(
|
||||
wrapper.findWhere((node) => node.prop('data-test-subj') === 'globalLoadingIndicator-hidden')
|
||||
).toHaveLength(1);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
import { Global, css } from '@emotion/react';
|
||||
import { EuiLoadingSpinner, EuiProgress, EuiIcon, EuiImage } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React from 'react';
|
||||
|
@ -14,8 +15,6 @@ import classNames from 'classnames';
|
|||
import type { Subscription } from 'rxjs';
|
||||
import type { HttpStart } from '@kbn/core-http-browser';
|
||||
|
||||
import './loading_indicator.scss';
|
||||
|
||||
export interface LoadingIndicatorProps {
|
||||
loadingCount$: ReturnType<HttpStart['getLoadingCount$']>;
|
||||
showAsBar?: boolean;
|
||||
|
@ -60,6 +59,12 @@ export class LoadingIndicator extends React.Component<LoadingIndicatorProps, { v
|
|||
|
||||
render() {
|
||||
const className = classNames(!this.state.visible && 'kbnLoadingIndicator-hidden');
|
||||
const indicatorHiddenCss = !this.state.visible
|
||||
? css({
|
||||
visibility: 'hidden',
|
||||
animationPlayState: 'paused',
|
||||
})
|
||||
: undefined;
|
||||
|
||||
const testSubj = this.state.visible
|
||||
? 'globalLoadingIndicator'
|
||||
|
@ -84,7 +89,6 @@ export class LoadingIndicator extends React.Component<LoadingIndicatorProps, { v
|
|||
type={'logoElastic'}
|
||||
size="l"
|
||||
data-test-subj={testSubj}
|
||||
className="chrHeaderLogo__cluster"
|
||||
aria-label={i18n.translate('core.ui.chrome.headerGlobalNav.logoAriaLabel', {
|
||||
defaultMessage: 'Elastic Logo',
|
||||
})}
|
||||
|
@ -102,18 +106,31 @@ export class LoadingIndicator extends React.Component<LoadingIndicatorProps, { v
|
|||
logoImage
|
||||
);
|
||||
|
||||
return !this.props.showAsBar ? (
|
||||
logo
|
||||
) : (
|
||||
<EuiProgress
|
||||
className={className}
|
||||
data-test-subj={testSubj}
|
||||
max={this.props.maxAmount}
|
||||
value={this.props.valueAmount}
|
||||
position="fixed"
|
||||
color="accent"
|
||||
size="xs"
|
||||
/>
|
||||
return (
|
||||
<>
|
||||
<Global
|
||||
styles={{
|
||||
'.euiHeaderSectionItem .euiButtonEmpty__text': {
|
||||
// stop global header buttons from jumping during loading state
|
||||
display: 'flex',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
{!this.props.showAsBar ? (
|
||||
logo
|
||||
) : (
|
||||
<EuiProgress
|
||||
className={className}
|
||||
css={indicatorHiddenCss}
|
||||
data-test-subj={testSubj}
|
||||
max={this.props.maxAmount}
|
||||
value={this.props.valueAmount}
|
||||
position="fixed"
|
||||
color="accent"
|
||||
size="xs"
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
.chrHeaderLogo__mark {
|
||||
margin-left: $euiSizeS;
|
||||
fill: $euiColorGhost;
|
||||
}
|
|
@ -184,7 +184,7 @@ export const focusUtilityBarAction = (containerElement: HTMLElement | null) => {
|
|||
* Resets keyboard focus on the page
|
||||
*/
|
||||
export const resetKeyboardFocus = () => {
|
||||
document.querySelector<HTMLAnchorElement>('header.headerGlobalNav a.chrHeaderLogo')?.focus();
|
||||
document.body.focus();
|
||||
};
|
||||
|
||||
interface OperatorHandler {
|
||||
|
|
|
@ -91,8 +91,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
require.resolve('./acme_text.png')
|
||||
);
|
||||
await goToSettings();
|
||||
const logo = await testSubjects.find('logo');
|
||||
const img = await logo.findByCssSelector('.chrHeaderLogo__mark');
|
||||
const img = await testSubjects.find('logoMark');
|
||||
const imgSrc = (await img.getAttribute('src')) ?? '';
|
||||
expect(imgSrc.startsWith('data:image/png')).to.be(true);
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue