diff --git a/semcore/d3-chart/__tests__/d3-chart-base.browser-test.tsx b/semcore/d3-chart/__tests__/d3-chart-base.browser-test.tsx index 904af85c1f..23e19b0071 100644 --- a/semcore/d3-chart/__tests__/d3-chart-base.browser-test.tsx +++ b/semcore/d3-chart/__tests__/d3-chart-base.browser-test.tsx @@ -218,12 +218,10 @@ test.describe(`${TAG.VISUAL}`, () => { test.describe('Reference Lines', () => { test('Verify attributes reference lines ', { - tag: [TAG.PRIORITY_MEDIUM, '@d3-chart'], + tag: [TAG.PRIORITY_LOW, '@d3-chart'], }, async ({ page }) => { await loadPage(page, 'stories/components/d3-chart/tests/examples/d3-chart/reference-line-props.tsx', 'en'); - const svgs = page.locator('svg'); - const referenceLine = locators.referenceLine(page, 0); await expect(referenceLine).toHaveAttribute('aria-hidden', 'true'); await expect(referenceLine).toHaveAttribute('title', 'Left data'); @@ -232,7 +230,7 @@ test.describe(`${TAG.VISUAL}`, () => { await expect(referenceTitle).toHaveAttribute('aria-hidden', 'true'); await expect(referenceTitle).toHaveAttribute('value', 'Category 0'); - const background = await svgs.first().locator('rect').nth(1); + const background = locators.plot(page, 0).locator('path[value="Category 3"]'); await expect(background).toHaveAttribute('aria-hidden', 'true'); await expect(background).toHaveAttribute('value', 'Category 3'); diff --git a/semcore/d3-chart/__tests__/d3-chart-base.browser-test.tsx-snapshots/-visual-Reference-Lines-Verify-attributes-reference-lines-1-chromium-linux.png b/semcore/d3-chart/__tests__/d3-chart-base.browser-test.tsx-snapshots/-visual-Reference-Lines-Verify-attributes-reference-lines-1-chromium-linux.png index e369b75fbd..dc58088b1f 100644 Binary files a/semcore/d3-chart/__tests__/d3-chart-base.browser-test.tsx-snapshots/-visual-Reference-Lines-Verify-attributes-reference-lines-1-chromium-linux.png and b/semcore/d3-chart/__tests__/d3-chart-base.browser-test.tsx-snapshots/-visual-Reference-Lines-Verify-attributes-reference-lines-1-chromium-linux.png differ diff --git a/semcore/d3-chart/__tests__/d3-chart-base.browser-test.tsx-snapshots/-visual-Reference-Lines-Verify-attributes-reference-lines-1-firefox-linux.png b/semcore/d3-chart/__tests__/d3-chart-base.browser-test.tsx-snapshots/-visual-Reference-Lines-Verify-attributes-reference-lines-1-firefox-linux.png index 4f42984c65..0123188385 100644 Binary files a/semcore/d3-chart/__tests__/d3-chart-base.browser-test.tsx-snapshots/-visual-Reference-Lines-Verify-attributes-reference-lines-1-firefox-linux.png and b/semcore/d3-chart/__tests__/d3-chart-base.browser-test.tsx-snapshots/-visual-Reference-Lines-Verify-attributes-reference-lines-1-firefox-linux.png differ diff --git a/semcore/d3-chart/__tests__/d3-chart-base.browser-test.tsx-snapshots/-visual-Reference-Lines-Verify-attributes-reference-lines-1-webkit-linux.png b/semcore/d3-chart/__tests__/d3-chart-base.browser-test.tsx-snapshots/-visual-Reference-Lines-Verify-attributes-reference-lines-1-webkit-linux.png index 6963bebd5f..dc2638f06d 100644 Binary files a/semcore/d3-chart/__tests__/d3-chart-base.browser-test.tsx-snapshots/-visual-Reference-Lines-Verify-attributes-reference-lines-1-webkit-linux.png and b/semcore/d3-chart/__tests__/d3-chart-base.browser-test.tsx-snapshots/-visual-Reference-Lines-Verify-attributes-reference-lines-1-webkit-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx new file mode 100644 index 0000000000..29e42e8502 --- /dev/null +++ b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx @@ -0,0 +1,507 @@ +import type { Locator, Page } from '@semcore/testing-utils/playwright'; +import { expect, test } from '@semcore/testing-utils/playwright'; +import { loadPage } from '@semcore/testing-utils/shared/helpers'; +import { TAG } from '@semcore/testing-utils/shared/tags'; + +const BASIC_USAGE_STORY = 'stories/components/d3-chart/tests/examples/line-chart/basic-usage.tsx'; +const TIME_AXIS_STORY = 'stories/components/d3-chart/docs/examples/d3-chart/reference-line.tsx'; + +export const locators = { + chart: (page: Page) => page.locator('[data-ui-name="Chart.Line"]').first(), + plot: (page: Page) => page.locator('svg[data-ui-name="Plot"]').first(), + dots: (page: Page, index?: number) => { + const base = page.locator('[data-ui-name="Line.Dots"]'); + return typeof index === 'number' ? base.nth(index) : base; + }, + tooltip: (page: Page) => page.locator('[data-ui-name="Line.Tooltip"], [data-ui-name="HoverLine.Tooltip"]'), + referenceLine: (page: Page) => page.locator('[data-ui-name="ReferenceLine"]'), + referenceLineArea: (page: Page) => page.locator('path[fill$="-pattern)"]:not([value])'), + referenceArea: (page: Page) => page.locator('path[fill$="-pattern)"][value]'), + referenceShapes: (page: Page) => page.locator('path[fill$="-pattern)"]'), + gradients: (page: Page) => page.locator('linearGradient[id$="-pattern"]'), + plotText: (page: Page, text: string) => page.locator('svg[data-ui-name="Plot"] text', { hasText: text }), +}; + +const expectEachToBeHiddenFromA11y = async (locator: Locator) => { + await expect(locator).not.toHaveCount(0); + + const exposed = await locator.evaluateAll((elements) => + elements + .map((element, index) => (element.closest('[aria-hidden="true"]') ? null : index)) + .filter((index) => index !== null), + ); + + expect(exposed).toEqual([]); +}; + +/** SVG user-space box; WebKit's `boundingBox()` is unreliable for ``. */ +const getSvgBox = (locator: Locator) => + locator.evaluate((element) => { + const { x, width } = (element as SVGGraphicsElement).getBBox(); + return { x, width }; + }); + +const getBox = async (locator: Locator) => { + const box = await locator.boundingBox(); + if (!box) throw new Error('Bounding box not found'); + return box; +}; + +/** Horizontal centre of the dot that sits on `x` of the first series. */ +const dotCenterX = async (page: Page, x: number) => { + const box = await getBox(locators.dots(page, x)); + return box.x + box.width / 2; +}; + +const RANGES = { + left: [0, 3], + middle: [8, 12], + right: [16, 19], +} as const; + +const SHORT_TITLE = 'Good'; +const SUB_TITLE = '+10%'; + +type PairwiseCase = { + name: string; + use: 'neutral' | 'good' | 'bad' | 'insight'; + title: '' | typeof SHORT_TITLE; + subTitle: '' | typeof SUB_TITLE; + range: keyof typeof RANGES; + line: 'off' | 'plain' | 'area40'; + lineValue?: number; + width: 500 | 300; +}; + +/** + * Pairwise set over use × title × subTitle × range × line × line position × plot width: + * every pair of values meets in at least one case (13 cases instead of 864). + */ +const pairwiseCases: PairwiseCase[] = [ + { name: '#1 bad, middle, no titles', use: 'bad', title: '', subTitle: '', range: 'middle', line: 'off', width: 500 }, + { name: '#2 good, right, titles, line area inside', use: 'good', title: SHORT_TITLE, subTitle: SUB_TITLE, range: 'right', line: 'area40', lineValue: 18, width: 500 }, + { name: '#3 insight, left, titles, plain line outside, narrow', use: 'insight', title: SHORT_TITLE, subTitle: SUB_TITLE, range: 'left', line: 'plain', lineValue: 10, width: 300 }, + { name: '#4 neutral, right, title, narrow', use: 'neutral', title: SHORT_TITLE, subTitle: '', range: 'right', line: 'off', width: 300 }, + { name: '#5 neutral, middle, subTitle only, plain line inside', use: 'neutral', title: '', subTitle: SUB_TITLE, range: 'middle', line: 'plain', lineValue: 10, width: 500 }, + { name: '#6 insight, middle, title, line area outside, narrow', use: 'insight', title: SHORT_TITLE, subTitle: '', range: 'middle', line: 'area40', lineValue: 4, width: 300 }, + { name: '#7 good, left, no titles, plain line inside, narrow', use: 'good', title: '', subTitle: '', range: 'left', line: 'plain', lineValue: 1, width: 300 }, + { name: '#8 bad, left, titles, line area inside', use: 'bad', title: SHORT_TITLE, subTitle: SUB_TITLE, range: 'left', line: 'area40', lineValue: 1, width: 500 }, + { name: '#9 neutral, left, titles', use: 'neutral', title: SHORT_TITLE, subTitle: SUB_TITLE, range: 'left', line: 'off', width: 500 }, + { name: '#10 bad, right, title, plain line outside, narrow', use: 'bad', title: SHORT_TITLE, subTitle: '', range: 'right', line: 'plain', lineValue: 6, width: 300 }, + { name: '#11 insight, right, no titles', use: 'insight', title: '', subTitle: '', range: 'right', line: 'off', width: 500 }, + { name: '#12 good, middle, titles, narrow', use: 'good', title: SHORT_TITLE, subTitle: SUB_TITLE, range: 'middle', line: 'off', width: 300 }, + { name: '#13 neutral, left, subTitle only, line area outside', use: 'neutral', title: '', subTitle: SUB_TITLE, range: 'left', line: 'area40', lineValue: 10, width: 500 }, +]; + +const toStoryProps = (c: PairwiseCase) => ({ + duration: 0, + useExplicitPlotWidth: true, + plotWidth: c.width, + withReferenceArea: true, + referenceAreaStart: RANGES[c.range][0], + referenceAreaEnd: RANGES[c.range][1], + referenceAreaUse: c.use, + referenceAreaTitle: c.title, + referenceAreaSubTitle: c.subTitle, + withReferenceLine: c.line !== 'off', + ...(c.lineValue !== undefined ? { referenceLineValue: c.lineValue } : {}), + ...(c.line === 'area40' ? { referenceLineArea: 40 } : {}), +}); + +const expectLineAreaWidth = async (page: Page, area: number) => { + const areaBox = await getBox(locators.referenceLineArea(page)); + const lineBox = await getBox(locators.referenceLine(page).locator('line').nth(1)); + + expect(Math.abs(areaBox.width - area)).toBeLessThanOrEqual(1); + expect(Math.abs(areaBox.x + areaBox.width / 2 - (lineBox.x + lineBox.width / 2))).toBeLessThanOrEqual(1); +}; + +/* ===================================================== +@visual +Visual states, hover and focus styles, paddings, margins, and snapshots. +===================================================== */ +test.describe(`${TAG.VISUAL}`, () => { + pairwiseCases.forEach((c) => { + test(`Verify reference pairwise ${c.name}`, { + tag: [TAG.PRIORITY_HIGH, '@line-chart', '@d3-chart', '@base-components', '@flex-box'], + }, async ({ page }) => { + await loadPage(page, BASIC_USAGE_STORY, 'en', toStoryProps(c)); + await locators.plot(page).waitFor({ state: 'visible' }); + + if (c.line === 'plain') { + await test.step('Reference line without area renders no area shape', async () => { + await expect(locators.referenceLine(page)).toHaveCount(1); + await expect(locators.referenceLineArea(page)).toHaveCount(0); + }); + } + + await test.step('Verify chart with reference renders correctly', async () => { + await expect(locators.chart(page)).toHaveScreenshot(); + }); + }); + }); + + test('Verify reference line with area 52', { + tag: [TAG.PRIORITY_HIGH, '@line-chart', '@d3-chart', '@base-components', '@flex-box'], + }, async ({ page }) => { + await loadPage(page, BASIC_USAGE_STORY, 'en', { + duration: 0, + withReferenceLine: true, + referenceLineArea: 52, + }); + await locators.plot(page).waitFor({ state: 'visible' }); + + await test.step('Area is 52px wide and centred on the line', async () => { + await expectLineAreaWidth(page, 52); + }); + + await test.step('Verify chart with reference line renders correctly', async () => { + await expect(locators.chart(page)).toHaveScreenshot(); + }); + }); + + test('Verify several reference lines passed as an array', { + tag: [TAG.PRIORITY_HIGH, '@line-chart', '@d3-chart', '@base-components', '@flex-box'], + }, async ({ page }) => { + await loadPage(page, BASIC_USAGE_STORY, 'en', { + duration: 0, + withReferenceLine: true, + referenceLineCount: 3, + referenceLineArea: 40, + }); + await locators.plot(page).waitFor({ state: 'visible' }); + + await test.step('Every line is rendered with its own area', async () => { + await expect(locators.referenceLine(page)).toHaveCount(3); + await expect(locators.referenceLineArea(page)).toHaveCount(3); + }); + + await test.step('Every area has its own gradient', async () => { + const ids = await locators.gradients(page).evaluateAll((elements) => elements.map((gradient) => gradient.id)); + + expect(ids).toHaveLength(3); + expect(new Set(ids).size).toBe(3); + }); + + await test.step('Verify chart with several reference lines renders correctly', async () => { + await expect(locators.chart(page)).toHaveScreenshot(); + }); + }); + + test('Verify reference line and area on a time axis', { + tag: [TAG.PRIORITY_HIGH, '@line-chart', '@d3-chart'], + }, async ({ page }) => { + await loadPage(page, TIME_AXIS_STORY, 'en'); + await locators.plot(page).waitFor({ state: 'visible' }); + + await test.step('Date values render both lines and the area', async () => { + await expect(locators.referenceLine(page)).toHaveCount(2); + await expect(locators.referenceLineArea(page)).toHaveCount(1); + await expect(locators.referenceArea(page)).toHaveCount(1); + }); + + await test.step('No reference geometry has NaN', async () => { + const ds = await locators.referenceShapes(page).evaluateAll((paths) => + paths.map((path) => path.getAttribute('d') ?? ''), + ); + + expect(ds.filter((d) => d.includes('NaN'))).toEqual([]); + }); + + await test.step('Area texts are rendered', async () => { + await expect(locators.plotText(page, 'Wow!')).toHaveCount(1); + await expect(locators.plotText(page, SUB_TITLE)).toHaveCount(1); + }); + + await test.step('Verify time axis chart with references renders correctly', async () => { + await expect(locators.chart(page)).toHaveScreenshot(); + }); + }); +}); + +/* ===================================================== +@functional +Keyboard and mouse interactions - no snapshots here. +We verify states, visibility, and attributes. +===================================================== */ +test.describe(`${TAG.FUNCTIONAL}`, () => { + test('Verify no reference is rendered without reference props', { + tag: [TAG.PRIORITY_HIGH, '@line-chart', '@d3-chart', '@base-components', '@flex-box'], + }, async ({ page }) => { + await loadPage(page, BASIC_USAGE_STORY, 'en', { duration: 0 }); + await locators.plot(page).waitFor({ state: 'visible' }); + + await expect(locators.referenceLine(page)).toHaveCount(0); + await expect(locators.referenceShapes(page)).toHaveCount(0); + await expect(locators.gradients(page)).toHaveCount(0); + }); + + [40, 52].forEach((area) => { + test(`Verify reference line with area ${area}`, { + tag: [TAG.PRIORITY_HIGH, '@line-chart', '@d3-chart', '@base-components', '@flex-box'], + }, async ({ page }) => { + await loadPage(page, BASIC_USAGE_STORY, 'en', { + duration: 0, + withReferenceLine: true, + referenceLineArea: area, + }); + await locators.plot(page).waitFor({ state: 'visible' }); + + await test.step('Line and its area are rendered', async () => { + await expect(locators.referenceLine(page)).toHaveCount(1); + await expect(locators.referenceLineArea(page)).toHaveCount(1); + }); + + await test.step(`Area is ${area}px wide and centred on the line`, async () => { + await expectLineAreaWidth(page, area); + }); + + await test.step('Bottom notch is hidden when area is set', async () => { + await expect(locators.referenceLine(page).locator('line')).toHaveCount(2); + }); + }); + }); + + test('Verify reference line without area renders only the line', { + tag: [TAG.PRIORITY_HIGH, '@line-chart', '@d3-chart', '@base-components', '@flex-box'], + }, async ({ page }) => { + await loadPage(page, BASIC_USAGE_STORY, 'en', { duration: 0, withReferenceLine: true }); + await locators.plot(page).waitFor({ state: 'visible' }); + + await test.step('Line keeps both notches', async () => { + await expect(locators.referenceLine(page).locator('line')).toHaveCount(3); + }); + + await test.step('No area shape is rendered', async () => { + await expect(locators.referenceLineArea(page)).toHaveCount(0); + }); + + await test.step('No path in the plot has NaN in its geometry', async () => { + const ds = await locators.plot(page).locator('path').evaluateAll((paths) => + paths.map((path) => path.getAttribute('d') ?? ''), + ); + + expect(ds.filter((d) => d.includes('NaN'))).toEqual([]); + }); + }); + + test('Verify reference area spans from start to end value', { + tag: [TAG.PRIORITY_HIGH, '@line-chart', '@d3-chart', '@base-components', '@flex-box'], + }, async ({ page }) => { + await loadPage(page, BASIC_USAGE_STORY, 'en', { + duration: 0, + withReferenceArea: true, + referenceAreaStart: 8, + referenceAreaEnd: 12, + }); + await locators.plot(page).waitFor({ state: 'visible' }); + + const narrow = await getBox(locators.referenceArea(page)); + + await test.step('Area edges match the x positions of start and end points', async () => { + expect(Math.abs(narrow.x - (await dotCenterX(page, 8)))).toBeLessThanOrEqual(1); + expect(Math.abs(narrow.x + narrow.width - (await dotCenterX(page, 12)))).toBeLessThanOrEqual(1); + }); + + await test.step('Doubling the range doubles the area width', async () => { + await loadPage(page, BASIC_USAGE_STORY, 'en', { + duration: 0, + withReferenceArea: true, + referenceAreaStart: 8, + referenceAreaEnd: 16, + }); + await locators.plot(page).waitFor({ state: 'visible' }); + + const wide = await getBox(locators.referenceArea(page)); + expect(Math.abs(wide.width - narrow.width * 2)).toBeLessThanOrEqual(1); + }); + }); + + ([ + ['neutral', 'gray-50'], + ['good', 'green-50'], + ['bad', 'red-50'], + ['insight', 'violet-50'], + ] as const).forEach(([use, token]) => { + test(`Verify reference area gradient color for use=${use}`, { + tag: [TAG.PRIORITY_MEDIUM, '@line-chart', '@d3-chart', '@base-components', '@flex-box'], + }, async ({ page }) => { + await loadPage(page, BASIC_USAGE_STORY, 'en', { + duration: 0, + withReferenceArea: true, + referenceAreaUse: use, + }); + await locators.plot(page).waitFor({ state: 'visible' }); + + const stops = locators.gradients(page).locator('stop'); + await expect(stops).not.toHaveCount(0); + + const colors = await stops.evaluateAll((elements) => elements.map((stop) => stop.getAttribute('stop-color'))); + colors.forEach((color) => { + expect(color).toContain(`var(--${token}, `); + }); + }); + }); + + test('Verify reference gradients have unique ids', { + tag: [TAG.PRIORITY_HIGH, '@line-chart', '@d3-chart', '@base-components', '@flex-box'], + }, async ({ page }) => { + await loadPage(page, BASIC_USAGE_STORY, 'en', { + duration: 0, + withReferenceLine: true, + referenceLineArea: 40, + withReferenceArea: true, + referenceAreaUse: 'bad', + }); + await locators.plot(page).waitFor({ state: 'visible' }); + + const ids = await locators.gradients(page).evaluateAll((elements) => elements.map((gradient) => gradient.id)); + + await test.step('Line and area each have their own gradient', async () => { + expect(ids).toHaveLength(2); + expect(new Set(ids).size).toBe(ids.length); + }); + + await test.step('No gradient id is built from an undefined uid', async () => { + expect(ids.filter((id) => id.startsWith('undefined'))).toEqual([]); + }); + + await test.step('Every reference shape points to an existing gradient', async () => { + const fills = await locators.referenceShapes(page).evaluateAll((paths) => + paths.map((path) => path.getAttribute('fill')), + ); + + expect(fills).toHaveLength(2); + fills.forEach((fill) => { + expect(ids.map((id) => `url(#${id})`)).toContain(fill); + }); + }); + }); + + ([ + { title: '', subTitle: '' }, + { title: SHORT_TITLE, subTitle: '' }, + { title: '', subTitle: SUB_TITLE }, + { title: SHORT_TITLE, subTitle: SUB_TITLE }, + ]).forEach(({ title, subTitle }) => { + test(`Verify reference area texts: title="${title}" subTitle="${subTitle}"`, { + tag: [TAG.PRIORITY_MEDIUM, '@line-chart', '@d3-chart', '@base-components', '@flex-box'], + }, async ({ page }) => { + await loadPage(page, BASIC_USAGE_STORY, 'en', { + duration: 0, + withReferenceArea: true, + referenceAreaStart: 8, + referenceAreaEnd: 12, + referenceAreaTitle: title, + referenceAreaSubTitle: subTitle, + }); + await locators.plot(page).waitFor({ state: 'visible' }); + + const area = await getSvgBox(locators.referenceArea(page)); + + for (const [text, isSet] of [[SHORT_TITLE, Boolean(title)], [SUB_TITLE, Boolean(subTitle)]] as const) { + await test.step(`"${text}" is ${isSet ? 'rendered inside the area' : 'not rendered'}`, async () => { + const node = locators.plotText(page, text); + + if (!isSet) { + await expect(node).toHaveCount(0); + return; + } + + await expect(node).toHaveCount(1); + const box = await getSvgBox(node); + expect(box.x).toBeGreaterThanOrEqual(area.x); + expect(box.x).toBeLessThan(area.x + area.width); + }); + } + }); + }); + + test('Verify reference shapes are hidden from assistive technology', { + tag: [TAG.PRIORITY_MEDIUM, TAG.ACCESSIBILITY, '@line-chart', '@d3-chart', '@base-components', '@flex-box'], + }, async ({ page }) => { + await loadPage(page, BASIC_USAGE_STORY, 'en', { + duration: 0, + withReferenceLine: true, + referenceLineArea: 40, + withReferenceArea: true, + }); + await locators.plot(page).waitFor({ state: 'visible' }); + + await test.step('Reference line is hidden', async () => { + await expectEachToBeHiddenFromA11y(locators.referenceLine(page)); + }); + + await test.step('Reference area is hidden', async () => { + await expectEachToBeHiddenFromA11y(locators.referenceArea(page)); + }); + + await test.step('Reference line area is hidden', async () => { + await expectEachToBeHiddenFromA11y(locators.referenceLineArea(page)); + }); + }); + + test('Verify tooltip appears when hovering inside the reference area', { + tag: [TAG.PRIORITY_MEDIUM, TAG.MOUSE, '@line-chart', '@d3-chart', '@base-components', '@flex-box'], + }, async ({ page }) => { + await loadPage(page, BASIC_USAGE_STORY, 'en', { + duration: 0, + withReferenceLine: true, + referenceLineValue: 10, + referenceLineArea: 40, + withReferenceArea: true, + referenceAreaStart: 8, + referenceAreaEnd: 12, + }); + await locators.plot(page).waitFor({ state: 'visible' }); + + const area = await getBox(locators.referenceArea(page)); + await page.mouse.move(area.x + area.width / 4, area.y + area.height / 2); + + await expect(locators.tooltip(page)).toBeVisible(); + }); + + test('Verify reference elements are not focusable', { + tag: [TAG.PRIORITY_LOW, TAG.KEYBOARD, '@line-chart', '@d3-chart', '@base-components', '@flex-box'], + }, async ({ page }) => { + await loadPage(page, BASIC_USAGE_STORY, 'en', { + duration: 0, + withReferenceLine: true, + referenceLineArea: 40, + withReferenceArea: true, + referenceAreaTitle: SHORT_TITLE, + }); + await locators.plot(page).waitFor({ state: 'visible' }); + + const focusable = await page + .locator('[data-ui-name="ReferenceLine"], [data-ui-name="ReferenceLine"] *, path[fill$="-pattern)"], svg[data-ui-name="Plot"] text') + .evaluateAll((elements) => elements.filter((element) => element.hasAttribute('tabindex')).length); + + expect(focusable).toBe(0); + }); + + test('Verify a single-item array renders like a single reference line', { + tag: [TAG.PRIORITY_MEDIUM, '@line-chart', '@d3-chart', '@base-components', '@flex-box'], + }, async ({ page }) => { + const props = { duration: 0, withReferenceLine: true, referenceLineValue: 10, referenceLineArea: 40 }; + + await loadPage(page, BASIC_USAGE_STORY, 'en', props); + await locators.plot(page).waitFor({ state: 'visible' }); + const objectArea = await getBox(locators.referenceLineArea(page)); + + await loadPage(page, BASIC_USAGE_STORY, 'en', { ...props, referenceLineCount: 1 }); + await locators.plot(page).waitFor({ state: 'visible' }); + + await test.step('One line and one area are rendered', async () => { + await expect(locators.referenceLine(page)).toHaveCount(1); + await expect(locators.referenceLineArea(page)).toHaveCount(1); + }); + + await test.step('Area has the same position and size', async () => { + const arrayArea = await getBox(locators.referenceLineArea(page)); + + expect(Math.abs(arrayArea.x - objectArea.x)).toBeLessThanOrEqual(1); + expect(Math.abs(arrayArea.width - objectArea.width)).toBeLessThanOrEqual(1); + }); + }); +}); diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-line-and-area-on-a-time-axis-1-chromium-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-line-and-area-on-a-time-axis-1-chromium-linux.png new file mode 100644 index 0000000000..85806335a2 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-line-and-area-on-a-time-axis-1-chromium-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-line-and-area-on-a-time-axis-1-firefox-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-line-and-area-on-a-time-axis-1-firefox-linux.png new file mode 100644 index 0000000000..20078976df Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-line-and-area-on-a-time-axis-1-firefox-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-line-and-area-on-a-time-axis-1-webkit-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-line-and-area-on-a-time-axis-1-webkit-linux.png new file mode 100644 index 0000000000..29c5f663be Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-line-and-area-on-a-time-axis-1-webkit-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-line-with-area-52-1-chromium-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-line-with-area-52-1-chromium-linux.png new file mode 100644 index 0000000000..f91a25ab3c Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-line-with-area-52-1-chromium-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-line-with-area-52-1-firefox-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-line-with-area-52-1-firefox-linux.png new file mode 100644 index 0000000000..6a734baaa5 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-line-with-area-52-1-firefox-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-line-with-area-52-1-webkit-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-line-with-area-52-1-webkit-linux.png new file mode 100644 index 0000000000..266a8c43da Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-line-with-area-52-1-webkit-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-1-bad-middle-no-titles-1-chromium-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-1-bad-middle-no-titles-1-chromium-linux.png new file mode 100644 index 0000000000..4a8b4b6c67 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-1-bad-middle-no-titles-1-chromium-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-1-bad-middle-no-titles-1-firefox-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-1-bad-middle-no-titles-1-firefox-linux.png new file mode 100644 index 0000000000..898d31ea18 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-1-bad-middle-no-titles-1-firefox-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-1-bad-middle-no-titles-1-webkit-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-1-bad-middle-no-titles-1-webkit-linux.png new file mode 100644 index 0000000000..e7854a061a Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-1-bad-middle-no-titles-1-webkit-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-10-bad-right-title-plain-line-outside-narrow-1-chromium-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-10-bad-right-title-plain-line-outside-narrow-1-chromium-linux.png new file mode 100644 index 0000000000..3c7da6347e Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-10-bad-right-title-plain-line-outside-narrow-1-chromium-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-10-bad-right-title-plain-line-outside-narrow-1-firefox-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-10-bad-right-title-plain-line-outside-narrow-1-firefox-linux.png new file mode 100644 index 0000000000..11b21892c3 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-10-bad-right-title-plain-line-outside-narrow-1-firefox-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-10-bad-right-title-plain-line-outside-narrow-1-webkit-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-10-bad-right-title-plain-line-outside-narrow-1-webkit-linux.png new file mode 100644 index 0000000000..c971d76cae Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-10-bad-right-title-plain-line-outside-narrow-1-webkit-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-11-insight-right-no-titles-1-chromium-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-11-insight-right-no-titles-1-chromium-linux.png new file mode 100644 index 0000000000..55aa5215bc Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-11-insight-right-no-titles-1-chromium-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-11-insight-right-no-titles-1-firefox-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-11-insight-right-no-titles-1-firefox-linux.png new file mode 100644 index 0000000000..c48bf1d94d Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-11-insight-right-no-titles-1-firefox-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-11-insight-right-no-titles-1-webkit-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-11-insight-right-no-titles-1-webkit-linux.png new file mode 100644 index 0000000000..fed8e5fd87 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-11-insight-right-no-titles-1-webkit-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-12-good-middle-long-title-subTitle-narrow-1-chromium-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-12-good-middle-long-title-subTitle-narrow-1-chromium-linux.png new file mode 100644 index 0000000000..1add30261e Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-12-good-middle-long-title-subTitle-narrow-1-chromium-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-12-good-middle-long-title-subTitle-narrow-1-firefox-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-12-good-middle-long-title-subTitle-narrow-1-firefox-linux.png new file mode 100644 index 0000000000..7416d48b6c Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-12-good-middle-long-title-subTitle-narrow-1-firefox-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-12-good-middle-long-title-subTitle-narrow-1-webkit-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-12-good-middle-long-title-subTitle-narrow-1-webkit-linux.png new file mode 100644 index 0000000000..f51666eedf Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-12-good-middle-long-title-subTitle-narrow-1-webkit-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-12-good-middle-titles-narrow-1-chromium-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-12-good-middle-titles-narrow-1-chromium-linux.png new file mode 100644 index 0000000000..9325bb7180 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-12-good-middle-titles-narrow-1-chromium-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-12-good-middle-titles-narrow-1-firefox-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-12-good-middle-titles-narrow-1-firefox-linux.png new file mode 100644 index 0000000000..dc76fa0d0d Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-12-good-middle-titles-narrow-1-firefox-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-12-good-middle-titles-narrow-1-webkit-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-12-good-middle-titles-narrow-1-webkit-linux.png new file mode 100644 index 0000000000..36f53fea8d Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-12-good-middle-titles-narrow-1-webkit-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-13-neutral-left-subTitle-only-line-area-outside-1-chromium-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-13-neutral-left-subTitle-only-line-area-outside-1-chromium-linux.png new file mode 100644 index 0000000000..84283232d4 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-13-neutral-left-subTitle-only-line-area-outside-1-chromium-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-13-neutral-left-subTitle-only-line-area-outside-1-firefox-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-13-neutral-left-subTitle-only-line-area-outside-1-firefox-linux.png new file mode 100644 index 0000000000..4f3f779aa8 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-13-neutral-left-subTitle-only-line-area-outside-1-firefox-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-13-neutral-left-subTitle-only-line-area-outside-1-webkit-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-13-neutral-left-subTitle-only-line-area-outside-1-webkit-linux.png new file mode 100644 index 0000000000..a7a78b753b Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-13-neutral-left-subTitle-only-line-area-outside-1-webkit-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-2-good-right-titles-line-area-inside-1-chromium-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-2-good-right-titles-line-area-inside-1-chromium-linux.png new file mode 100644 index 0000000000..10fac98bef Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-2-good-right-titles-line-area-inside-1-chromium-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-2-good-right-titles-line-area-inside-1-firefox-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-2-good-right-titles-line-area-inside-1-firefox-linux.png new file mode 100644 index 0000000000..181bc4e01a Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-2-good-right-titles-line-area-inside-1-firefox-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-2-good-right-titles-line-area-inside-1-webkit-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-2-good-right-titles-line-area-inside-1-webkit-linux.png new file mode 100644 index 0000000000..c2c4f3d091 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-2-good-right-titles-line-area-inside-1-webkit-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-3-insight-left-titles-plain-line-outside-narrow-1-chromium-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-3-insight-left-titles-plain-line-outside-narrow-1-chromium-linux.png new file mode 100644 index 0000000000..efdad76223 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-3-insight-left-titles-plain-line-outside-narrow-1-chromium-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-3-insight-left-titles-plain-line-outside-narrow-1-firefox-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-3-insight-left-titles-plain-line-outside-narrow-1-firefox-linux.png new file mode 100644 index 0000000000..7c572971ae Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-3-insight-left-titles-plain-line-outside-narrow-1-firefox-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-3-insight-left-titles-plain-line-outside-narrow-1-webkit-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-3-insight-left-titles-plain-line-outside-narrow-1-webkit-linux.png new file mode 100644 index 0000000000..bb38600c8e Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-3-insight-left-titles-plain-line-outside-narrow-1-webkit-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-4-neutral-right-long-title-narrow-1-chromium-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-4-neutral-right-long-title-narrow-1-chromium-linux.png new file mode 100644 index 0000000000..5c001053ea Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-4-neutral-right-long-title-narrow-1-chromium-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-4-neutral-right-long-title-narrow-1-firefox-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-4-neutral-right-long-title-narrow-1-firefox-linux.png new file mode 100644 index 0000000000..1b0179ed86 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-4-neutral-right-long-title-narrow-1-firefox-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-4-neutral-right-long-title-narrow-1-webkit-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-4-neutral-right-long-title-narrow-1-webkit-linux.png new file mode 100644 index 0000000000..bcb129d317 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-4-neutral-right-long-title-narrow-1-webkit-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-4-neutral-right-title-narrow-1-chromium-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-4-neutral-right-title-narrow-1-chromium-linux.png new file mode 100644 index 0000000000..b02fbb5964 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-4-neutral-right-title-narrow-1-chromium-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-4-neutral-right-title-narrow-1-firefox-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-4-neutral-right-title-narrow-1-firefox-linux.png new file mode 100644 index 0000000000..70ea49ed58 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-4-neutral-right-title-narrow-1-firefox-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-4-neutral-right-title-narrow-1-webkit-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-4-neutral-right-title-narrow-1-webkit-linux.png new file mode 100644 index 0000000000..1b0e3fc433 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-4-neutral-right-title-narrow-1-webkit-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-5-neutral-middle-subTitle-only-plain-line-inside-1-chromium-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-5-neutral-middle-subTitle-only-plain-line-inside-1-chromium-linux.png new file mode 100644 index 0000000000..fa8a83c745 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-5-neutral-middle-subTitle-only-plain-line-inside-1-chromium-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-5-neutral-middle-subTitle-only-plain-line-inside-1-firefox-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-5-neutral-middle-subTitle-only-plain-line-inside-1-firefox-linux.png new file mode 100644 index 0000000000..60f56dfe08 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-5-neutral-middle-subTitle-only-plain-line-inside-1-firefox-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-5-neutral-middle-subTitle-only-plain-line-inside-1-webkit-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-5-neutral-middle-subTitle-only-plain-line-inside-1-webkit-linux.png new file mode 100644 index 0000000000..65df2bb8a7 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-5-neutral-middle-subTitle-only-plain-line-inside-1-webkit-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-6-insight-middle-title-line-area-outside-narrow-1-chromium-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-6-insight-middle-title-line-area-outside-narrow-1-chromium-linux.png new file mode 100644 index 0000000000..04b35622bc Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-6-insight-middle-title-line-area-outside-narrow-1-chromium-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-6-insight-middle-title-line-area-outside-narrow-1-firefox-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-6-insight-middle-title-line-area-outside-narrow-1-firefox-linux.png new file mode 100644 index 0000000000..5d8a18f7e0 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-6-insight-middle-title-line-area-outside-narrow-1-firefox-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-6-insight-middle-title-line-area-outside-narrow-1-webkit-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-6-insight-middle-title-line-area-outside-narrow-1-webkit-linux.png new file mode 100644 index 0000000000..0a28b997c5 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-6-insight-middle-title-line-area-outside-narrow-1-webkit-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-7-good-left-no-titles-plain-line-inside-narrow-1-chromium-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-7-good-left-no-titles-plain-line-inside-narrow-1-chromium-linux.png new file mode 100644 index 0000000000..cd41e1bed9 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-7-good-left-no-titles-plain-line-inside-narrow-1-chromium-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-7-good-left-no-titles-plain-line-inside-narrow-1-firefox-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-7-good-left-no-titles-plain-line-inside-narrow-1-firefox-linux.png new file mode 100644 index 0000000000..fa70e7e3d8 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-7-good-left-no-titles-plain-line-inside-narrow-1-firefox-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-7-good-left-no-titles-plain-line-inside-narrow-1-webkit-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-7-good-left-no-titles-plain-line-inside-narrow-1-webkit-linux.png new file mode 100644 index 0000000000..3c10d3bfd3 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-7-good-left-no-titles-plain-line-inside-narrow-1-webkit-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-8-bad-left-long-title-subTitle-line-area-inside-1-chromium-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-8-bad-left-long-title-subTitle-line-area-inside-1-chromium-linux.png new file mode 100644 index 0000000000..d434a9dcbf Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-8-bad-left-long-title-subTitle-line-area-inside-1-chromium-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-8-bad-left-long-title-subTitle-line-area-inside-1-firefox-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-8-bad-left-long-title-subTitle-line-area-inside-1-firefox-linux.png new file mode 100644 index 0000000000..e6ea2ec83e Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-8-bad-left-long-title-subTitle-line-area-inside-1-firefox-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-8-bad-left-long-title-subTitle-line-area-inside-1-webkit-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-8-bad-left-long-title-subTitle-line-area-inside-1-webkit-linux.png new file mode 100644 index 0000000000..9cd55ca66c Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-8-bad-left-long-title-subTitle-line-area-inside-1-webkit-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-8-bad-left-titles-line-area-inside-1-chromium-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-8-bad-left-titles-line-area-inside-1-chromium-linux.png new file mode 100644 index 0000000000..dbb12f8906 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-8-bad-left-titles-line-area-inside-1-chromium-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-8-bad-left-titles-line-area-inside-1-firefox-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-8-bad-left-titles-line-area-inside-1-firefox-linux.png new file mode 100644 index 0000000000..8d5484bb35 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-8-bad-left-titles-line-area-inside-1-firefox-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-8-bad-left-titles-line-area-inside-1-webkit-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-8-bad-left-titles-line-area-inside-1-webkit-linux.png new file mode 100644 index 0000000000..a4ce7eeec6 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-8-bad-left-titles-line-area-inside-1-webkit-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-9-neutral-left-titles-1-chromium-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-9-neutral-left-titles-1-chromium-linux.png new file mode 100644 index 0000000000..02528b6b99 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-9-neutral-left-titles-1-chromium-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-9-neutral-left-titles-1-firefox-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-9-neutral-left-titles-1-firefox-linux.png new file mode 100644 index 0000000000..f16ea15214 Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-9-neutral-left-titles-1-firefox-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-9-neutral-left-titles-1-webkit-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-9-neutral-left-titles-1-webkit-linux.png new file mode 100644 index 0000000000..a44253c32f Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-reference-pairwise-9-neutral-left-titles-1-webkit-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-several-reference-lines-passed-as-an-array-1-chromium-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-several-reference-lines-passed-as-an-array-1-chromium-linux.png new file mode 100644 index 0000000000..0d2b5dcd9a Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-several-reference-lines-passed-as-an-array-1-chromium-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-several-reference-lines-passed-as-an-array-1-firefox-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-several-reference-lines-passed-as-an-array-1-firefox-linux.png new file mode 100644 index 0000000000..a143c70bbf Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-several-reference-lines-passed-as-an-array-1-firefox-linux.png differ diff --git a/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-several-reference-lines-passed-as-an-array-1-webkit-linux.png b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-several-reference-lines-passed-as-an-array-1-webkit-linux.png new file mode 100644 index 0000000000..cfa4bc420e Binary files /dev/null and b/semcore/d3-chart/__tests__/line-chart-reference.browser-test.tsx-snapshots/-visual-Verify-several-reference-lines-passed-as-an-array-1-webkit-linux.png differ diff --git a/semcore/d3-chart/src/Reference.jsx b/semcore/d3-chart/src/Reference.jsx index 1bb41295da..2a01c7c04f 100644 --- a/semcore/d3-chart/src/Reference.jsx +++ b/semcore/d3-chart/src/Reference.jsx @@ -2,6 +2,7 @@ import { Component, sstyled } from '@semcore/core'; import uniqueIDEnhancement from '@semcore/core/lib/utils/uniqueID'; import React from 'react'; +import { SvgElement } from './component/SvgElement'; import createElement from './createElement'; import style from './style/reference.shadow.css'; import { scaleOfBandwidth } from './utils'; @@ -132,6 +133,8 @@ class ReferenceLineRoot extends Component { position: 'left', }; + static enhance = [uniqueIDEnhancement()]; + getTitleProps() { const { position, value } = this.asProps; return { position, value }; @@ -144,12 +147,29 @@ class ReferenceLineRoot extends Component { render() { const SReferenceLine = this.Element; - const { title, scale, position, value, color, resolveColor, styles } = this.asProps; + const SArea = SvgElement; + const { title, scale, position, value, color, resolveColor, styles, uid, area } = this.asProps; const positionProps = lineDirection2props[side2direction[position]]; const { notchFirst, notchLast, ...line } = positionProps(scale, value); + const patternId = `${uid}-pattern`; return sstyled(styles)( <> + {area && ( + + + + {getColorByUse('neutral', resolveColor)} + + + + + + )} - + {!area && ()} {title && {title}} , @@ -186,42 +206,104 @@ function Title(props) { />, ); } -function Background(props) { - const { Element: SBackground, styles, scale, position = 'left', value, endValue } = props; - const positionProps = rectDirection2props[side2direction[position]]; - return sstyled(styles)( - , - ); +function getColorByUse(use, resolveColor) { + switch (use) { + case 'bad': { + return ( + <> + + + + + ); + } + case 'good': { + return ( + <> + + + + + ); + } + case 'insight': { + return ( + <> + + + + + ); + } + default: { + return ( + <> + + + + + ); + } + } +} + +function getReferenceAreaPath({ x, y, width, height }) { + const r = 12; + + const path = `M ${x},${y + r} Q ${x},${y} ${x + r},${y} H ${x + width - r} Q ${x + width},${y} ${x + width},${y + r} V ${y + height} H ${x} Z`; + + return path; } -Background.style = style; -const diagonalGap = 8; -const gap = Math.sqrt(diagonalGap ** 2 + diagonalGap ** 2); -const gap12 = gap * (1 / 2); -const gap32 = gap * (3 / 2); -const path = `M-${gap},-${gap12} L${gap},${gap32} M-${gap12},-${gap} L${gap32},${gap}`; function Stripes(props) { - const { Element: SStripes, styles, scale, position = 'left', value, endValue, uid } = props; - const SStripesPatternPath = 'path'; - const positionProps = rectDirection2props[side2direction[position]]; + const { Element: SStripes, styles, scale, position = 'left', value, endValue, uid, use = 'neutral', title, subTitle, resolveColor } = props; + const positionProps = rectDirection2props[side2direction[position]](scale, value, endValue); const patternId = `${uid}-pattern`; + const STitle = SvgElement; + const SSubTitle = SvgElement; + + const textX = positionProps.x + 6; + const textY = positionProps.y + 6; return sstyled(styles)( + + + {getColorByUse(use, resolveColor)} + + + - - - + + {title && ( + + {title} + + )} + + {subTitle && ( + + {subTitle} + + )} , ); } @@ -230,9 +312,9 @@ Stripes.enhance = [uniqueIDEnhancement()]; export const ReferenceLine = createElement(ReferenceLineRoot, { Title, - Background, + Background: Stripes, Stripes, }); -export const ReferenceBackground = createElement(Background); +export const ReferenceBackground = createElement(Stripes); export const ReferenceStripes = createElement(Stripes); diff --git a/semcore/d3-chart/src/component/Chart/AbstractChart.tsx b/semcore/d3-chart/src/component/Chart/AbstractChart.tsx index d18a5a3157..1d0913dfbb 100644 --- a/semcore/d3-chart/src/component/Chart/AbstractChart.tsx +++ b/semcore/d3-chart/src/component/Chart/AbstractChart.tsx @@ -659,6 +659,10 @@ export abstract class AbstractChart< ); } + protected renderReference(): React.ReactNode { + return null; + } + public render() { const SChart = Root; const { styles, data, patterns, a11yAltTextConfig, duration, eventEmitter, showTooltip, locale } = @@ -684,6 +688,7 @@ export abstract class AbstractChart< {...extractedAriaProps} > {this.renderAxis()} + {this.renderReference()} {!showTooltip ? null : this.renderTooltip()} {this.renderChart()} diff --git a/semcore/d3-chart/src/component/Chart/LineChart.tsx b/semcore/d3-chart/src/component/Chart/LineChart.tsx index da0f002a56..e9cbdb8521 100644 --- a/semcore/d3-chart/src/component/Chart/LineChart.tsx +++ b/semcore/d3-chart/src/component/Chart/LineChart.tsx @@ -7,7 +7,7 @@ import type { ObjectData } from './AbstractChart.type'; import { HIGHLIGHT_DOT } from './AbstractChart.type'; import type { LineChartData, LineChartDefaultProps, LineChartProps, LineChartType } from './LineChart.type'; // @ts-ignore -import { Line, minMax, HoverLine } from '../..'; +import { Line, minMax, HoverLine, ReferenceLine, ReferenceStripes } from '../..'; import type { ChartState } from './AbstractChart'; import { AbstractChart } from './AbstractChart'; import { localizedMessages } from '../../translations/__intergalactic-dynamic-locales'; @@ -116,6 +116,36 @@ class LineChartComponent extends AbstractChart< ); } + protected renderReference() { + const { referenceLine, referenceArea } = this.asProps; + + if (!referenceLine && !referenceArea) { + return null; + } + + return ( + <> + {referenceLine && ( + Array.isArray(referenceLine) + ? referenceLine.map((refLineItem) => { + return (); + }) + : () + )} + + {referenceArea && ( + + )} + + ); + } + protected getLegendAriaLabel(): string { return this.asProps.getI18nText('legendForChart', { chartType: 'Line' }); } diff --git a/semcore/d3-chart/src/component/Chart/LineChart.type.ts b/semcore/d3-chart/src/component/Chart/LineChart.type.ts index ac2413752b..3ed4b002d3 100644 --- a/semcore/d3-chart/src/component/Chart/LineChart.type.ts +++ b/semcore/d3-chart/src/component/Chart/LineChart.type.ts @@ -15,6 +15,37 @@ type AreaItem = { export type LineChartData = Array>; +type ReferenceLine = { + /** + * Simple reference line. + */ + value: string | number | Date; + + /** + * Size of area near line + */ + area?: number; +}; + +type ReferenceArea = { + /** + * Reference line with area. + */ + value: [string | number | Date, string | number | Date]; + /** + * @default neutral. + */ + use?: 'neutral' | 'insight' | 'good' | 'bad'; + /** + * Title of the area. + */ + title?: string; + /** + * Custom subtitle with data. + */ + subTitle?: string; +}; + export type LineChartProps = BaseChartProps & { /** Field name that groups the data points */ groupKey: string; @@ -32,6 +63,14 @@ export type LineChartProps = BaseChartProps & { areaCurve?: CurveFactory; /** Callback triggered when a user clicks on a line */ onClickLine?: (index: number, event: React.SyntheticEvent) => void; + /** + * Settings for render reference line. + */ + referenceLine?: ReferenceLine | ReferenceLine[]; + /** + * Settings for render reference area. + */ + referenceArea?: ReferenceArea; }; export type LineChartDefaultProps = { diff --git a/semcore/d3-chart/src/style/reference.shadow.css b/semcore/d3-chart/src/style/reference.shadow.css index 03132f29c1..53255d5cdf 100644 --- a/semcore/d3-chart/src/style/reference.shadow.css +++ b/semcore/d3-chart/src/style/reference.shadow.css @@ -6,11 +6,10 @@ SReferenceLine { STitle { font-size: var(--intergalactic-fs-100, 12px); fill: var(--intergalactic-chart-grid-text-label, oklch(from oklch(0.182 0.045 244.8 / 0.593) l c h / 0.4)); - transform-origin: var(--transform-origin); } STitle[position='top'] { - text-anchor: middle; + dominant-baseline: hanging; } STitle[position='bottom'] { @@ -30,14 +29,12 @@ STitle[position='left'] { dominant-baseline: middle; } -SBackground { - fill: var(--intergalactic-chart-grid-period-bg, oklch(0.96 0.005 232.5)); -} -SStripes { - fill: var(--fill); +SSubTitle { + font-size: var(--intergalactic-fs-100, 12px); + fill: var(--intergalactic-chart-grid-text-label-accent, oklch(0.102 0.021 230.9 / 0.9)); + font-weight: bold; } -SStripesPatternPath { - stroke: var(--intergalactic-chart-grid-period-pattern, oklch(0.95 0.006 232.7)); - stroke-width: 1px; +SBackground { + fill: var(--intergalactic-chart-grid-period-bg, oklch(0.96 0.005 232.5)); } diff --git a/semcore/d3-chart/src/types/Reference.d.ts b/semcore/d3-chart/src/types/Reference.d.ts index 87f036defa..468b29d311 100644 --- a/semcore/d3-chart/src/types/Reference.d.ts +++ b/semcore/d3-chart/src/types/Reference.d.ts @@ -6,12 +6,18 @@ import type { IntergalacticD3Component } from './Plot'; /** @deprecated **/ export interface IReferenceLineProps extends ReferenceLineProps, UnknownProperties {} export type ReferenceLineProps = Context & { - /** The position of the title relative reference line - * @default 'left' */ + /** + * The position of the title relative reference line + * @default 'left' + * @deprecated use ReferenceArea if you need a title. + */ position?: 'top' | 'right' | 'bottom' | 'left'; /** Value element of data */ value?: any; - /** Reference line title */ + /** + * Reference line title + * @deprecated use ReferenceArea if you need title. + */ title?: string; }; @@ -47,23 +53,34 @@ export type ReferenceStripesProps = Context & { /** Value of the background end */ endValue?: number | string; }; - +/** + * @deprecated use `referenceLine` property on Chart.Line. + */ export declare const ReferenceLine: IntergalacticD3Component< 'line', ReferenceLineProps, Context > & { + /** + * @deprecated use `referenceArea` property on Chart.Line with title property + */ Title: IntergalacticD3Component<'text', ReferenceLineTitleProps, Context>; /** * @deprecated use `ReferenceBackground` instead. */ Background: IntergalacticD3Component<'rect', ReferenceLineBackgroundProps, Context>; }; +/** + * @deprecated use `referenceArea` property on Chart.Line. + */ export declare const ReferenceBackground: IntergalacticD3Component< 'rect', ReferenceLineBackgroundProps, Context >; +/** + * @deprecated use `referenceArea` property on Chart.Line. + */ export declare const ReferenceStripes: IntergalacticD3Component< 'rect', ReferenceStripesProps, diff --git a/stories/components/d3-chart/__mocks__/line.ts b/stories/components/d3-chart/__mocks__/line.ts index aff40efad2..99e4a03873 100644 --- a/stories/components/d3-chart/__mocks__/line.ts +++ b/stories/components/d3-chart/__mocks__/line.ts @@ -139,6 +139,14 @@ export default { { time: new Date(2025, 1, 9), line: 0 }, { time: new Date(2025, 1, 14), line: 5 }, ], + Months: [ + { time: new Date(2025, 0, 1), line: 8000 }, + { time: new Date(2025, 1, 1), line: 14000 }, + { time: new Date(2025, 2, 1), line: 11000 }, + { time: new Date(2025, 3, 1), line: 19000 }, + { time: new Date(2025, 4, 1), line: 22000 }, + { time: new Date(2025, 5, 1), line: 16000 }, + ], Area: [ { x: 0, y: 2, y0: 4, y1: 0 }, { x: 1, y: 4, y0: 6, y1: 2 }, diff --git a/stories/components/d3-chart/docs/examples/d3-chart/reference-line.tsx b/stories/components/d3-chart/docs/examples/d3-chart/reference-line.tsx index cc02bbf7f3..23a7a8fe05 100644 --- a/stories/components/d3-chart/docs/examples/d3-chart/reference-line.tsx +++ b/stories/components/d3-chart/docs/examples/d3-chart/reference-line.tsx @@ -1,49 +1,55 @@ -import { - Plot, - ReferenceLine, - ReferenceStripes, - ReferenceBackground, - XAxis, - YAxis, -} from '@semcore/ui/d3-chart'; -import { scaleLinear, scaleBand } from 'd3-scale'; +import { Chart } from '@semcore/ui/d3-chart'; +import { scaleLinear, scaleTime } from 'd3-scale'; import React from 'react'; -import BarMockData from '../../../__mocks__/bar'; +import LineMockData from '../../../__mocks__/line'; + +const data = LineMockData.Months; + +const monthCenter = (date: Date) => new Date(date.getFullYear(), date.getMonth(), 15); + +const valueFormatter = (value: unknown) => { + if (typeof value === 'number') { + return value === 0 ? '0' : `${value / 1000}K`; + } + + return null; +}; const Demo = () => { - const MARGIN = 40; + const MARGIN = { top: 28, right: 0, bottom: 32, left: 46 }; const width = 500; - const height = 300; + const height = 220; + const plotWidth = width - MARGIN.left - MARGIN.right; + const monthWidth = plotWidth / data.length; + const lastMonth = data[data.length - 1].time; - const xScale = scaleBand() - .range([MARGIN, width - MARGIN]) - .domain(dataBar.map((d) => d.category)) - .paddingInner(0.4) - .paddingOuter(0.2); + const xScale = scaleTime() + .range([MARGIN.left, width - MARGIN.right]) + .domain([data[0].time, lastMonth]); const yScale = scaleLinear() - .range([height - MARGIN, MARGIN]) - .domain([0, 10]); + .range([height - MARGIN.bottom, MARGIN.top]) + .domain([0, 30000]); return ( - - - - - - - - - - - - - - + ); }; -const dataBar = BarMockData.Default; - export default Demo; diff --git a/stories/components/d3-chart/tests/d3-chart-base.stories.tsx b/stories/components/d3-chart/tests/d3-chart-base.stories.tsx index fcd8081a09..83ff6d6fd8 100644 --- a/stories/components/d3-chart/tests/d3-chart-base.stories.tsx +++ b/stories/components/d3-chart/tests/d3-chart-base.stories.tsx @@ -57,7 +57,12 @@ export const GridAxisProps: StoryObj = { args: BasicUsageProps, }; +/** + * Covers only deprecated `Reference*` components. Use `referenceLine` / `referenceArea` + * on `Chart.Line` instead. + */ export const ReferenceLineProps: StoryObj = { + name: 'Reference Line Props (deprecated)', render: ReferenceLinePropsExample, }; diff --git a/stories/components/d3-chart/tests/examples/line-chart/basic-usage.tsx b/stories/components/d3-chart/tests/examples/line-chart/basic-usage.tsx index 7d5f762060..884f412e1d 100644 --- a/stories/components/d3-chart/tests/examples/line-chart/basic-usage.tsx +++ b/stories/components/d3-chart/tests/examples/line-chart/basic-usage.tsx @@ -32,6 +32,24 @@ type LineChartStoryProps = LineChartProps & { */ deltaOverride?: 'off' | keyof typeof deltaOverrides; withInterpolatedGaps?: boolean; + + withReferenceLine?: boolean; + withReferenceArea?: boolean; + + referenceLineValue?: number; + referenceLineArea?: number; + /** + * Number of reference lines, passed as an array and spaced 5 points apart from + * `referenceLineValue`. Unset keeps the single-object form. + */ + referenceLineCount?: number; + /** Puts every line from `referenceLineCount` on the same value instead of 5 points apart. */ + referenceLinesOverlap?: boolean; + referenceAreaStart?: number; + referenceAreaEnd?: number; + referenceAreaUse?: 'neutral' | 'insight' | 'good' | 'bad'; + referenceAreaTitle?: string; + referenceAreaSubTitle?: string; }; /** @@ -110,6 +128,17 @@ const Demo = (props: LineChartStoryProps) => { titleFormat, deltaOverride, withInterpolatedGaps, + withReferenceLine, + withReferenceArea, + referenceLineValue, + referenceLineArea, + referenceLineCount, + referenceLinesOverlap, + referenceAreaStart, + referenceAreaEnd, + referenceAreaUse, + referenceAreaTitle, + referenceAreaSubTitle, ...chartProps } = getPropsToChart(props); @@ -155,6 +184,26 @@ const Demo = (props: LineChartStoryProps) => { ...(getPercentDelta ? { getPercentDelta } : {}), }; + if (withReferenceLine) { + const firstValue = referenceLineValue ?? 3; + const step = referenceLinesOverlap ? 0 : 5; + + responsiveChartProps.referenceLine = referenceLineCount + ? Array.from({ length: referenceLineCount }, (_, i) => ({ value: firstValue + i * step, area: referenceLineArea })) + : { value: firstValue, area: referenceLineArea }; + } + + if (withReferenceArea) { + const use = referenceAreaUse ?? 'insight' as const; + + responsiveChartProps.referenceArea = { + value: [referenceAreaStart ?? 12, referenceAreaEnd ?? 16], + use, + title: referenceAreaTitle || undefined, + subTitle: referenceAreaSubTitle || undefined, + }; + } + const showResponsiveInfo = aspect || hMin || hMax || useExplicitPlotWidth; return ( @@ -193,6 +242,14 @@ export const defaultProps = getChartProps({ withInterpolatedGaps: false, titleFormat: 'off', deltaOverride: 'off', + withReferenceLine: false, + withReferenceArea: false, + referenceLineValue: 3, + referenceLinesOverlap: false, + referenceAreaStart: 12, + referenceAreaEnd: 16, + referenceAreaTitle: '', + referenceAreaSubTitle: '', }); Demo.defaultProps = defaultProps; diff --git a/stories/components/d3-chart/tests/line-chart.stories.tsx b/stories/components/d3-chart/tests/line-chart.stories.tsx index 195e827e19..a07cab5898 100644 --- a/stories/components/d3-chart/tests/line-chart.stories.tsx +++ b/stories/components/d3-chart/tests/line-chart.stories.tsx @@ -31,6 +31,11 @@ export const Lines: StoryObj = { */ const storyKnob = { table: { category: 'Story data knobs' } } as const; +/** + * Knobs that build the `referenceLine` / `referenceArea` objects passed to `LineChart`. + */ +const referenceKnob = { table: { category: 'Reference knobs' } } as const; + export const BasicUsage = { render: BasicUsageExample, argTypes: getChartArgTypes({ @@ -38,7 +43,6 @@ export const BasicUsage = { hMin: { control: { type: 'number', min: 0, max: 600, step: 10 } }, hMax: { control: { type: 'number', min: 0, max: 600, step: 10 } }, showDots: { control: 'boolean' }, - useExplicitPlotWidth: { control: 'boolean', ...storyKnob }, highlightDots: { control: 'select', @@ -59,6 +63,22 @@ export const BasicUsage = { options: ['off', 'custom', 'divideByZero', 'includesFirstPoint'], ...storyKnob, }, + withReferenceLine: { control: 'boolean', ...referenceKnob }, + referenceLineValue: { control: 'number', if: { arg: 'withReferenceLine' }, ...referenceKnob }, + referenceLineArea: { control: 'number', if: { arg: 'withReferenceLine' }, ...referenceKnob }, + referenceLineCount: { control: { type: 'number', min: 1, max: 3 }, if: { arg: 'withReferenceLine' }, ...referenceKnob }, + referenceLinesOverlap: { control: 'boolean', if: { arg: 'withReferenceLine' }, ...referenceKnob }, + withReferenceArea: { control: 'boolean', ...referenceKnob }, + referenceAreaStart: { control: 'number', if: { arg: 'withReferenceArea' }, ...referenceKnob }, + referenceAreaEnd: { control: 'number', if: { arg: 'withReferenceArea' }, ...referenceKnob }, + referenceAreaUse: { + control: 'select', + if: { arg: 'withReferenceArea' }, + options: ['neutral', 'good', 'bad', 'insight'], + ...referenceKnob, + }, + referenceAreaTitle: { control: 'text', if: { arg: 'withReferenceArea' }, ...referenceKnob }, + referenceAreaSubTitle: { control: 'text', if: { arg: 'withReferenceArea' }, ...referenceKnob }, }), args: BasicUsageProps, }; diff --git a/stories/patterns/core/tests/all-components/components/Dashboard/Dashboard.tsx b/stories/patterns/core/tests/all-components/components/Dashboard/Dashboard.tsx index 61ff868d25..a45cb5fd99 100644 --- a/stories/patterns/core/tests/all-components/components/Dashboard/Dashboard.tsx +++ b/stories/patterns/core/tests/all-components/components/Dashboard/Dashboard.tsx @@ -24,8 +24,10 @@ import DonutMockData from '../../../../../../components/d3-chart/__mocks__/donut import ScatterplotMockData from '../../../../../../components/d3-chart/__mocks__/scatterplot'; import VennMockData from '../../../../../../components/d3-chart/__mocks__/venn'; import AreaChartBasicExample from '../../../../../../components/d3-chart/docs/examples/area-chart/basic-usage'; +import BarChartLinksExample from '../../../../../../components/d3-chart/docs/examples/bar-chart/links'; import LegendWithMetricsExample from '../../../../../../components/d3-chart/docs/examples/chart-legend/legend-with-metrics'; +import ReferenceLineExample from '../../../../../../components/d3-chart/docs/examples/d3-chart/reference-line'; import FeedbackRatingFormExample from '../../../../../ux-patterns/feedback-rating/docs/examples/feedback_rating_form'; import PrimaryTable from '../Tables/PrimaryTable'; @@ -708,6 +710,34 @@ export function Dashboard({ showPrimaryTableFooter = false }: DashboardProps) { + + + + + Line with reference + + + + + + + + + + + + Bar with links + + + + + + + {showPrimaryTableFooter && ( diff --git a/website/docs/data-display/d3-chart/d3-chart-api.md b/website/docs/data-display/d3-chart/d3-chart-api.md index e82b75f35a..d4af99457c 100644 --- a/website/docs/data-display/d3-chart/d3-chart-api.md +++ b/website/docs/data-display/d3-chart/d3-chart-api.md @@ -90,6 +90,10 @@ type Pattern = { ## ReferenceLine +::: warning +`ReferenceLine`, `ReferenceBackground` and `ReferenceStripes` are deprecated. Use the `referenceLine` and `referenceArea` properties of `Chart.Line`. +::: + ```js import { ReferenceLine } from '@semcore/ui/d3-chart'; ``` diff --git a/website/docs/style/design-tokens/design-tokens.json b/website/docs/style/design-tokens/design-tokens.json index f7154c3d90..1dae9da49d 100644 --- a/website/docs/style/design-tokens/design-tokens.json +++ b/website/docs/style/design-tokens/design-tokens.json @@ -772,9 +772,7 @@ "name": "--intergalactic-chart-grid-period-pattern", "value": "oklch(0.95 0.006 232.7)", "description": "Stripe color for diagonal pattern background.", - "components": [ - "d3-chart" - ] + "components": [] }, { "name": "--intergalactic-chart-grid-bg-good", @@ -830,7 +828,9 @@ "name": "--intergalactic-chart-grid-text-label-accent", "value": "oklch(0.102 0.021 230.9 / 0.9)", "description": "Text label with accent on the chart grid.", - "components": [] + "components": [ + "d3-chart" + ] }, { "name": "--intergalactic-chart-grid-x-axis",