Skip to content
Closed
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
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}
/>
);
};
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
@@ -1,18 +1,21 @@
import type { Meta, StoryObj } from '@storybook/react';

Check failure on line 1 in src/charts/barChart/stories/children/XAxis/xAxis.stories.tsx

View workflow job for this annotation

GitHub Actions / Validate PR Standards

Cannot find module '@storybook/react' or its corresponding type declarations.

Check failure on line 1 in src/charts/barChart/stories/children/XAxis/xAxis.stories.tsx

View workflow job for this annotation

GitHub Actions / Validate PR Standards

Cannot find module '@storybook/react' or its corresponding type declarations.

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 @@
• <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 @@
],
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 @@
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 @@
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
46 changes: 40 additions & 6 deletions src/charts/barChart/stories/children/YAxis/yAxis.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
import type { Meta, StoryObj } from '@storybook/react';

Check failure on line 1 in src/charts/barChart/stories/children/YAxis/yAxis.stories.tsx

View workflow job for this annotation

GitHub Actions / Validate PR Standards

Cannot find module '@storybook/react' or its corresponding type declarations.

Check failure on line 1 in src/charts/barChart/stories/children/YAxis/yAxis.stories.tsx

View workflow job for this annotation

GitHub Actions / Validate PR Standards

Cannot find module '@storybook/react' or its corresponding type declarations.

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 { BarChartYAxisProps } from '../../../barChart.type';
import { BarChartYAxis } from '../../../fragments/barChartYAxis';
import { simplifiedData } from '../../templates/data';
import { yAxisArgTypes } from './yAxis.argtypes';

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

const meta = {
argTypes: yAxisArgTypes(),
component: BarChartYAxis,
decorators: [
(Story: React.ComponentType) => (
<>
Expand All @@ -30,6 +33,11 @@
<>
<strong>Key Features:</strong>
</>,
<>
• <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>position</strong> - Axis placement (left or right, refresh story after
setting in controls)
Expand Down Expand Up @@ -68,10 +76,30 @@
],
tags: ['autodocs'],
title: 'Charts/BarChart/Child Components/BarChartYAxis',
} satisfies Meta<typeof BarChartYAxis>;
} satisfies Meta<YAxisStoryArgs>;

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

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 'units':
return val => `${val}k`;
case 'custom':
return val => `[${val}]`;
case 'none':
default:
return undefined;
}
};

export const YAxisCustomization: Story = {
args: {
Expand Down Expand Up @@ -161,11 +189,17 @@
step: 1,
},
},
valueFormatter: 'currency',

transform: undefined,
},

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

const chartData = simplifiedData;

const barConfigs = [
Expand Down Expand Up @@ -203,7 +237,7 @@
orientation={BarOrientation.HORIZONTAL}
pKey="year"
>
<BarChart.YAxis {...args} />
<BarChart.YAxis {...actualArgs} />

{chartData.map((dataPoint, index) => (
<BarChart.Path
Expand Down
Loading
Loading