[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:
Shahzad 2020-10-07 10:17:53 +02:00 committed by GitHub
parent cded1ce5f1
commit 8f49154100
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 75 additions and 20 deletions

View file

@ -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`}>

View file

@ -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();
});

View file

@ -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}
/>
);
}

View file

@ -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}
/>
</>
);

View file

@ -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>

View file

@ -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}>

View file

@ -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.',
});