diff --git a/e2e/screenshots/all.test.ts-snapshots/baselines/test-cases/metric-trend-length-chrome-linux.png b/e2e/screenshots/all.test.ts-snapshots/baselines/test-cases/metric-trend-length-chrome-linux.png new file mode 100644 index 0000000000..4de091aff0 Binary files /dev/null and b/e2e/screenshots/all.test.ts-snapshots/baselines/test-cases/metric-trend-length-chrome-linux.png differ diff --git a/packages/charts/src/chart_types/metric/renderer/dom/sparkline.tsx b/packages/charts/src/chart_types/metric/renderer/dom/sparkline.tsx index 977dc0888d..dd056778a3 100644 --- a/packages/charts/src/chart_types/metric/renderer/dom/sparkline.tsx +++ b/packages/charts/src/chart_types/metric/renderer/dom/sparkline.tsx @@ -50,22 +50,24 @@ export const SparkLine: FunctionComponent<{ id: string; datum: MetricWTrend; }> = ({ id, datum: { color, trend, trendA11yTitle, trendA11yDescription, trendShape } }) => { - if (!trend) { - return null; - } const sortedTrendData = getSortedData(trend); - const [xMin, xMax] = [sortedTrendData.at(0)!.x, sortedTrendData.at(-1)!.x]; + const xMin = sortedTrendData.at(0)?.x ?? NaN; + const xMax = sortedTrendData.at(-1)?.x ?? NaN; const [, yMax] = extent(sortedTrendData.map((d) => d.y)); const xScale = (value: number) => (value - xMin) / (xMax - xMin); const yScale = (value: number) => value / yMax; - const path = areaGenerator<{ x: number; y: number }>( - (d) => xScale(d.x), - () => 1, - (d) => 1 - yScale(d.y), - (d) => isFiniteNumber(d.x) && isFiniteNumber(d.y), - trendShape === MetricTrendShape.Bars ? CurveType.CURVE_STEP_AFTER : CurveType.LINEAR, - ); + const shouldVisualizePath = Boolean(xMax - xMin) && yMax; + + const path = shouldVisualizePath + ? areaGenerator<{ x: number; y: number }>( + (d) => xScale(d.x), + () => 1, + (d) => 1 - yScale(d.y), + (d) => isFiniteNumber(d.x) && isFiniteNumber(d.y), + trendShape === MetricTrendShape.Bars ? CurveType.CURVE_STEP_AFTER : CurveType.LINEAR, + ) + : undefined; const titleId = `${id}-trend-title`; const descriptionId = `${id}-trend-description`; @@ -89,13 +91,15 @@ export const SparkLine: FunctionComponent<{ - + {path && ( + + )} ); diff --git a/storybook/stories/test_cases/22_metric_trend_length.story.tsx b/storybook/stories/test_cases/22_metric_trend_length.story.tsx new file mode 100644 index 0000000000..fb08e84c52 --- /dev/null +++ b/storybook/stories/test_cases/22_metric_trend_length.story.tsx @@ -0,0 +1,95 @@ +/* + * 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 { number } from '@storybook/addon-knobs'; +import React, { useMemo } from 'react'; + +import { Chart, Settings, Metric } from '@elastic/charts'; +import { getRandomNumberGenerator } from '@elastic/charts/src/mocks/utils'; + +import { ChartsStory } from '../../types'; +import { useBaseTheme } from '../../use_base_theme'; + +const rng = getRandomNumberGenerator(); + +export const Example: ChartsStory = (_, { title, description }) => { + const trendLength = number('Trend length x', 3, { min: 0 }); + const trendData = Array.from({ length: trendLength }) + .fill(0) + .map((_, x) => ({ + x, + y: rng(0, 100), + })); + + return ( + + + `${v} length`, + trend: [], + trendShape: 'area', + }, + { + color: '#add3f5', + title: 'Trend - length 1', + value: 1, + valueFormatter: (v) => `${v} length`, + trend: useMemo( + () => [ + { + x: 1, + y: rng(0, 100), + }, + ], + [], + ), + trendShape: 'area', + }, + ], + [ + { + color: '#db9b2c', + title: 'Trend - length 2', + value: 2, + valueFormatter: (v) => `${v} length`, + trend: useMemo( + () => [ + { + x: 1, + y: rng(0, 100), + }, + { + x: 2, + y: rng(0, 100), + }, + ], + [], + ), + trendShape: 'area', + }, + { + color: '#1ceec6', + title: 'Trend - length x', + value: trendLength, + valueFormatter: (v) => `${v} length`, + trend: trendData, + trendShape: 'area', + }, + ], + ]} + /> + + ); +}; diff --git a/storybook/stories/test_cases/test_cases.stories.tsx b/storybook/stories/test_cases/test_cases.stories.tsx index 81302336b1..78fd831236 100644 --- a/storybook/stories/test_cases/test_cases.stories.tsx +++ b/storybook/stories/test_cases/test_cases.stories.tsx @@ -21,5 +21,6 @@ export { Example as testPointsOutsideOfDomain } from './8_test_points_outside_of export { Example as duplicateLabelsInPartitionLegend } from './9_duplicate_labels_in_partition_legend.story'; export { Example as highlighterZIndex } from './10_highlighter_z_index.story'; export { Example as domainEdges } from './21_domain_edges.story'; +export { Example as metricTrendLength } from './22_metric_trend_length.story'; export { Example as startDayOfWeek } from './11_start_day_of_week.story'; export { Example as logWithNegativeValues } from './12_log_with_negative_values.story';