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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Using Force UI as a dependency in package.json -

```json
"dependencies": {
"@bsf/force-ui": "git+https://github.com/brainstormforce/force-ui#1.6.0"
"@bsf/force-ui": "git+https://github.com/brainstormforce/force-ui#1.6.1"
}
```

Expand All @@ -28,7 +28,7 @@ npm install
Or you can directly run the following command to install the package -

```bash
npm i -S @bsf/force-ui@git+https://github.com/brainstormforce/force-ui.git#1.6.0
npm i -S @bsf/force-ui@git+https://github.com/brainstormforce/force-ui.git#1.6.1
```

<br />
Expand Down
6 changes: 6 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
Version 1.6.1 - 11th April, 2025
- Improvement - Added a new prop to the LineChart component to enable Biaxial Line chart functionality, along with various UI enhancements for improved user experience.
- Improvement - Added customizable properties for the LineChart and AreaChart components to tailor x-axis and y-axis ticks and labels for better data visualization.
- Improvement - Introduced a `className` prop in the Dropzone component to enhance customizability and allow for more flexible styling options.
- Fix - Corrected the positioning of days in the DatePicker component to ensure accurate display and improved user experience.

Version 1.6.0 - 8th April, 2025
- New - Introduced a versatile Text component that supports multiple HTML elements and customizable styles for enhanced typography flexibility.
- Improvement - Display xAxis data on the tooltip when hovering.
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@bsf/force-ui",
"version": "1.6.0",
"version": "1.6.1",
"description": "Library of components for the BSF project",
"main": "./dist/force-ui.cjs.js",
"module": "./dist/force-ui.es.js",
Expand Down
115 changes: 114 additions & 1 deletion src/components/area-chart/area-chart.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Label from '../label';
import Button from '../button';
import Badge from '../badge';
import Container from '../container';
import { ArrowUpRight, ArrowUp } from 'lucide-react';
import { ArrowUpRight, ArrowUp, AlertCircle } from 'lucide-react';

const areaChartData = [
{ month: 'January', sales: 186, expenses: 80 },
Expand All @@ -15,7 +15,21 @@ const areaChartData = [
{ month: 'June', sales: 214, expenses: 140 },
];

// Data with large values to demonstrate Y-axis formatting
const largeValuesData = [
{ month: 'January', pageviews: 1200, sessions: 800 },
{ month: 'February', pageviews: 2800, sessions: 1500 },
{ month: 'March', pageviews: 5500, sessions: 2900 },
{ month: 'April', pageviews: 8200, sessions: 4100 },
{ month: 'May', pageviews: 14000, sessions: 6200 },
{ month: 'June', pageviews: 18500, sessions: 8800 },
];

// Empty data for demonstrating custom no data component
const emptyData: { month: string; sales: number; expenses: number }[] = [];

const dataKeys = [ 'sales', 'expenses' ];
const largeDataKeys = [ 'pageviews', 'sessions' ];

const chartDataIteractive = [
{ date: '2024-04-01', desktop: 222, mobile: 150 },
Expand Down Expand Up @@ -121,6 +135,29 @@ const colors = [
// Custom tick formatter function for months
const monthFormatter = ( value: string ) => value.slice( 0, 3 );

// Custom Y-axis formatter function to display values in K/M format
const yAxisFormatter = ( value: number ) => {
if ( value >= 1000000 ) {
return `${ ( value / 1000000 ).toFixed( 1 ) }M`;
}
if ( value >= 1000 ) {
return `${ ( value / 1000 ).toFixed( 1 ) }K`;
}
return value.toString();
};

// Custom No Data Component
const CustomNoDataComponent = () => (
<div className="flex flex-col items-center justify-center p-6 rounded-lg bg-gray-50 text-gray-600">
<AlertCircle className="mb-3 text-amber-500" size={ 50 } />
<div className="text-base font-medium">No data found</div>
<p className="text-sm text-center text-gray-500 mt-1 max-w-xs">
There is no data available for this chart at the moment. Try
adjusting your filters or check back later.
</p>
</div>
);

const monthFormatterInteractive = ( value: string ) => {
const date = new Date( value );
return date.toLocaleDateString( 'en-US', {
Expand Down Expand Up @@ -187,7 +224,83 @@ export const AreaChartInteractive: Story = {
},
};

export const AreaChartWithFormattedYAxis: Story = {
args: {
chartWidth: 600,
chartHeight: 300,
data: largeValuesData,
dataKeys: largeDataKeys,
colors: [
{ stroke: '#3b82f6', fill: '#BFDBFE' },
{ stroke: '#f97316', fill: '#FFEDD5' },
],
variant: 'solid',
showXAxis: true,
xAxisDataKey: 'month',
showYAxis: true,
tickFormatter: monthFormatter,
yAxisTickFormatter: yAxisFormatter,
showLegend: true,
areaChartWrapperProps: {
margin: {
left: 35,
right: 14,
top: 6,
bottom: 6,
},
},
},
};

export const AreaChartGradientWithFormattedYAxis: Story = {
args: {
chartWidth: 600,
chartHeight: 300,
data: largeValuesData,
dataKeys: largeDataKeys,
colors: [
{ stroke: '#3b82f6', fill: '#BFDBFE' },
{ stroke: '#f97316', fill: '#FFEDD5' },
],
variant: 'gradient',
showXAxis: true,
xAxisDataKey: 'month',
showYAxis: true,
tickFormatter: monthFormatter,
yAxisTickFormatter: yAxisFormatter,
showLegend: true,
areaChartWrapperProps: {
margin: {
left: 35,
right: 14,
top: 6,
bottom: 6,
},
},
},
};

export const AreaChartWithCustomNoDataComponent: Story = {
args: {
chartWidth: 600,
chartHeight: 300,
data: emptyData,
dataKeys,
colors,
variant: 'solid',
showXAxis: true,
xAxisDataKey: 'month',
showYAxis: true,
noDataComponent: <CustomNoDataComponent />,
},
};

AreaChartInteractive.storyName = 'Area Chart Gradient with Legend';
AreaChartWithFormattedYAxis.storyName = 'Area Chart with Formatted Y-Axis';
AreaChartGradientWithFormattedYAxis.storyName =
'Area Chart Gradient with Formatted Y-Axis';
AreaChartWithCustomNoDataComponent.storyName =
'Area Chart with Custom No Data Component';

type Story1 = StoryFn<typeof AreaChart>;

Expand Down
51 changes: 37 additions & 14 deletions src/components/area-chart/area-chart.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useState } from 'react';
import { useEffect, useState, type ReactNode } from 'react';
import {
AreaChart as AreaChartWrapper,
Area,
Expand All @@ -14,6 +14,13 @@ import ChartTooltipContent from './chart-tooltip-content';
import Label from '../label';
import type { CategoricalChartProps } from 'recharts/types/chart/generateCategoricalChart';

// Default color constants
const DEFAULT_FONT_COLOR = '#6B7280';
const DEFAULT_AREA_COLORS = [
{ stroke: '#2563EB', fill: '#BFDBFE' },
{ stroke: '#38BDF8', fill: '#BAE6FD' },
];

interface DataItem {
[key: string]: number | string; // Adjust based on your data structure
}
Expand Down Expand Up @@ -56,9 +63,18 @@ interface AreaChartProps {
/** Whether to display the `<CartesianGrid />`, adding horizontal and vertical grid lines. */
showCartesianGrid?: boolean;

/** A function used to format the ticks on the axes, e.g., for formatting dates or numbers. */
/** A function used to format the ticks on the x-axis, e.g., for formatting dates or numbers. */
xAxisTickFormatter?: ( value: string ) => string;

/**
* A function used to format the ticks on the x-axis, e.g., for formatting dates or numbers.
* @deprecated Use `xAxisTickFormatter` instead.
*/
tickFormatter?: ( value: string ) => string;

/** A function used to format the ticks on the y-axis, e.g., for converting 1000 to 1K. */
yAxisTickFormatter?: ( value: number ) => string;

/** The key in the data objects representing values for the x-axis. This is used to access the x-axis values from each data entry. */
xAxisDataKey?: string;

Expand All @@ -85,6 +101,12 @@ interface AreaChartProps {
CategoricalChartProps,
'width' | 'height' | 'data'
>;

/**
* Custom component to display when no data is available.
* If not provided, a default "No data available" message will be displayed.
*/
noDataComponent?: ReactNode;
}

const AreaChart = ( {
Expand All @@ -99,11 +121,13 @@ const AreaChart = ( {
tooltipLabelKey,
showLegend = true,
showCartesianGrid = true,
xAxisTickFormatter,
tickFormatter,
yAxisTickFormatter,
xAxisDataKey,
yAxisDataKey,
xAxisFontSize = 'sm', // sm, md, lg
xAxisFontColor = '#6B7280',
xAxisFontColor = DEFAULT_FONT_COLOR,
chartWidth = 350,
chartHeight = 200,
areaChartWrapperProps = {
Expand All @@ -114,17 +138,12 @@ const AreaChart = ( {
bottom: 6,
},
},
noDataComponent,
}: AreaChartProps ) => {
const [ width, setWidth ] = useState( chartWidth );
const [ height, setHeight ] = useState( chartHeight );

// Default colors
const defaultColors: Color[] = [
{ stroke: '#2563EB', fill: '#BFDBFE' },
{ stroke: '#38BDF8', fill: '#BAE6FD' },
];

const appliedColors = colors.length > 0 ? colors : defaultColors;
const appliedColors = colors.length > 0 ? colors : DEFAULT_AREA_COLORS;

useEffect( () => {
setWidth( chartWidth );
Expand Down Expand Up @@ -167,9 +186,11 @@ const AreaChart = ( {

if ( ! data || data.length === 0 ) {
return (
<Label size="sm" variant="help">
No data available
</Label>
noDataComponent || (
<Label size="sm" variant="help">
No data available
</Label>
)
);
}

Expand All @@ -182,18 +203,20 @@ const AreaChart = ( {
tickLine={ false }
axisLine={ false }
tickMargin={ 8 }
tickFormatter={ tickFormatter }
tickFormatter={ xAxisTickFormatter || tickFormatter }
tick={ {
fontSize: fontSizeVariant,
fill: xAxisFontColor,
} }
hide={ ! showXAxis }
interval="preserveStartEnd"
/>
<YAxis
dataKey={ yAxisDataKey }
tickLine={ false }
axisLine={ false }
tickMargin={ 8 }
tickFormatter={ yAxisTickFormatter }
tick={ {
fontSize: fontSizeVariant,
fill: xAxisFontColor,
Expand Down
2 changes: 1 addition & 1 deletion src/components/area-chart/chart-tooltip-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ const ChartTooltipContent = forwardRef<
} }
/>
) }
<div className="flex-1 flex justify-between items-center">
<div className="flex-1 flex justify-between items-center gap-1">
<span>{ item[ nameKey ] || item.dataKey }</span>
<span className="font-mono font-medium">
{ formatter
Expand Down
11 changes: 7 additions & 4 deletions src/components/datepicker/datepicker-component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,10 @@ const DatePickerComponent = ( {

const shouldShowDay =
isThisMonth || isRangeEndInCurrentMonth || isPartOfRange;
const showOutsideDates = ! showOutsideDays && isOutside;

// Fix: Corrected the logic for hiding outside dates
// Only hide outside days when showOutsideDays is false AND the day is outside
const hideOutsideDay = ! showOutsideDays && isOutside;

// Common class for disabled outside days
const disabledOutsideClass =
Expand Down Expand Up @@ -398,7 +401,7 @@ const DatePickerComponent = ( {
className={ cn(
buttonClasses,
isToday && 'font-semibold',
showOutsideDates && 'opacity-0',
hideOutsideDay && 'opacity-0',
isRangeStart && 'fui-range-start',
isRangeEnd && 'fui-range-end',
isRangeMiddle && 'fui-range-middle',
Expand All @@ -415,8 +418,7 @@ const DatePickerComponent = ( {
data-selected={ isSelected }
data-day={ format( day.date, 'yyyy-MM-dd' ) }
>
{ ( ! showOutsideDates || ( isPartOfRange && shouldShowDay ) ) &&
customDayProps.children }
{ customDayProps.children }
{ isToday && shouldShowDay && (
<span className="absolute h-1 w-1 bg-background-brand rounded-full bottom-1"></span>
) }
Expand Down Expand Up @@ -553,6 +555,7 @@ const DatePickerComponent = ( {
...classNames,
} }
numberOfMonths={ numberOfMonths }
showOutsideDays={ true }
components={ {
MonthCaption:
CustomMonthCaption as unknown as CustomComponents['MonthCaption'],
Expand Down
Loading
Loading