diff --git a/README.md b/README.md index 8e8fffd5..426fc923 100644 --- a/README.md +++ b/README.md @@ -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.3.2" + "@bsf/force-ui": "git+https://github.com/brainstormforce/force-ui#1.3.4" } ``` @@ -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.3.2 +npm i -S @bsf/force-ui@git+https://github.com/brainstormforce/force-ui.git#1.3.4 ```
diff --git a/changelog.txt b/changelog.txt index 05bf1d4d..271bb8dc 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,15 +1,25 @@ -Version 1.3.2 - 18th December, 2024 -Fixed - Adjusted the color of the Switch component label and help text. +Version 1.3.4 - 26th December, 2024 +- Improvement - Enhanced the UI of the Table and Line chart component for responsive design. +- Improvement - Added option group to the Select component. +- Improvement - Added support for controlling selected dates through the 'selected' prop in DatePicker component. +- Fixed - DatePicker component crash when navigating through years. + +Version 1.3.3 - 20th December, 2024 +- Fixed - React `Each child in a list should have a unique "key" prop` console warning. +- Fixed - Toaster content overlapping with the close button. + +Version 1.3.2 - 17th December, 2024 +- Fixed - Adjusted the color of the Switch component label and help text. Version 1.3.1 - 17th December, 2024 -Fixed - The underline issue to enhance visual consistency. -Fixed - Issue with the Select component where a check mark was displayed even when no item was selected. -Fixed - Design mismatch in the Switch component. -Fixed - Text, icon size, alignment, and color inconsistencies in the Date Picker to ensure a uniform appearance. -Fixed - Input ref not pointing to the input field. -Fixed - Icon size and alignment issues in the Menu component for better visual clarity. -Fixed - Sidebar height not being overridable. -Improvement - Removed backdrop blur to enhance performance and visual clarity. +- Fixed - The underline issue to enhance visual consistency. +- Fixed - Issue with the Select component where a check mark was displayed even when no item was selected. +- Fixed - Design mismatch in the Switch component. +- Fixed - Text, icon size, alignment, and color inconsistencies in the Date Picker to ensure a uniform appearance. +- Fixed - Input ref not pointing to the input field. +- Fixed - Icon size and alignment issues in the Menu component for better visual clarity. +- Fixed - Sidebar height not being overridable. +- Improvement - Removed backdrop blur to enhance performance and visual clarity. Version 1.3.0 - 16th December, 2024 - New - Table component. diff --git a/package.json b/package.json index babe0eb0..ca50f9b9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@bsf/force-ui", - "version": "1.3.2", + "version": "1.3.4", "description": "Library of components for the BSF project", "main": "./dist/force-ui.js", "module": "./dist/force-ui.js", diff --git a/src/components/button/button.tsx b/src/components/button/button.tsx index b9ce047a..8f951e06 100644 --- a/src/components/button/button.tsx +++ b/src/components/button/button.tsx @@ -1,4 +1,9 @@ -import React, { forwardRef, type ElementType, type ReactNode } from 'react'; +import React, { + forwardRef, + Fragment, + type ElementType, + type ReactNode, +} from 'react'; import { cn } from '@/utilities/functions'; export interface ButtonProps { @@ -140,12 +145,14 @@ const Button: React.FunctionComponent = forwardRef( disabled={ disabled } { ...rest } > - { iconLeft } + { iconLeft } { children ? { children } : null } - { iconRight } + { iconRight } ); } ); +Button.displayName = 'Button'; + export default Button; diff --git a/src/components/label/label.tsx b/src/components/label/label.tsx index 7a261cad..8c3521ca 100644 --- a/src/components/label/label.tsx +++ b/src/components/label/label.tsx @@ -78,6 +78,8 @@ const Label = forwardRef( } ); +Label.displayName = 'Label'; + export default Label as ( props: LabelProps & T, ref: React.Ref diff --git a/src/components/line-chart/line-chart.tsx b/src/components/line-chart/line-chart.tsx index 170a27fb..9b714b59 100644 --- a/src/components/line-chart/line-chart.tsx +++ b/src/components/line-chart/line-chart.tsx @@ -5,6 +5,7 @@ import { YAxis, CartesianGrid, Tooltip, + ResponsiveContainer, } from 'recharts'; import ChartTooltipContent from './chart-tooltip-content'; import Label from '../label'; @@ -64,10 +65,10 @@ interface LineChartProps { yAxisFontColor?: string; /** Width of the chart container. */ - chartWidth?: number; + chartWidth?: number | string; /** Height of the chart container. */ - chartHeight?: number; + chartHeight?: number | string; /** Determines whether dots are shown on each data point. */ withDots?: boolean; @@ -124,56 +125,59 @@ const LineChart = ( { } return ( - - { showCartesianGrid && } - { showXAxis && ( - - ) } - { showYAxis && ( - - ) } - - { showTooltip && ( - - } - /> - ) } - - { dataKeys.map( ( key, index ) => ( - - ) ) } - + + + { showCartesianGrid && } + { showXAxis && ( + + ) } + { showYAxis && ( + + ) } + + { showTooltip && ( + + } + /> + ) } + + { dataKeys.map( ( key, index ) => ( + + ) ) } + + ); }; diff --git a/src/components/select/component-style.ts b/src/components/select/component-style.ts index 967a2ec5..d6eaae5f 100644 --- a/src/components/select/component-style.ts +++ b/src/components/select/component-style.ts @@ -49,3 +49,11 @@ export const disabledClassNames = { icon: 'group-disabled:text-icon-disabled', text: 'group-disabled:text-field-color-disabled', }; + +export const optionGroupDividerClassNames = + 'h-px my-2 w-full border-border-subtle border-b border-t-0 border-solid'; +export const optionGroupDividerSizeClassNames = { + sm: 'w-[calc(100%+0.75rem)] translate-x-[-0.375rem]', + md: 'w-[calc(100%+1rem)] translate-x-[-0.5rem]', + lg: 'w-[calc(100%+1rem)] translate-x-[-0.5rem]', +}; diff --git a/src/components/select/select-atom.stories.tsx b/src/components/select/select-atom.stories.tsx index c514d367..de2ad67c 100644 --- a/src/components/select/select-atom.stories.tsx +++ b/src/components/select/select-atom.stories.tsx @@ -13,6 +13,32 @@ const options = [ { id: '8', name: 'Pink' }, ]; +const groupedOptions = [ + { + label: 'Warm Colors', + options: [ + { id: '1', name: 'Red' }, + { id: '2', name: 'Orange' }, + { id: '3', name: 'Yellow' }, + ], + }, + { + label: 'Cool Colors', + options: [ + { id: '4', name: 'Green' }, + { id: '5', name: 'Cyan' }, + { id: '6', name: 'Blue' }, + ], + }, + { + label: 'Other Colors', + options: [ + { id: '7', name: 'Purple' }, + { id: '8', name: 'Pink' }, + ], + }, +]; + const meta: Meta = { title: 'Atoms/Select', component: Select, @@ -21,6 +47,7 @@ const meta: Meta = { 'Select.Portal': Select.Portal, 'Select.Options': Select.Options, 'Select.Option': Select.Option, + 'Select.OptionGroup': Select.OptionGroup, } as Record>, parameters: { layout: 'centered', @@ -267,3 +294,76 @@ SelectWithSearchWithoutPortal.args = { combobox: true, disabled: false, }; + +const GroupedSelectTemplate: Story = ( { + size, + multiple, + combobox, + disabled, +} ) => ( +
+ +
+); + +export const GroupedSelect = GroupedSelectTemplate.bind( {} ); +GroupedSelect.args = { + size: 'md', + multiple: false, + combobox: false, + disabled: false, +}; + +export const GroupedSelectWithSearch = GroupedSelectTemplate.bind( {} ); +GroupedSelectWithSearch.args = { + size: 'md', + multiple: false, + combobox: true, + disabled: false, +}; + +GroupedSelect.play = async ( { canvasElement } ) => { + const canvas = within( canvasElement ); + const selectButton = await canvas.findByRole( 'combobox' ); + await userEvent.click( selectButton ); + + const listBox = await screen.findByRole( 'listbox' ); + expect( listBox ).toHaveTextContent( 'Warm Colors' ); + expect( listBox ).toHaveTextContent( 'Cool Colors' ); + expect( listBox ).toHaveTextContent( 'Red' ); + + const allOptions = await screen.findAllByRole( 'option' ); + await userEvent.click( allOptions[ 0 ] ); + + expect( selectButton ).toHaveTextContent( 'Red' ); +}; diff --git a/src/components/select/select-types.ts b/src/components/select/select-types.ts index c3325006..b3dc0da9 100644 --- a/src/components/select/select-types.ts +++ b/src/components/select/select-types.ts @@ -99,8 +99,17 @@ export interface SelectButtonProps extends AriaAttributes { className?: string; } +export interface SelectOptionGroupProps { + /** Label for the option group */ + label: string; + /** Children options */ + children: ReactNode; + /** Additional class name for the option group */ + className?: string; +} + export interface SelectOptionsProps { - /** Expects the `Select.Option` children of the Select.Options Component. */ + /** Expects the `Select.Option` or `Select.OptionGroup` children */ children?: ReactNode; /** Key used to identify searched value using the key. Default is 'id'. */ searchBy?: string; diff --git a/src/components/select/select.tsx b/src/components/select/select.tsx index d3d6ed02..8ff4caa8 100644 --- a/src/components/select/select.tsx +++ b/src/components/select/select.tsx @@ -10,6 +10,7 @@ import { isValidElement, useEffect, useLayoutEffect, + Fragment, } from 'react'; import { cn } from '@/utilities/functions'; import { CheckIcon, ChevronDown, ChevronsUpDown, Search } from 'lucide-react'; @@ -30,7 +31,12 @@ import { } from '@floating-ui/react'; import Badge from '../badge'; import { nanoid } from 'nanoid'; -import { disabledClassNames, sizeClassNames } from './component-style'; +import { + disabledClassNames, + optionGroupDividerClassNames, + optionGroupDividerSizeClassNames, + sizeClassNames, +} from './component-style'; import type { OnClick, OnKeyDown, @@ -43,6 +49,7 @@ import type { SelectPortalProps, SelectProps, SelectSizes, + SelectOptionGroupProps, } from './select-types'; // Context to manage the state of the select component. @@ -198,7 +205,7 @@ export function SelectButton( { }; return ( -
+
{ !! label && (