diff --git a/e2e/screenshots/metric_stories.test.ts-snapshots/metric/should-render-metric-with-value-in-middle-position-chrome-linux.png b/e2e/screenshots/metric_stories.test.ts-snapshots/metric/should-render-metric-with-value-in-middle-position-chrome-linux.png new file mode 100644 index 0000000000..649a8edfe7 Binary files /dev/null and b/e2e/screenshots/metric_stories.test.ts-snapshots/metric/should-render-metric-with-value-in-middle-position-chrome-linux.png differ diff --git a/e2e/tests/metric_stories.test.ts b/e2e/tests/metric_stories.test.ts index 671caabda8..81f6bad986 100644 --- a/e2e/tests/metric_stories.test.ts +++ b/e2e/tests/metric_stories.test.ts @@ -112,6 +112,15 @@ test.describe('Metric', () => { ); }); + test('should render metric with value in middle position', async ({ page }) => { + await common.expectChartAtUrlToMatchScreenshot(page)( + `http://localhost:9001/?path=/story/metric-alpha--basic&globals=toggles.showHeader:true;toggles.showChartTitle:false;toggles.showChartDescription:false;toggles.showChartBoundary:false;theme:light&knob-value text-align=center&knob-value position=middle`, + { + action: async () => await common.setResizeDimensions(page)({ height: 300, width: 200 }), + }, + ); + }); + test('should use restrictive breakpoint at 99px height', async ({ page }) => { await common.expectChartAtUrlToMatchScreenshot(page)( `http://localhost:9001/?path=/story/metric-alpha--layout&globals=theme:light;toggles.showHeader:true;toggles.showChartTitle:false;toggles.showChartDescription:false;toggles.showChartBoundary:false&knob-Aria description_Secondary metric=This is a description&knob-Bar background_Colors=rgb(194,201,214)&knob-Blending background_Colors=rgba(255,255,255,1)&knob-Color by value_Secondary metric=true&knob-Custom extra_Secondary metric=last 5m&knob-Extra element alignment_Text configuration and position=left&knob-Is numeric metric=true&knob-Label_Secondary metric=Last week&knob-Metric color_Colors=rgb(246,217,143)&knob-Metric icon align_Text configuration and position=right&knob-Primary metric alignment_Text configuration and position=left&knob-Primary metric font size (only if custom font size selected)_Text configuration and position=40&knob-Primary metric font size mode_Text configuration and position=default&knob-Primary metric position_Text configuration and position=top&knob-Progress bar direction=horizontal&knob-Progress max=100&knob-Secondary metric label position_Secondary metric=before&knob-Secondary metric trend icon position_Secondary metric=after&knob-Secondary metric trend icon_Secondary metric=↑&knob-Secondary metric value color_Secondary metric=rgb(93, 191, 149)&knob-Secondary metric value_Secondary metric=87.20&knob-Show extra_Secondary metric=true&knob-Show metric icon_Text configuration and position=true&knob-Title= Count of records Count of records Count of records Count of records&knob-Title and subtitle alignment_Text configuration and position=left&knob-Title weight_Text configuration and position=normal&knob-Trend a11y description=The trend shows a peak of CPU usage in the last 5 minutes&knob-Trend a11y title=The Cluster CPU Usage trend&knob-Trend data points=30&knob-Trend shape=area&knob-Value=5&knob-Value color_Colors=#065B58&knob-Subtitle=Subtitle Subtitle Subtitle Subtitle Subtitle&knob-Visualization type=none&knob-Value prefix=&knob-Value postfix= &knob-Use custom extra_Secondary metric=&knob-Use value color_Colors=&knob-Use blending background_Colors=&knob-Show value icon=`, diff --git a/packages/charts/api/charts.api.md b/packages/charts/api/charts.api.md index 78a6c63e8f..09a43f922a 100644 --- a/packages/charts/api/charts.api.md +++ b/packages/charts/api/charts.api.md @@ -2174,7 +2174,7 @@ export interface MetricStyle { // (undocumented) valueFontSize: 'default' | 'fit' | number; // (undocumented) - valuePosition: 'top' | 'bottom'; + valuePosition: 'top' | 'middle' | 'bottom'; // (undocumented) valueTextAlign: Extract; } diff --git a/packages/charts/src/chart_types/metric/renderer/dom/_text.scss b/packages/charts/src/chart_types/metric/renderer/dom/_text.scss index bc049f5dc7..5ddc55d7f2 100644 --- a/packages/charts/src/chart_types/metric/renderer/dom/_text.scss +++ b/packages/charts/src/chart_types/metric/renderer/dom/_text.scss @@ -40,7 +40,7 @@ } } - .echMetricText__extraBlock { + &__extraBlock { display: flex; align-items: center; overflow: hidden; @@ -55,6 +55,11 @@ &--right { justify-content: flex-end; } + + // Vertical position modifiers + &--middle { + padding-top: 0; + } } &__valueBlock { diff --git a/packages/charts/src/chart_types/metric/renderer/dom/text.tsx b/packages/charts/src/chart_types/metric/renderer/dom/text.tsx index fb7d3a2265..824c65bde3 100644 --- a/packages/charts/src/chart_types/metric/renderer/dom/text.tsx +++ b/packages/charts/src/chart_types/metric/renderer/dom/text.tsx @@ -24,6 +24,7 @@ const GRID_SPAN_THREE = '1 / span 3'; const gridRows = { top: { value: '1', titles: '2', body: '3', extra: '4' }, + middle: { value: '3', titles: '1', body: '2', extra: '5' }, bottom: { value: '4', titles: '1', body: '2', extra: '3' }, }; @@ -39,8 +40,14 @@ const gridColumnsValuePositionBottom = { right: { value: GRID_SPAN_THREE, titles: '1 / span 2', body: GRID_SPAN_THREE, extra: GRID_SPAN_THREE }, }; +const gridColumnsValuePositionMiddle = { + left: { value: GRID_SPAN_THREE, titles: '2 / span 2', body: GRID_SPAN_THREE, extra: GRID_SPAN_THREE }, + right: { value: GRID_SPAN_THREE, titles: '1 / span 2', body: GRID_SPAN_THREE, extra: GRID_SPAN_THREE }, +}; + const gridColumns = { top: gridColumnsValuePostitionTop, + middle: gridColumnsValuePositionMiddle, bottom: gridColumnsValuePositionBottom, }; @@ -52,6 +59,7 @@ const getGridTemplateColumnsWithIcon = (iconSize: number) => { const gridTemplateRows = { bottom: `min-content auto min-content min-content`, + middle: `min-content 1fr min-content 1fr min-content`, top: `min-content min-content auto min-content`, }; @@ -179,7 +187,11 @@ export const MetricText: React.FC = ({ {/* Extra Block */}
0 ? titleLines.length * titleLineHeight : 0; const actualSubtitleHeight = subtitleLines.length > 0 ? subtitleLines.length * subtitleLineHeight + ELEMENT_PADDING : 0; // Subtitle padding top 5px - const actualExtraHeight = breakpoints.extra ? extraHeight + ELEMENT_PADDING : 0; // Extra padding top 5px + const actualExtraHeight = breakpoints.extra ? extraHeight + extraPaddingTop : 0; const nonValueElementsHeight = actualTitleHeight + actualSubtitleHeight + actualExtraHeight + progressBarHeight + PADDING * 2; diff --git a/packages/charts/src/utils/themes/theme.ts b/packages/charts/src/utils/themes/theme.ts index e537d9c7f9..4c5ae6c201 100644 --- a/packages/charts/src/utils/themes/theme.ts +++ b/packages/charts/src/utils/themes/theme.ts @@ -327,7 +327,7 @@ export interface MetricStyle { titlesTextAlign: Extract; extraTextAlign: Extract; valueTextAlign: Extract; - valuePosition: 'top' | 'bottom'; + valuePosition: 'top' | 'middle' | 'bottom'; iconAlign: Extract; titleWeight: MetricFontWeight; diff --git a/storybook/stories/metric/1_basic.story.tsx b/storybook/stories/metric/1_basic.story.tsx index 69b9c677ed..3e2b9ccdca 100644 --- a/storybook/stories/metric/1_basic.story.tsx +++ b/storybook/stories/metric/1_basic.story.tsx @@ -81,7 +81,7 @@ export const Example: ChartsStory = (_, { title: storyTitle, description }) => { const titlesTextAlign = getTextAlignKnob('title text-align', 'left'); const valueTextAlign = getTextAlignKnob('value text-align', 'right'); const extraTextAlign = getTextAlignKnob('extra text-align', 'right'); - const valuePosition = select('value position', { Bottom: 'bottom', Top: 'top' }, 'bottom'); + const valuePosition = select('value position', { Bottom: 'bottom', Middle: 'middle', Top: 'top' }, 'bottom'); const iconAlign = select( 'icon align', { diff --git a/storybook/stories/metric/2_grid.story.tsx b/storybook/stories/metric/2_grid.story.tsx index aab23bb65e..4df0807ff3 100644 --- a/storybook/stories/metric/2_grid.story.tsx +++ b/storybook/stories/metric/2_grid.story.tsx @@ -63,6 +63,7 @@ export const Example: ChartsStory = (_, { title, description }) => { 'default', ); const valueFontSize = number('value font size (px)', 40, { min: 0, step: 10 }); + const valuePosition = select('value position', { Bottom: 'bottom', Middle: 'middle', Top: 'top' }, 'bottom'); const data: (MetricDatum | undefined)[] = useMemo( () => [ @@ -227,6 +228,7 @@ export const Example: ChartsStory = (_, { title, description }) => { metric: { emptyBackground, valueFontSize: valueFontSizeMode === 'custom' ? valueFontSize : valueFontSizeMode, + valuePosition, }, }} baseTheme={useBaseTheme()} diff --git a/storybook/stories/metric/3_body.story.tsx b/storybook/stories/metric/3_body.story.tsx index 24a9edb13e..b30ae6fa04 100644 --- a/storybook/stories/metric/3_body.story.tsx +++ b/storybook/stories/metric/3_body.story.tsx @@ -53,6 +53,7 @@ export const Example: ChartsStory = (_, { title: storyTitle, description }) => { const valueIconType = customKnobs.eui.getIconTypeKnob('EUI value icon glyph name', 'sortUp'); const showBody = boolean('show body contents', true); const showBodyArea = boolean('show full body area', false); + const valuePosition = select('value position', { Bottom: 'bottom', Middle: 'middle', Top: 'top' }, 'bottom'); const getIcon = (type: string) => ({ width, height, color }: { width: number; height: number; color: string }) => ( @@ -112,6 +113,11 @@ export const Example: ChartsStory = (_, { title: storyTitle, description }) => { return ( { if (isMetricElementEvent(d)) { diff --git a/storybook/stories/metric/7_layout.story.tsx b/storybook/stories/metric/7_layout.story.tsx index 83e592df95..5c3efce3ac 100644 --- a/storybook/stories/metric/7_layout.story.tsx +++ b/storybook/stories/metric/7_layout.story.tsx @@ -243,7 +243,7 @@ export const Example: ChartsStory = (_, { title: storyTitle, description }) => { // Value (primary metric) const valuePosition = select( 'Primary metric position', - { Bottom: 'bottom', Top: 'top' }, + { Bottom: 'bottom', Middle: 'middle', Top: 'top' }, 'top', textConfigurationAndPositionGroup, );