Skip to content

Commit 3f7ac16

Browse files
bosiraphaelremi
authored andcommitted
Fix horizontal bar chart spacing between ticks (twentyhq#15702)
This PR fixes a bug where the spacing between ticks on the Y axis was adjusted according to the width of the widget where it should have been adjusted according to the height. Same for the X axis. **Before**: Works for the vertical layout but not for the horizontal layout https://github.com/user-attachments/assets/f0b94103-1ba6-4dbe-bbc6-c47541c1b5fa **After**: Works for both https://github.com/user-attachments/assets/165faada-2943-4e05-92d6-a31def569500
1 parent d6c2835 commit 3f7ac16

19 files changed

+252
-95
lines changed

packages/twenty-front/src/modules/page-layout/widgets/graph/components/__stories__/GraphWidgetBarChart.stories.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { type Meta, type StoryObj } from '@storybook/react';
22

33
import { GraphWidgetBarChart } from '@/page-layout/widgets/graph/graphWidgetBarChart/components/GraphWidgetBarChart';
4+
import { BarChartLayout } from '@/page-layout/widgets/graph/graphWidgetBarChart/types/BarChartLayout';
45
import { CatalogDecorator, ComponentDecorator } from 'twenty-ui/testing';
56

67
const meta: Meta<typeof GraphWidgetBarChart> = {
@@ -280,7 +281,7 @@ export const Horizontal: Story = {
280281
],
281282
indexBy: 'product',
282283
keys: ['score'],
283-
layout: 'horizontal',
284+
layout: BarChartLayout.HORIZONTAL,
284285
showLegend: false,
285286
showGrid: true,
286287
xAxisLabel: 'Score',

packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/components/CustomBarItem.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { BAR_CHART_HOVER_BRIGHTNESS } from '@/page-layout/widgets/graph/graphWidgetBarChart/constants/BarChartHoverBrightness';
22
import { BAR_CHART_MAXIMUM_WIDTH } from '@/page-layout/widgets/graph/graphWidgetBarChart/constants/MaximumBarWidth';
3+
import { BarChartLayout } from '@/page-layout/widgets/graph/graphWidgetBarChart/types/BarChartLayout';
34
import { type BarDatum, type BarItemProps } from '@nivo/bar';
45
import { animated, to } from '@react-spring/web';
56
import { isNumber } from '@sniptt/guards';
@@ -12,7 +13,7 @@ type CustomBarItemProps<D extends BarDatum> = BarItemProps<D> & {
1213
groupMode?: 'grouped' | 'stacked';
1314
data?: readonly D[];
1415
indexBy?: string;
15-
layout?: 'vertical' | 'horizontal';
16+
layout?: BarChartLayout;
1617
chartId?: string;
1718
};
1819

@@ -46,7 +47,7 @@ export const CustomBarItem = <D extends BarDatum>({
4647
groupMode = 'grouped',
4748
data: chartData,
4849
indexBy,
49-
layout = 'vertical',
50+
layout = BarChartLayout.VERTICAL,
5051
chartId,
5152
}: CustomBarItemProps<D>) => {
5253
const handleClick = useCallback(
@@ -123,7 +124,7 @@ export const CustomBarItem = <D extends BarDatum>({
123124
barData.indexValue,
124125
]);
125126

126-
const isHorizontal = layout === 'horizontal';
127+
const isHorizontal = layout === BarChartLayout.HORIZONTAL;
127128
const clipPathId = `round-corner-${chartId ?? 'chart'}-${barData.index}-${
128129
seriesIndex >= 0 ? seriesIndex : 'x'
129130
}`;

packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/components/CustomTotalsLayer.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { type BarChartDataItem } from '@/page-layout/widgets/graph/graphWidgetBarChart/types/BarChartDataItem';
2+
import { BarChartLayout } from '@/page-layout/widgets/graph/graphWidgetBarChart/types/BarChartLayout';
23
import { useTheme } from '@emotion/react';
34
import { type BarCustomLayerProps, type ComputedBarDatum } from '@nivo/bar';
45
import { animated } from '@react-spring/web';
@@ -10,7 +11,7 @@ type CustomTotalsLayerProps = Pick<
1011
> & {
1112
formatValue?: (value: number) => string;
1213
offset?: number;
13-
layout?: 'vertical' | 'horizontal';
14+
layout?: BarChartLayout;
1415
groupMode?: 'grouped' | 'stacked';
1516
omitNullValues?: boolean;
1617
};
@@ -137,12 +138,12 @@ export const CustomTotalsLayer = ({
137138
bars,
138139
formatValue,
139140
offset = 0,
140-
layout = 'vertical',
141+
layout = BarChartLayout.VERTICAL,
141142
groupMode = 'grouped',
142143
omitNullValues = false,
143144
}: CustomTotalsLayerProps) => {
144145
const theme = useTheme();
145-
const isVertical = layout === 'vertical';
146+
const isVertical = layout === BarChartLayout.VERTICAL;
146147

147148
const labels =
148149
groupMode === 'stacked'

packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/components/GraphWidgetBarChart.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { BAR_CHART_MINIMUM_INNER_PADDING } from '@/page-layout/widgets/graph/gra
77
import { useBarChartData } from '@/page-layout/widgets/graph/graphWidgetBarChart/hooks/useBarChartData';
88
import { useBarChartTheme } from '@/page-layout/widgets/graph/graphWidgetBarChart/hooks/useBarChartTheme';
99
import { type BarChartDataItem } from '@/page-layout/widgets/graph/graphWidgetBarChart/types/BarChartDataItem';
10+
import { BarChartLayout } from '@/page-layout/widgets/graph/graphWidgetBarChart/types/BarChartLayout';
1011
import { type BarChartSeries } from '@/page-layout/widgets/graph/graphWidgetBarChart/types/BarChartSeries';
1112
import { calculateBarChartValueRange } from '@/page-layout/widgets/graph/graphWidgetBarChart/utils/calculateBarChartValueRange';
1213
import { calculateStackedBarChartValueRange } from '@/page-layout/widgets/graph/graphWidgetBarChart/utils/calculateStackedBarChartValueRange';
@@ -45,7 +46,7 @@ type GraphWidgetBarChartProps = {
4546
xAxisLabel?: string;
4647
yAxisLabel?: string;
4748
id: string;
48-
layout?: 'vertical' | 'horizontal';
49+
layout?: BarChartLayout;
4950
groupMode?: 'grouped' | 'stacked';
5051
seriesLabels?: Record<string, string>;
5152
rangeMin?: number;
@@ -73,7 +74,7 @@ export const GraphWidgetBarChart = ({
7374
xAxisLabel,
7475
yAxisLabel,
7576
id,
76-
layout = 'vertical',
77+
layout = BarChartLayout.VERTICAL,
7778
groupMode,
7879
seriesLabels,
7980
rangeMin,
@@ -209,7 +210,7 @@ export const GraphWidgetBarChart = ({
209210
const zeroMarker = hasNegativeValues
210211
? [
211212
{
212-
axis: (layout === 'vertical' ? 'y' : 'x') as 'y' | 'x',
213+
axis: (layout === BarChartLayout.VERTICAL ? 'y' : 'x') as 'y' | 'x',
213214
value: 0,
214215
lineStyle: {
215216
stroke: theme.border.color.medium,
@@ -260,10 +261,10 @@ export const GraphWidgetBarChart = ({
260261
axisRight={null}
261262
axisBottom={axisBottomConfig}
262263
axisLeft={axisLeftConfig}
263-
enableGridX={layout === 'horizontal' && showGrid}
264-
enableGridY={layout === 'vertical' && showGrid}
265-
gridXValues={layout === 'horizontal' ? 5 : undefined}
266-
gridYValues={layout === 'vertical' ? 5 : undefined}
264+
enableGridX={layout === BarChartLayout.HORIZONTAL && showGrid}
265+
enableGridY={layout === BarChartLayout.VERTICAL && showGrid}
266+
gridXValues={layout === BarChartLayout.HORIZONTAL ? 5 : undefined}
267+
gridYValues={layout === BarChartLayout.VERTICAL ? 5 : undefined}
267268
enableLabel={false}
268269
labelSkipWidth={12}
269270
innerPadding={
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const BAR_CHART_MIN_TICK_SPACING_HEIGHT_RATIO = 2.5;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const BAR_CHART_MINIMUM_WIDTH_PER_TICK = 100;

packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/hooks/useGraphBarChartWidgetData.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMetadataItemById';
22
import { type BarChartDataItem } from '@/page-layout/widgets/graph/graphWidgetBarChart/types/BarChartDataItem';
3+
import { type BarChartLayout } from '@/page-layout/widgets/graph/graphWidgetBarChart/types/BarChartLayout';
34
import { type BarChartSeries } from '@/page-layout/widgets/graph/graphWidgetBarChart/types/BarChartSeries';
45
import { useGraphWidgetGroupByQuery } from '@/page-layout/widgets/graph/hooks/useGraphWidgetGroupByQuery';
56
import { transformGroupByDataToBarChartData } from '@/page-layout/widgets/graph/utils/transformGroupByDataToBarChartData';
@@ -19,7 +20,7 @@ type UseGraphBarChartWidgetDataResult = {
1920
xAxisLabel?: string;
2021
yAxisLabel?: string;
2122
showDataLabels: boolean;
22-
layout?: 'vertical' | 'horizontal';
23+
layout?: BarChartLayout;
2324
loading: boolean;
2425
error?: Error;
2526
hasTooManyGroups: boolean;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export enum BarChartLayout {
2+
VERTICAL = 'vertical',
3+
HORIZONTAL = 'horizontal',
4+
}

packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/utils/__tests__/calculateBarChartEndLineCoordinates.test.ts

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import { type ComputedBarDatum } from '@nivo/bar';
21
import { type BarChartDataItem } from '@/page-layout/widgets/graph/graphWidgetBarChart/types/BarChartDataItem';
2+
import { BarChartLayout } from '@/page-layout/widgets/graph/graphWidgetBarChart/types/BarChartLayout';
3+
import { type ComputedBarDatum } from '@nivo/bar';
34
import { calculateBarChartEndLineCoordinates } from '../calculateBarChartEndLineCoordinates';
45
describe('calculateBarChartEndLineCoordinates', () => {
56
const createMockBar = (
@@ -26,7 +27,10 @@ describe('calculateBarChartEndLineCoordinates', () => {
2627
describe('vertical layout', () => {
2728
it('should calculate horizontal line coordinates at the top of vertical bars', () => {
2829
const mockBar = createMockBar();
29-
const result = calculateBarChartEndLineCoordinates(mockBar, 'vertical');
30+
const result = calculateBarChartEndLineCoordinates(
31+
mockBar,
32+
BarChartLayout.VERTICAL,
33+
);
3034
expect(result).toEqual({
3135
x1: 100,
3236
x2: 140,
@@ -38,7 +42,7 @@ describe('calculateBarChartEndLineCoordinates', () => {
3842
const barAtOrigin = createMockBar({ x: 0, y: 0 });
3943
const result = calculateBarChartEndLineCoordinates(
4044
barAtOrigin,
41-
'vertical',
45+
BarChartLayout.VERTICAL,
4246
);
4347
expect(result).toEqual({
4448
x1: 0,
@@ -51,7 +55,7 @@ describe('calculateBarChartEndLineCoordinates', () => {
5155
const negativeBar = createMockBar({ x: -50, y: -20 });
5256
const result = calculateBarChartEndLineCoordinates(
5357
negativeBar,
54-
'vertical',
58+
BarChartLayout.VERTICAL,
5559
);
5660
expect(result).toEqual({
5761
x1: -50,
@@ -64,7 +68,10 @@ describe('calculateBarChartEndLineCoordinates', () => {
6468
describe('horizontal layout', () => {
6569
it('should calculate vertical line coordinates at the end of horizontal bars', () => {
6670
const mockBar = createMockBar();
67-
const result = calculateBarChartEndLineCoordinates(mockBar, 'horizontal');
71+
const result = calculateBarChartEndLineCoordinates(
72+
mockBar,
73+
BarChartLayout.HORIZONTAL,
74+
);
6875
expect(result).toEqual({
6976
x1: 140,
7077
x2: 140,
@@ -74,7 +81,10 @@ describe('calculateBarChartEndLineCoordinates', () => {
7481
});
7582
it('should handle bars with different dimensions', () => {
7683
const wideBar = createMockBar({ width: 100, height: 20 });
77-
const result = calculateBarChartEndLineCoordinates(wideBar, 'horizontal');
84+
const result = calculateBarChartEndLineCoordinates(
85+
wideBar,
86+
BarChartLayout.HORIZONTAL,
87+
);
7888
expect(result).toEqual({
7989
x1: 200,
8090
x2: 200,
@@ -84,7 +94,10 @@ describe('calculateBarChartEndLineCoordinates', () => {
8494
});
8595
it('should handle very thin bars', () => {
8696
const thinBar = createMockBar({ width: 1, height: 200 });
87-
const result = calculateBarChartEndLineCoordinates(thinBar, 'horizontal');
97+
const result = calculateBarChartEndLineCoordinates(
98+
thinBar,
99+
BarChartLayout.HORIZONTAL,
100+
);
88101
expect(result).toEqual({
89102
x1: 101,
90103
x2: 101,

packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/utils/calculateBarChartEndLineCoordinates.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { type BarChartDataItem } from '@/page-layout/widgets/graph/graphWidgetBarChart/types/BarChartDataItem';
2+
import { BarChartLayout } from '@/page-layout/widgets/graph/graphWidgetBarChart/types/BarChartLayout';
23
import { type ComputedBarDatum } from '@nivo/bar';
34

45
export const calculateBarChartEndLineCoordinates = (
56
bar: ComputedBarDatum<BarChartDataItem>,
6-
layout: 'vertical' | 'horizontal',
7+
layout: BarChartLayout,
78
) => {
8-
if (layout === 'vertical') {
9+
if (layout === BarChartLayout.VERTICAL) {
910
return {
1011
x1: bar.x,
1112
x2: bar.x + bar.width,

0 commit comments

Comments
 (0)