[UX] Update help labels for web core vitals (#79662)
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
cded1ce5f1
commit
8f49154100
|
@ -48,7 +48,8 @@ export function UXMetrics() {
|
|||
<KeyUXMetrics data={data} loading={status !== 'success'} />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiHorizontalRule />
|
||||
<EuiSpacer size="xs" />
|
||||
<EuiHorizontalRule margin="xs" />
|
||||
|
||||
<EuiFlexGroup justifyContent="spaceBetween" wrap>
|
||||
<EuiFlexItem grow={1} data-cy={`client-metrics`}>
|
||||
|
|
|
@ -33,14 +33,9 @@ describe('UXSection', () => {
|
|||
expect(getByText('View in app')).toBeInTheDocument();
|
||||
expect(getByText('elastic-co-frontend')).toBeInTheDocument();
|
||||
expect(getByText('Largest contentful paint')).toBeInTheDocument();
|
||||
expect(getByText('Largest contentful paint 1.94 s')).toBeInTheDocument();
|
||||
expect(getByText('First input delay 14 ms')).toBeInTheDocument();
|
||||
expect(getByText('Cumulative layout shift 0.01')).toBeInTheDocument();
|
||||
|
||||
expect(getByText('Largest contentful paint')).toBeInTheDocument();
|
||||
expect(getByText('Largest contentful paint 1.94 s')).toBeInTheDocument();
|
||||
expect(getByText('First input delay 14 ms')).toBeInTheDocument();
|
||||
expect(getByText('Cumulative layout shift 0.01')).toBeInTheDocument();
|
||||
expect(getByText('1.94 s')).toBeInTheDocument();
|
||||
expect(getByText('14 ms')).toBeInTheDocument();
|
||||
expect(getByText('0.01')).toBeInTheDocument();
|
||||
|
||||
// LCP Rank Values
|
||||
expect(getByText('Good (65%)')).toBeInTheDocument();
|
||||
|
@ -77,7 +72,7 @@ describe('UXSection', () => {
|
|||
);
|
||||
|
||||
expect(getByText('User Experience')).toBeInTheDocument();
|
||||
expect(getAllByText('Statistic is loading')).toHaveLength(3);
|
||||
expect(getAllByText('--')).toHaveLength(3);
|
||||
expect(queryAllByText('View in app')).toEqual([]);
|
||||
expect(getByText('elastic-co-frontend')).toBeInTheDocument();
|
||||
});
|
||||
|
|
|
@ -10,7 +10,7 @@ import { Observable } from 'rxjs';
|
|||
import { CoreStart } from 'src/core/public';
|
||||
import { createKibanaReactContext } from '../../../../../../../../src/plugins/kibana_react/public';
|
||||
import { CoreVitalItem } from '../core_vital_item';
|
||||
import { LCP_LABEL } from '../translations';
|
||||
import { LCP_HELP_LABEL, LCP_LABEL } from '../translations';
|
||||
import { EuiThemeProvider } from '../../../../typings';
|
||||
|
||||
const KibanaReactContext = createKibanaReactContext(({
|
||||
|
@ -40,6 +40,7 @@ export function Basic() {
|
|||
title={LCP_LABEL}
|
||||
value={'0.00s'}
|
||||
loading={false}
|
||||
helpLabel={LCP_HELP_LABEL}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -52,6 +53,7 @@ export function FiftyPercentGood() {
|
|||
value={'0.00s'}
|
||||
loading={false}
|
||||
ranks={[50, 25, 25]}
|
||||
helpLabel={LCP_HELP_LABEL}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -64,6 +66,7 @@ export function OneHundredPercentBad() {
|
|||
value={'0.00s'}
|
||||
loading={false}
|
||||
ranks={[0, 0, 100]}
|
||||
helpLabel={LCP_HELP_LABEL}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -76,6 +79,7 @@ export function OneHundredPercentAverage() {
|
|||
value={'0.00s'}
|
||||
loading={false}
|
||||
ranks={[0, 100, 0]}
|
||||
helpLabel={LCP_HELP_LABEL}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { EuiFlexGroup, euiPaletteForStatus, EuiSpacer, EuiStat } from '@elastic/eui';
|
||||
import { EuiFlexGroup, EuiIconTip, euiPaletteForStatus, EuiSpacer, EuiStat } from '@elastic/eui';
|
||||
import React, { useState } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { PaletteLegends } from './palette_legends';
|
||||
|
@ -15,6 +15,8 @@ import {
|
|||
LESS_LABEL,
|
||||
MORE_LABEL,
|
||||
CV_POOR_LABEL,
|
||||
IS_LABEL,
|
||||
TAKES_LABEL,
|
||||
} from './translations';
|
||||
|
||||
export interface Thresholds {
|
||||
|
@ -28,13 +30,16 @@ interface Props {
|
|||
ranks?: number[];
|
||||
loading: boolean;
|
||||
thresholds: Thresholds;
|
||||
isCls?: boolean;
|
||||
helpLabel: string;
|
||||
}
|
||||
|
||||
export function getCoreVitalTooltipMessage(
|
||||
thresholds: Thresholds,
|
||||
position: number,
|
||||
title: string,
|
||||
percentage: number
|
||||
percentage: number,
|
||||
isCls?: boolean
|
||||
) {
|
||||
const good = position === 0;
|
||||
const bad = position === 2;
|
||||
|
@ -42,9 +47,10 @@ export function getCoreVitalTooltipMessage(
|
|||
|
||||
return i18n.translate('xpack.observability.ux.dashboard.webVitals.palette.tooltip', {
|
||||
defaultMessage:
|
||||
'{percentage} % of users have {exp} experience because the {title} takes {moreOrLess} than {value}{averageMessage}.',
|
||||
'{percentage} % of users have {exp} experience because the {title} {isOrTakes} {moreOrLess} than {value}{averageMessage}.',
|
||||
values: {
|
||||
percentage,
|
||||
isOrTakes: isCls ? IS_LABEL : TAKES_LABEL,
|
||||
title: title?.toLowerCase(),
|
||||
exp: good ? CV_GOOD_LABEL : bad ? CV_POOR_LABEL : CV_AVERAGE_LABEL,
|
||||
moreOrLess: bad || average ? MORE_LABEL : LESS_LABEL,
|
||||
|
@ -59,7 +65,15 @@ export function getCoreVitalTooltipMessage(
|
|||
});
|
||||
}
|
||||
|
||||
export function CoreVitalItem({ loading, title, value, thresholds, ranks = [100, 0, 0] }: Props) {
|
||||
export function CoreVitalItem({
|
||||
loading,
|
||||
title,
|
||||
value,
|
||||
thresholds,
|
||||
ranks = [100, 0, 0],
|
||||
isCls,
|
||||
helpLabel,
|
||||
}: Props) {
|
||||
const palette = euiPaletteForStatus(3);
|
||||
|
||||
const [inFocusInd, setInFocusInd] = useState<number | null>(null);
|
||||
|
@ -71,7 +85,12 @@ export function CoreVitalItem({ loading, title, value, thresholds, ranks = [100,
|
|||
<EuiStat
|
||||
titleSize="s"
|
||||
title={value}
|
||||
description={title}
|
||||
description={
|
||||
<>
|
||||
{title}
|
||||
<EuiIconTip content={helpLabel} type="questionInCircle" />
|
||||
</>
|
||||
}
|
||||
titleColor={palette[biggestValIndex]}
|
||||
isLoading={loading}
|
||||
/>
|
||||
|
@ -89,7 +108,7 @@ export function CoreVitalItem({ loading, title, value, thresholds, ranks = [100,
|
|||
position={ind}
|
||||
inFocus={inFocusInd !== ind && inFocusInd !== null}
|
||||
percentage={ranks[ind]}
|
||||
tooltip={getCoreVitalTooltipMessage(thresholds, ind, title, ranks[ind])}
|
||||
tooltip={getCoreVitalTooltipMessage(thresholds, ind, title, ranks[ind], isCls)}
|
||||
/>
|
||||
))}
|
||||
</EuiFlexGroup>
|
||||
|
@ -101,6 +120,7 @@ export function CoreVitalItem({ loading, title, value, thresholds, ranks = [100,
|
|||
onItemHover={(ind) => {
|
||||
setInFocusInd(ind);
|
||||
}}
|
||||
isCls={isCls}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -5,7 +5,14 @@
|
|||
*/
|
||||
import * as React from 'react';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
|
||||
import { CLS_LABEL, FID_LABEL, LCP_LABEL } from './translations';
|
||||
import {
|
||||
CLS_HELP_LABEL,
|
||||
CLS_LABEL,
|
||||
FID_HELP_LABEL,
|
||||
FID_LABEL,
|
||||
LCP_HELP_LABEL,
|
||||
LCP_LABEL,
|
||||
} from './translations';
|
||||
import { CoreVitalItem } from './core_vital_item';
|
||||
import { WebCoreVitalsTitle } from './web_core_vitals_title';
|
||||
import { ServiceName } from './service_name';
|
||||
|
@ -60,6 +67,7 @@ export function CoreVitals({ data, loading, displayServiceName, serviceName }: P
|
|||
ranks={lcpRanks}
|
||||
loading={loading}
|
||||
thresholds={CoreVitalsThresholds.LCP}
|
||||
helpLabel={LCP_HELP_LABEL}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem style={{ flexBasis: 380 }}>
|
||||
|
@ -69,6 +77,7 @@ export function CoreVitals({ data, loading, displayServiceName, serviceName }: P
|
|||
ranks={fidRanks}
|
||||
loading={loading}
|
||||
thresholds={CoreVitalsThresholds.FID}
|
||||
helpLabel={FID_HELP_LABEL}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem style={{ flexBasis: 380 }}>
|
||||
|
@ -78,6 +87,8 @@ export function CoreVitals({ data, loading, displayServiceName, serviceName }: P
|
|||
ranks={clsRanks}
|
||||
loading={loading}
|
||||
thresholds={CoreVitalsThresholds.CLS}
|
||||
isCls={true}
|
||||
helpLabel={CLS_HELP_LABEL}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
|
|
@ -46,9 +46,10 @@ interface Props {
|
|||
ranks: number[];
|
||||
thresholds: Thresholds;
|
||||
title: string;
|
||||
isCls?: boolean;
|
||||
}
|
||||
|
||||
export function PaletteLegends({ ranks, title, onItemHover, thresholds }: Props) {
|
||||
export function PaletteLegends({ ranks, title, onItemHover, thresholds, isCls }: Props) {
|
||||
const [darkMode] = useUiSetting$<boolean>('theme:darkMode');
|
||||
|
||||
const palette = euiPaletteForStatus(3);
|
||||
|
@ -68,7 +69,7 @@ export function PaletteLegends({ ranks, title, onItemHover, thresholds }: Props)
|
|||
}}
|
||||
>
|
||||
<EuiToolTip
|
||||
content={getCoreVitalTooltipMessage(thresholds, ind, title, ranks[ind])}
|
||||
content={getCoreVitalTooltipMessage(thresholds, ind, title, ranks[ind], isCls)}
|
||||
position="bottom"
|
||||
>
|
||||
<StyledSpan darkMode={darkMode}>
|
||||
|
|
|
@ -52,3 +52,26 @@ export const MORE_LABEL = i18n.translate('xpack.observability.ux.coreVitals.more
|
|||
export const LESS_LABEL = i18n.translate('xpack.observability.ux.coreVitals.less', {
|
||||
defaultMessage: 'less',
|
||||
});
|
||||
|
||||
export const IS_LABEL = i18n.translate('xpack.observability.ux.coreVitals.is', {
|
||||
defaultMessage: 'is',
|
||||
});
|
||||
|
||||
export const TAKES_LABEL = i18n.translate('xpack.observability.ux.coreVitals.takes', {
|
||||
defaultMessage: 'takes',
|
||||
});
|
||||
|
||||
export const LCP_HELP_LABEL = i18n.translate('xpack.observability.ux.coreVitals.lcp.help', {
|
||||
defaultMessage:
|
||||
'Largest contentful paint measures loading performance. To provide a good user experience, LCP should occur within 2.5 seconds of when the page first starts loading.',
|
||||
});
|
||||
|
||||
export const FID_HELP_LABEL = i18n.translate('xpack.observability.ux.coreVitals.fid.help', {
|
||||
defaultMessage:
|
||||
'First input delay measures interactivity. To provide a good user experience, pages should have a FID of less than 100 milliseconds.',
|
||||
});
|
||||
|
||||
export const CLS_HELP_LABEL = i18n.translate('xpack.observability.ux.coreVitals.cls.help', {
|
||||
defaultMessage:
|
||||
'Cumulative Layout Shift (CLS): measures visual stability. To provide a good user experience, pages should maintain a CLS of less than 0.1.',
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue