Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 package.json
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@
"@storybook/addon-docs": "10.2.10",
"@storybook/addon-links": "10.2.10",
"@storybook/addon-themes": "10.2.10",
"@storybook/react": "10.2.10",
"@storybook/react-vite": "10.2.10",
"@storybook/test-runner": "0.24.2",
"@storybook/testing-library": "0.2.2",
Expand Down
4 changes: 4 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/__mocks__/styleMock.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
module.exports = {};
export default {};
3 changes: 3 additions & 0 deletions src/charts/barChart/barChart.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type { TickData } from '@/components/tick/tick.types';
import type { CanvasConfig } from '@/types/canvas.type';
import type { ChartError, ChartErrorCollection, ErrorType } from '@/types/errors.type';
import type { Positions } from '@/types/position.enum';
import type { ValueFormatter } from '@/types/valueFormatter.type';

export type BarChartChildrenType = ReactNode | ReactElement<PathProps | XAxisProps | YAxisProps>;

Expand Down Expand Up @@ -121,13 +122,15 @@ export interface BarChartXAxisProps extends Omit<XAxisProps, OmitProps>, React.A
*/
ariaLabel?: string;
tickValues?: BarChartTickValuesAxisProps;
valueFormatter?: ValueFormatter<string>;
}
export interface BarChartYAxisProps extends Omit<YAxisProps, OmitProps>, React.AriaAttributes {
/**
* @deprecated Use aria-label instead for better accessibility standards
*/
ariaLabel?: string;
tickValues?: BarChartTickValuesAxisProps;
valueFormatter?: ValueFormatter<string>;
}
export interface BarChartSeparatorProps {
topSeparator?: StyleProps;
Expand Down
16 changes: 16 additions & 0 deletions src/charts/barChart/fragments/__tests__/barChartXAxis.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,20 @@ describe('LineChartXAxis', () => {
const xAxis = getByTestId('testxAxis');
expect(xAxis).toBeInTheDocument();
});

it('renders formatted tick labels', () => {
const { getByText } = render(
<BarChartContext.Provider value={CONTEXT}>
<BarChart.XAxis
tickLine={{}}
tickText={{ fontSize: 12 }}
valueFormatter={value => `Label ${value}`}
/>
</BarChartContext.Provider>
);

expect(getByText('Label 1')).toBeInTheDocument();
expect(getByText('Label 2')).toBeInTheDocument();
expect(getByText('Label 3')).toBeInTheDocument();
});
});
16 changes: 16 additions & 0 deletions src/charts/barChart/fragments/__tests__/barChartYAxis.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,20 @@ describe('LineChartYAxis', () => {
const yAxis = getByTestId('testyAxis');
expect(yAxis).toBeInTheDocument();
});

it('renders formatted tick labels', () => {
const { getByText } = render(
<BarChartContext.Provider value={CONTEXT}>
<BarChart.YAxis
tickLine={{}}
tickText={{ fontSize: 12 }}
valueFormatter={value => `${value}%`}
/>
</BarChartContext.Provider>
);

expect(getByText('10%')).toBeInTheDocument();
expect(getByText('20%')).toBeInTheDocument();
expect(getByText('30%')).toBeInTheDocument();
});
});
7 changes: 6 additions & 1 deletion src/charts/barChart/fragments/barChartXAxis.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { type FC, type ReactElement, useContext } from 'react';

import { XAxis } from '@/components/axisChart/xAxis/xAxis';
import { TickDataUtils } from '@/components/tick/tick.types';
import { Positions } from '@/types/position.enum';
import { getTickTextYCoordinate } from '@/utils/getTickTextCoordinate/getTickTextCoordinates';

Expand All @@ -12,6 +13,7 @@ export const BarChartXAxis: FC<BarChartXAxisProps> = ({
position = Positions.BOTTOM,
tickLine,
tickText,
valueFormatter = (value: string) => value,
...props
}): ReactElement => {
const {
Expand All @@ -29,6 +31,9 @@ export const BarChartXAxis: FC<BarChartXAxisProps> = ({

const y1 = context.extraSpaceTopY;
const y2 = Number(context.canvasHeight) - context.extraSpaceBottomY;
const formattedTickValues = tickText
? TickDataUtils.formatTicksValues(tickValues, valueFormatter)
: undefined;

return (
<XAxis
Expand All @@ -51,7 +56,7 @@ export const BarChartXAxis: FC<BarChartXAxisProps> = ({
...tickText,
y: tickTextY,
}}
tickValues={tickText ? tickValues : undefined}
tickValues={formattedTickValues}
/>
);
};
7 changes: 6 additions & 1 deletion src/charts/barChart/fragments/barChartYAxis.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { type FC, type ReactElement, useContext } from 'react';

import { YAxis } from '@/components/axisChart/yAxis/yAxis';
import { TickDataUtils } from '@/components/tick/tick.types';
import { Positions } from '@/types/position.enum';
import { ajustedTextSpace } from '@/utils/ajustedTextSpace/ajustedTextSpace';
import { getTickTextXCoordinate } from '@/utils/getTickTextCoordinate/getTickTextCoordinates';
Expand All @@ -13,6 +14,7 @@ export const BarChartYAxis: FC<BarChartYAxisProps> = ({
position = Positions.LEFT,
tickLine,
tickText,
valueFormatter = (value: string) => value,
...props
}): ReactElement => {
const {
Expand All @@ -30,6 +32,9 @@ export const BarChartYAxis: FC<BarChartYAxisProps> = ({
coordinates.x1,
ajustedText
);
const formattedTickValues = tickText
? TickDataUtils.formatTicksValues(tickValues, valueFormatter)
: undefined;

return (
<YAxis
Expand All @@ -44,7 +49,7 @@ export const BarChartYAxis: FC<BarChartYAxisProps> = ({
x2: Number(context.canvasWidth) - context.extraSpaceRightX,
}}
tickText={{ ...tickText, x: xTickText }}
tickValues={tickText ? tickValues : undefined}
tickValues={formattedTickValues}
/>
);
};
9 changes: 3 additions & 6 deletions src/charts/barChart/stories/barChart.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@ import { AXIS_WITH_HORIZONTAL_BARS } from './templates/axisWithHorizontalBars';
import { AXIS_WITH_VERTICAL_BARS } from './templates/axisWithVericalBars';
import { COMPARATIVE_DATA, MIXED_DATA } from './templates/data';
import { BarChartWithErrorHandlingWithHooks } from './templates/withErrorHandling';
import {
BarChartWithTooltip,
BarChartHorizontalWithTooltip,
} from './templates/withTooltip';
import { BarChartHorizontalWithTooltip, BarChartWithTooltip } from './templates/withTooltip';

const meta = {
argTypes: argtypes(),
Expand Down Expand Up @@ -272,8 +269,8 @@ export const WithTooltipHorizontal: Story = {
text={[
<div key="tooltip-horizontal-explanation">
<p>
This example shows a <strong>horizontal bar chart</strong> with a fixed info
panel that displays details about the hovered bar.
This example shows a <strong>horizontal bar chart</strong> with a fixed info panel
that displays details about the hovered bar.
</p>
<p>
Instead of a floating tooltip, this pattern uses a persistent panel that updates
Expand Down
20 changes: 20 additions & 0 deletions src/charts/barChart/stories/children/XAxis/xAxis.argtypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,26 @@ export const xAxisArgTypes = (): ArgTypes<BarChartXAxisProps> => {
},
},

valueFormatter: {
control: {
labels: {
currency: 'Currency ($)',
custom: 'Custom Format [val]',
millions: 'Millions (M)',
none: 'None (no formatting)',
percentage: 'Percentage (%)',
thousands: 'Thousands (K)',
},
type: 'select',
},
description: 'Select a formatting style for tick labels in this story.',
options: ['none', 'currency', 'percentage', 'thousands', 'millions', 'custom'],
table: {
category: CATEGORY_CONTROL.DATA,
type: { summary: 'ValueFormatter | undefined' },
},
},

transform: {
control: { type: 'text' },
description: 'SVG transform attribute for positioning and scaling.',
Expand Down
44 changes: 38 additions & 6 deletions src/charts/barChart/stories/children/XAxis/xAxis.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@ import { BarOrientation } from '@/components/bar/bar.type';
import { Note } from '@/storybook/components/note/note';
import { DefaultCanvasConfig } from '@/types/canvas.type';
import { Positions } from '@/types/position.enum';
import type { ValueFormatter } from '@/types/valueFormatter.type';

import { BarChart } from '../../../barChart';
import type { BarChartXAxisProps } from '../../../barChart.type';
import { BarChartXAxis } from '../../../fragments/barChartXAxis';
import { xAxisArgTypes } from './xAxis.argtypes';

type XAxisStoryArgs = Omit<BarChartXAxisProps, 'valueFormatter'> & {
valueFormatter?: ValueFormatter | string;
};

const meta = {
argTypes: xAxisArgTypes(),
component: BarChartXAxis,
decorators: [
(Story: React.ComponentType) => (
<>
Expand All @@ -33,6 +36,11 @@ const meta = {
• <strong>tickValues</strong> - Define custom tick positions using numeric or custom
format
</>,
<>
• <strong>valueFormatter</strong> - Format tick labels using a callback function{' '}
<code>(val) =&gt; string</code>. The dropdown below shows preset examples, but in your
code you'll pass actual functions.
</>,
<>
• <strong>tickText</strong> - Complete text styling control including font, color, and
positioning
Expand Down Expand Up @@ -61,10 +69,28 @@ const meta = {
],
tags: ['autodocs'],
title: 'Charts/BarChart/Child Components/BarChartXAxis',
} satisfies Meta<typeof BarChartXAxis>;
} satisfies Meta<XAxisStoryArgs>;

export default meta;
type Story = StoryObj<typeof meta>;
type Story = StoryObj<XAxisStoryArgs>;

const getValueFormatter = (formatterType: string) => {
switch (formatterType) {
case 'currency':
return val => `$${val}`;
case 'percentage':
return val => `${val}%`;
case 'thousands':
return val => `${val}K`;
case 'millions':
return val => `${val}M`;
case 'custom':
return val => `[${val}]`;
case 'none':
default:
return undefined;
}
};

export const XAxisCustomization: Story = {
args: {
Expand Down Expand Up @@ -159,11 +185,17 @@ export const XAxisCustomization: Story = {
values: ['2001', '2002', '2003', '2004'],
},
},
valueFormatter: 'thousands',

transform: undefined,
},

render: (args: BarChartXAxisProps) => {
render: (args: XAxisStoryArgs) => {
const actualArgs = {
...args,
valueFormatter: getValueFormatter(args.valueFormatter as string),
};

// Simplified data for better visualization (single series per year)
const simplifiedData = [
{ value: 50, year: 2001 },
Expand Down Expand Up @@ -208,7 +240,7 @@ export const XAxisCustomization: Story = {
orientation={BarOrientation.VERTICAL}
pKey="year"
>
<BarChart.XAxis {...args} />
<BarChart.XAxis {...actualArgs} />
{simplifiedData.map((dataPoint, index) => (
<BarChart.Path
key={`bar-${dataPoint.year}`}
Expand Down
22 changes: 22 additions & 0 deletions src/charts/barChart/stories/children/YAxis/yAxis.argtypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,28 @@ export const yAxisArgTypes = (): ArgTypes<BarChartYAxisProps> => {
},
},

valueFormatter: {
control: {
labels: {
currency: 'Currency ($)',
custom: 'Custom brackets [val]',
millions: 'Millions (M)',
none: 'None (no formatting)',
percentage: 'Percentage (%)',
thousands: 'Thousands (K)',
units: 'Units (k)',
},
type: 'select',
},
description: 'Select a formatting style for tick labels in this story.',
options: ['none', 'currency', 'percentage', 'units', 'thousands', 'millions', 'custom'],
table: {
category: CATEGORY_CONTROL.DATA,
defaultValue: { summary: 'undefined' },
type: { summary: 'ValueFormatter' },
},
},

transform: {
control: { type: 'text' },
description: 'SVG transform attribute for positioning and scaling.',
Expand Down
Loading
Loading