Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
e7034e0
[UIK-4704][d3-chart] added showPercentValueInTooltip prop for Area/Ba…
slizhevskyv-semrush Jan 28, 2026
910ceed
Update semcore/d3-chart/src/component/Chart/AbstractChart.tsx
slizhevskyv-semrush Jan 28, 2026
f76a357
Update semcore/d3-chart/src/component/Chart/AbstractChart.tsx
slizhevskyv-semrush Jan 28, 2026
48844a8
[UIK-4704][d3-chart] add prop to storybook controls
slizhevskyv-semrush Feb 2, 2026
abf0cc6
[UIK-4704][d3-chart] update snapshots
slizhevskyv-semrush Feb 2, 2026
4b930b9
[UIK-4704][chore] updated playground controls to handle showPercentVa…
slizhevskyv-semrush Feb 3, 2026
b8561e4
[d3-chart] update tests and snapshots
Valeria-Zimnitskaya Feb 3, 2026
ef1cee7
[docs] added playground for Cigarette
sheila-semrush Feb 3, 2026
9016f17
[docs] small fix in cigarette playground, added percentage to example
sheila-semrush Feb 3, 2026
cd2f663
[docs] small fix in cigarette playground
sheila-semrush Feb 3, 2026
ab82db8
[tests] updated snapshot
sheila-semrush Feb 3, 2026
6c4ba7b
[UIK-4704][d3-chart] update layout for tooltip/refactor components lo…
slizhevskyv-semrush Feb 4, 2026
552d0d1
[UIK-4704][d3-chart] update layout for tooltip/refactor components lo…
slizhevskyv-semrush Feb 4, 2026
c183954
Merge branch 'release/v16' into UIK-4704/percent-value-in-tooltip
slizhevskyv-semrush Feb 4, 2026
0e2258b
[UIK-4704][d3-chart] update snapshots/small fixes
slizhevskyv-semrush Feb 4, 2026
cb9bbab
Merge branch 'UIK-4704/percent-value-in-tooltip' of github.com:semrus…
slizhevskyv-semrush Feb 4, 2026
35bfd9d
[d3-chart] update cigarrete chart
Valeria-Zimnitskaya Feb 5, 2026
b1e1c52
Merge branch 'release/v16' into UIK-4704/percent-value-in-tooltip
Valeria-Zimnitskaya Feb 5, 2026
3cb35de
[d3-chart] some fixes in tooltips
ilyabrower Feb 5, 2026
e3e3a68
[d3-chart] update tests
Valeria-Zimnitskaya Feb 5, 2026
c75fe08
[playground] fixed cigarette chart name
ilyabrower Feb 5, 2026
d187895
[docs] updated chart data for cigarette playground
sheila-semrush Feb 5, 2026
d03fbb0
[chore] Merge branch 'UIK-4704/percent-value-in-tooltip' of github.co…
ilyabrower Feb 5, 2026
c6bee6c
[playground, d3-chart] fixed rendering boolean props in playground, f…
ilyabrower Feb 5, 2026
8903265
[d3-chart] enabled percent in tooltips only for cigarette
ilyabrower Feb 6, 2026
6051acd
[d3-chart] enabled percent in tooltips only for cigarette
ilyabrower Feb 6, 2026
b3997d9
[d3-chart] update snapshots
Valeria-Zimnitskaya Feb 6, 2026
83b8107
[stories] update test story
Valeria-Zimnitskaya Feb 6, 2026
4b0adb8
[d3-chart] fixed showTooltip flag in cigarette chart
ilyabrower Feb 6, 2026
b27c6c6
[d3-chart] update cigarette test
Valeria-Zimnitskaya Feb 6, 2026
79cf141
[chore] fix one unstable test
Valeria-Zimnitskaya Feb 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions playground/components/Playground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ function Playground<
link={link}
sourceCode={reactElementToJSXString(element, {
showDefaultProps: false,
useBooleanShorthandSyntax: false,
filterProps,
...(JSXDisplayName && { displayName: () => JSXDisplayName }),
})}
Expand Down
100 changes: 100 additions & 0 deletions playground/entries/Chart/Cigarette.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import type { CigaretteChartProps } from '@semcore/ui/d3-chart';
import { Chart } from '@semcore/ui/d3-chart';
import React from 'react';

import { getDefaultChartControls } from './common/controls';
import type { CommonChartProps, LegendChartProps } from './common/controls';
import type { JSXProps } from '../../types/JSXProps';
import type { PlaygroundEntry } from '../../types/Playground';
import createGithubLink from '../../utils/createGHLink';

type CigaretteChartPlaygroundProps = {
commonChartProps: CommonChartProps;
legendProps: LegendChartProps & { withTrend: boolean };
cigaretteProps: {
tooltipViewType: CigaretteChartProps['tooltipViewType'];
layout: 'vertical' | 'horizontal';
showPercentValueInTooltip: boolean;
};
};
export type CigaretteChartJSXProps = JSXProps<CigaretteChartPlaygroundProps>;

const data = {
Cats: 524,
Dogs: 44,
Capybaras: 0,
Hamsters: 1456,
Birds: 123,
};

function getJSX(props: CigaretteChartJSXProps) {
const { ...legendProps } = props.legendProps ?? {};

return (
<Chart.Cigarette
Comment thread
sheila-semrush marked this conversation as resolved.
data={data}
plotWidth={props.cigaretteProps.layout === 'horizontal' ? 300 : 44}
plotHeight={props.cigaretteProps.layout === 'horizontal' ? 28 : 200}
aria-label='Cigarette chart'
tooltipViewType={props.cigaretteProps.tooltipViewType}
invertAxis={props.cigaretteProps.layout !== 'vertical'}
Comment thread
sheila-semrush marked this conversation as resolved.
showPercentValueInTooltip={props.cigaretteProps.showPercentValueInTooltip}
{...props.commonChartProps}
{...(props.legendProps && {
legendProps,
showLegend: props.commonChartProps.showLegend as true,
})}
{...(props.legendProps?.patterns && { patterns: props.legendProps.patterns })}
/>
);
}

const entry: PlaygroundEntry<CigaretteChartJSXProps> = {
JSX: (props) => getJSX(props),
controls: {
cigaretteProps: {
type: 'group',
groupName: 'Cigarette props',
isOpenedByDefault: true,
controls: {
layout: {
type: 'select',
options: ['horizontal', 'vertical'],
value: 'horizontal',
displayName: 'Layout',
},
tooltipViewType: {
type: 'select',
options: ['all', 'single'],
value: 'single',
displayName: 'Tooltip type',
},
showPercentValueInTooltip: {
type: 'boolean',
value: false,
displayName: 'Percent in tooltip',
},
},
},
...getDefaultChartControls({
skip: {
commonChartProps: ['showXAxis', 'showYAxis', 'direction', 'alignItems'],
legendProps: ['direction'],
},
}) },
link: createGithubLink('d3-chart'),
filterProps: (value: unknown, key: string) => {
if (key === 'data') {
return false;
}

if (key === 'invertAxis') {
return value === false;
}

return true;
},
JSXDisplayName: 'Chart.Cigarette',
};

export default entry;
2 changes: 2 additions & 0 deletions playground/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import ChartBar from './entries/Chart/Bar';
import ChartBarHorizontal from './entries/Chart/BarHorizontal';
import ChartBubble from './entries/Chart/Bubble';
import ChartLegend from './entries/Chart/ChartLegend';
import ChartCigarette from './entries/Chart/Cigarette';
import ChartDonut from './entries/Chart/Donut';
import ChartHistogram from './entries/Chart/Histogram';
import ChartLine from './entries/Chart/Line';
Expand Down Expand Up @@ -85,6 +86,7 @@ const registry = {
'Chart.Bar': ChartBar,
'Chart.BarHorizontal': ChartBarHorizontal,
'Chart.Bubble': ChartBubble,
'Chart.Cigarette': ChartCigarette,
'ChartLegend': ChartLegend,
'Chart.Donut': ChartDonut,
'Chart.Histogram': ChartHistogram,
Expand Down
29 changes: 23 additions & 6 deletions semcore/d3-chart/__tests__/area-chart.browser-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ test.describe(`${TAG.VISUAL}`, () => {
invertAxis: false,
showTooltip: true,
showTotalInTooltip: true,
showPercentValueInTooltip: true,
showLegend: true,
showDots: true,
patterns: false,
Expand All @@ -64,6 +65,7 @@ test.describe(`${TAG.VISUAL}`, () => {
invertAxis: false,
showTooltip: true,
showTotalInTooltip: false,
showPercentValueInTooltip: false,
showLegend: true,
showDots: false,
patterns: true,
Expand All @@ -82,6 +84,7 @@ test.describe(`${TAG.VISUAL}`, () => {
invertAxis: true,
showTooltip: false,
showTotalInTooltip: false,
showPercentValueInTooltip: true,
showLegend: false,
showDots: true,
patterns: false,
Expand All @@ -99,12 +102,26 @@ test.describe(`${TAG.VISUAL}`, () => {
'en',
vars,
);

await test.step('Verify chart renders correctly', async () => {
await locators.plot(page).waitFor({ state: 'visible' });
await page.waitForTimeout(500);
await expect(page).toHaveScreenshot();
});
await locators.plot(page).waitFor({ state: 'visible' });
await page.waitForTimeout(500);
if (!vars.showTooltip) {
await test.step('Verify chart renders correctly', async () => {
await expect(page).toHaveScreenshot();
});
} else if (vars.showTooltip) {
await test.step('Verify tooltip appears on hover', async () => {
const chart = locators.plot(page).first();
const box = await chart.boundingBox();
if (box) {
await page.mouse.move(box.x + 50, box.y + 50);
}

const tooltip = locators.tooltip(page);
await tooltip.waitFor({ state: 'visible' });
await expect(tooltip).toBeVisible();
await expect(page).toHaveScreenshot();
});
}
});
});

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
67 changes: 45 additions & 22 deletions semcore/d3-chart/__tests__/bar-chart.browser-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,17 @@ test.describe(`${TAG.VISUAL}`, () => {
vars,
);

await test.step('Verify chart renders correctly', async () => {
await test.step('Verify chart with tooltip renders correctly', async () => {
await locators.plot(page).waitFor({ state: 'visible' });
await page.waitForTimeout(500);
const chart = locators.plot(page).first();
const box = await page.locator('path').nth(2).boundingBox();
if (box) {
await page.mouse.move(box.x + 50, box.y + 50);
}

const tooltip = locators.tooltip(page);
await tooltip.waitFor({ state: 'visible' });
await expect(page).toHaveScreenshot();
});
});
Expand Down Expand Up @@ -312,11 +319,12 @@ test.describe(`${TAG.VISUAL}`, () => {
props: {
groupKey: 'category',
type: 'group',
showTotalInTooltip: true,
invertAxis: false,
data: [
{ category: 'Category 0', bar1: 4, bar2: 7 },
{ category: 'Category 1', bar1: 3, bar2: 5 },
{ category: 'Category 2', bar1: 8, bar2: 2 },
{ category: 'Category 0', bar1: 5, bar2: 7, bar3: 4, bar4: 1, bar5: 0, bar6: 1 },
{ category: 'Category 1', bar1: null, bar2: 7, bar3: null, bar4: 3, bar5: 0, bar6: 8 },
{ category: 'Category 2', bar1: 1, bar2: 7, bar3: null, bar4: undefined, bar5: 0 },
{ category: 'Category 3', bar1: 6, bar2: 9 },
{ category: 'Category 4', bar1: 1, bar2: 4 },
],
Expand All @@ -329,8 +337,9 @@ test.describe(`${TAG.VISUAL}`, () => {
type: 'group',
invertAxis: true,
data: [
{ category: 'Category 0', bar1: 4, bar2: 7 },
{ category: 'Category 1', bar1: 3, bar2: 5 },
{ category: 'Category 0', bar1: 5, bar2: 7, bar3: 4, bar4: 1, bar5: 0, bar6: 1 },
{ category: 'Category 1', bar1: null, bar2: 7, bar3: null, bar4: 3, bar5: 0, bar6: 8 },
{ category: 'Category 2', bar1: 1, bar2: 7, bar3: null, bar4: undefined, bar5: 0 },
{ category: 'Category 2', bar1: 8, bar2: 2 },
{ category: 'Category 3', bar1: 6, bar2: 9 },
{ category: 'Category 4', bar1: 1, bar2: 4 },
Expand All @@ -342,11 +351,12 @@ test.describe(`${TAG.VISUAL}`, () => {
props: {
groupKey: 'category',
type: 'stack',
showTotalInTooltip: true,
invertAxis: false,
data: [
{ category: 'Category 0', bar1: 4, bar2: 7 },
{ category: 'Category 1', bar1: 3, bar2: 5 },
{ category: 'Category 2', bar1: 8, bar2: 2 },
{ category: 'Category 0', bar1: 5, bar2: 7, bar3: 4, bar4: 1, bar5: 0, bar6: 1 },
{ category: 'Category 1', bar1: null, bar2: 7, bar3: null, bar4: 3, bar5: 0, bar6: 8 },
{ category: 'Category 2', bar1: 1, bar2: 7, bar3: null, bar4: undefined, bar5: 0 },
{ category: 'Category 3', bar1: 6, bar2: 9 },
{ category: 'Category 4', bar1: 1, bar2: 4 },
],
Expand All @@ -359,8 +369,9 @@ test.describe(`${TAG.VISUAL}`, () => {
type: 'stack',
invertAxis: true,
data: [
{ category: 'Category 0', bar1: 4, bar2: 7 },
{ category: 'Category 1', bar1: 3, bar2: 5 },
{ category: 'Category 0', bar1: 5, bar2: 7, bar3: 4, bar4: 1, bar5: 0, bar6: 1 },
{ category: 'Category 1', bar1: null, bar2: 7, bar3: null, bar4: 3, bar5: 0, bar6: 8 },
{ category: 'Category 2', bar1: 1, bar2: 7, bar3: null, bar4: undefined, bar5: 0 },
{ category: 'Category 2', bar1: 8, bar2: 2 },
{ category: 'Category 3', bar1: 6, bar2: 9 },
{ category: 'Category 4', bar1: 1, bar2: 4 },
Expand Down Expand Up @@ -388,17 +399,29 @@ test.describe(`${TAG.VISUAL}`, () => {
});

await test.step('Verify tooltip on hover', async () => {
const box = await chart.boundingBox();
if (!box) throw new Error('Bounding box not found');

const targetX = 128.42;
const targetY = 190.53;
const hoverX = box.x + targetX;
const hoverY = box.y + targetY;

await page.mouse.move(hoverX, hoverY);
await page.waitForTimeout(500);
await expect(page).toHaveScreenshot();
if (variant.props.type == 'group') {
const boxLocator = page.locator('path:nth-child(9)');
const box = await boxLocator.boundingBox();
if (!box) throw new Error('Bounding box not found');

const hoverX = box.x + box.width / 2;
const hoverY = box.y + box.height / 2;

await page.mouse.move(hoverX, hoverY);
await page.waitForTimeout(500);
await expect(page).toHaveScreenshot();
} else if (variant.props.type == 'stack') {
const boxLocator = page.locator('path:nth-child(37)');
const box = await boxLocator.boundingBox();
if (!box) throw new Error('Bounding box not found');

const hoverX = box.x + box.width / 2;
const hoverY = box.y + box.height / 2;

await page.mouse.move(hoverX, hoverY);
await page.waitForTimeout(500);
await expect(page).toHaveScreenshot();
}
});
});
});
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
72 changes: 72 additions & 0 deletions semcore/d3-chart/__tests__/cigarette-chart.browser-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,78 @@ test.describe(`${TAG.VISUAL}`, () => {
await expect(page).toHaveScreenshot();
});
});

test('Verify no tooltip when showTooltip=false', {
tag: [TAG.PRIORITY_MEDIUM, TAG.MOUSE, '@cigarette-chart', '@d3-chart'],
}, async ({ page }) => {
await loadPage(
page,
'stories/components/d3-chart/tests/examples/cigarette-chart/basic-usage.tsx',
'en',
{ showTooltip: false },
);

await test.step('Verify tooltip with percent shown', async () => {
await locators.plot(page).first().waitFor({ state: 'visible' });
await page.waitForTimeout(500);
await locators.plot(page).first().locator('path').nth(2).hover();
await expect(locators.tooltip(page)).toHaveCount(0);
await expect(page).toHaveScreenshot();
});
});

const tooltipViewTypeVariants = [
{
name: 'single with percent',
props: {
showPercentValueInTooltip: true,
tooltipViewType: 'single',
},
},
{
name: 'single without percent',
props: {
showPercentValueInTooltip: false,
tooltipViewType: 'single',
},
},
{
name: 'all with percent and total',
props: {
showPercentValueInTooltip: true,
showTotalInTooltip: true,
tooltipViewType: 'all',
},
},
{
name: 'all without percent',
props: {
showPercentValueInTooltip: false,
tooltipViewType: 'all',
},
},
];

tooltipViewTypeVariants.forEach((variant) => {
test(`Verify tooltipViewType=${variant.name}`, {
tag: [TAG.PRIORITY_MEDIUM, TAG.MOUSE, '@cigarette-chart', '@d3-chart'],
}, async ({ page }) => {
await loadPage(
page,
'stories/components/d3-chart/tests/examples/cigarette-chart/basic-usage.tsx',
'en',
variant.props,
);

await test.step('Verify tooltip shown correctly', async () => {
await locators.plot(page).first().waitFor({ state: 'visible' });
await page.waitForTimeout(500);
await locators.plot(page).first().locator('path').nth(2).hover();
await locators.tooltip(page).waitFor({ state: 'visible' });
await expect(page).toHaveScreenshot();
});
});
});
});

/* =====================================================
Expand Down
Loading
Loading