From b6bcefc4e81f5ad3adf01a1771bea163f68f05f5 Mon Sep 17 00:00:00 2001 From: Marcin Sawicki Date: Wed, 8 Feb 2023 15:27:04 +0100 Subject: [PATCH 1/4] fixes for Picker component --- .../src/components/Picker/Picker.tsx | 3 ++- .../src/components/Picker/PickerList.module.scss | 8 +++++++- .../src/components/Picker/PickerList.tsx | 4 +++- .../src/components/Picker/TriggerBody.module.scss | 7 +++++++ .../src/components/Picker/TriggerBody.tsx | 14 +++++++++++--- 5 files changed, 30 insertions(+), 6 deletions(-) diff --git a/packages/react-components/src/components/Picker/Picker.tsx b/packages/react-components/src/components/Picker/Picker.tsx index 04acd3d19..47a9b302b 100644 --- a/packages/react-components/src/components/Picker/Picker.tsx +++ b/packages/react-components/src/components/Picker/Picker.tsx @@ -120,7 +120,7 @@ export const Picker: React.FC = ({ return onSelect(null); } - const newSelectedItems = items.filter((item) => + const newSelectedItems = options.filter((item) => newSelectedItemsKeys.includes(item.key) ); @@ -208,6 +208,7 @@ export const Picker: React.FC = ({ = ({ })} onClick={() => !item.disabled && handleOnClick(item)} > - {getOptionContent(item)} +
+ {getOptionContent(item)} +
{isItemSelected(item.key) && } ); diff --git a/packages/react-components/src/components/Picker/TriggerBody.module.scss b/packages/react-components/src/components/Picker/TriggerBody.module.scss index 76a749a5f..8fb6d5764 100644 --- a/packages/react-components/src/components/Picker/TriggerBody.module.scss +++ b/packages/react-components/src/components/Picker/TriggerBody.module.scss @@ -6,6 +6,13 @@ $base-class: 'picker-trigger-body'; gap: 4px; justify-content: flex-start; + &__item { + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + &__input { display: flex; flex-grow: 2; diff --git a/packages/react-components/src/components/Picker/TriggerBody.tsx b/packages/react-components/src/components/Picker/TriggerBody.tsx index f9201d113..ce4bd62f3 100644 --- a/packages/react-components/src/components/Picker/TriggerBody.tsx +++ b/packages/react-components/src/components/Picker/TriggerBody.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import cx from 'clsx'; import { IPickerListItem } from './PickerList'; import { Tag } from '../Tag'; @@ -12,6 +13,7 @@ const baseClass = 'picker-trigger-body'; export interface ITriggerBodyProps { isOpen: boolean; isSearchDisabled?: boolean; + isDisabled?: boolean; placeholder: string; items?: IPickerListItem[] | null; type: PickerType; @@ -23,6 +25,7 @@ export interface ITriggerBodyProps { export const TriggerBody: React.FC = ({ isOpen, isSearchDisabled, + isDisabled, placeholder, items, type, @@ -30,6 +33,11 @@ export const TriggerBody: React.FC = ({ onItemRemove, onFilter, }) => { + const mergedClassNames = cx( + styles[baseClass], + type === 'multi' && styles[`${baseClass}--multi`] + ); + const shouldDisplaySearch = isOpen && !isSearchDisabled; const getSingleItem = (item: IPickerListItem) => { @@ -45,7 +53,7 @@ export const TriggerBody: React.FC = ({ ); } - return item.name; + return
{item.name}
; }; const handleOnChange = (e: React.ChangeEvent) => { @@ -66,7 +74,7 @@ export const TriggerBody: React.FC = ({ } return ( -
+
{type === 'single' ? getSingleItem(items[0]) : items.map((item) => { @@ -75,7 +83,7 @@ export const TriggerBody: React.FC = ({ key={item.name} className={styles[`${baseClass}__tag`]} iconSize={iconSize} - dismissible + dismissible={!isDisabled} onRemove={() => onItemRemove(item)} > {getSingleItem(item)} From b4ec70b0fbff6d1368f8840e2c250aaf65f71fe1 Mon Sep 17 00:00:00 2001 From: Marcin Sawicki Date: Wed, 8 Feb 2023 16:08:16 +0100 Subject: [PATCH 2/4] fixes for tests --- .../src/components/Picker/PickerList.spec.tsx | 8 ++++---- .../react-components/src/components/Picker/PickerList.tsx | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/react-components/src/components/Picker/PickerList.spec.tsx b/packages/react-components/src/components/Picker/PickerList.spec.tsx index b46575ae2..168a0538e 100644 --- a/packages/react-components/src/components/Picker/PickerList.spec.tsx +++ b/packages/react-components/src/components/Picker/PickerList.spec.tsx @@ -53,23 +53,23 @@ describe(' component', () => { }); it('should mark selected list item as selected', () => { - const { getByText } = renderComponent({ + const { getByTestId } = renderComponent({ ...defaultProps, isOpen: true, selectedItemsKeys: ['three'], }); - expect(getByText('Option three')).toHaveAttribute('aria-selected', 'true'); + expect(getByTestId('three')).toHaveAttribute('aria-selected', 'true'); }); it('should mark selected list item as disabled', () => { - const { getByText } = renderComponent({ + const { getByTestId } = renderComponent({ ...defaultProps, isOpen: true, items: [{ key: 'three', name: 'Option three', disabled: true }], }); - expect(getByText('Option three')).toHaveAttribute('aria-disabled', 'true'); + expect(getByTestId('three')).toHaveAttribute('aria-disabled', 'true'); }); it('should display default empty state if no filter result', () => { diff --git a/packages/react-components/src/components/Picker/PickerList.tsx b/packages/react-components/src/components/Picker/PickerList.tsx index e45965148..3ef13bd0f 100644 --- a/packages/react-components/src/components/Picker/PickerList.tsx +++ b/packages/react-components/src/components/Picker/PickerList.tsx @@ -224,6 +224,7 @@ export const PickerList: React.FC = ({ return (
  • { if (currentItemKey === item.key) { element?.scrollIntoView({ block: 'nearest' }); From 5a20be4d16f9eb6bec85c22232e19e26b391b943 Mon Sep 17 00:00:00 2001 From: Marcin Sawicki Date: Thu, 9 Feb 2023 08:40:08 +0100 Subject: [PATCH 3/4] small change --- .../react-components/src/components/Picker/TriggerBody.tsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/react-components/src/components/Picker/TriggerBody.tsx b/packages/react-components/src/components/Picker/TriggerBody.tsx index ce4bd62f3..5a99d4119 100644 --- a/packages/react-components/src/components/Picker/TriggerBody.tsx +++ b/packages/react-components/src/components/Picker/TriggerBody.tsx @@ -33,11 +33,6 @@ export const TriggerBody: React.FC = ({ onItemRemove, onFilter, }) => { - const mergedClassNames = cx( - styles[baseClass], - type === 'multi' && styles[`${baseClass}--multi`] - ); - const shouldDisplaySearch = isOpen && !isSearchDisabled; const getSingleItem = (item: IPickerListItem) => { @@ -74,7 +69,7 @@ export const TriggerBody: React.FC = ({ } return ( -
    +
    {type === 'single' ? getSingleItem(items[0]) : items.map((item) => { From c1f3590f9aa064b32c2b2d4be3d06b2244cc8d29 Mon Sep 17 00:00:00 2001 From: Marcin Sawicki Date: Fri, 10 Feb 2023 17:12:54 +0100 Subject: [PATCH 4/4] refactored stories for picker component --- .../src/components/Picker/Picker.stories.tsx | 200 +++++++----------- 1 file changed, 78 insertions(+), 122 deletions(-) diff --git a/packages/react-components/src/components/Picker/Picker.stories.tsx b/packages/react-components/src/components/Picker/Picker.stories.tsx index 0c7e2d254..b968d5c5a 100644 --- a/packages/react-components/src/components/Picker/Picker.stories.tsx +++ b/packages/react-components/src/components/Picker/Picker.stories.tsx @@ -1,104 +1,122 @@ import * as React from 'react'; import { ComponentMeta, Story } from '@storybook/react'; -import { IPickerProps, Picker as PickerComponent } from './Picker'; +import { IPickerProps, Picker } from './Picker'; import { defaultExtendedOptions, defaultOptions } from './constants'; import { IPickerListItem } from './PickerList'; import './Picker.stories.css'; +import { StoryDescriptor } from '../../stories/components/StoryDescriptor'; export default { title: 'Components/Picker', - component: PickerComponent, + component: Picker, parameters: { componentSubtitle: `TBD`, }, argTypes: { onSelect: { action: 'changed' }, }, -} as ComponentMeta; +} as ComponentMeta; -const StoryTemplate: Story = (args: IPickerProps) => { +const commonWidth: React.CSSProperties = { width: 300 }; + +const PickerComponent = (args: IPickerProps) => { const [selectedItems, setSelectedItems] = React.useState< IPickerListItem[] | null >(args.selected || null); return ( -
    - setSelectedItems(items)} - /> -
    + setSelectedItems(items)} + /> ); }; -export const Picker = StoryTemplate.bind({}); -Picker.args = { - options: defaultOptions, -}; - -export const PickerWithLabel = StoryTemplate.bind({}); -PickerWithLabel.args = { - options: defaultOptions, - label: 'Picker', +const StoryTemplate: Story = (args: IPickerProps) => { + return ( +
    + +
    + ); }; -export const PickerWithError = StoryTemplate.bind({}); -PickerWithError.args = { +export const Default = StoryTemplate.bind({}); +Default.args = { options: defaultOptions, - error: 'Error message', }; -export const DisabledPicker = StoryTemplate.bind({}); -DisabledPicker.args = { +export const States = (args: IPickerProps): React.ReactElement => ( +
    + + + + + + + + + + + + + + + + + + + + + +
    +); +States.args = { options: defaultOptions, - disabled: true, + label: 'Example label', }; -export const PickerWithGroupedOptions = StoryTemplate.bind({}); -PickerWithGroupedOptions.args = { - options: defaultExtendedOptions, -}; - -export const PickerWithDisabledSearch = StoryTemplate.bind({}); -PickerWithDisabledSearch.args = { - searchDisabled: true, - options: defaultExtendedOptions, -}; - -export const PickerWithSelectedOption = StoryTemplate.bind({}); -PickerWithSelectedOption.args = { - selected: [{ key: 'two', name: 'Option two' }], - options: defaultExtendedOptions, -}; - -export const PickerInMultiselectMode = StoryTemplate.bind({}); -PickerInMultiselectMode.args = { - type: 'multi', - options: defaultExtendedOptions, - selectAllOptionText: 'Select all', -}; - -export const PickerInMultiselectModeWithSelectedOptions = StoryTemplate.bind( - {} +export const PickerWithGroupedOptions = ( + args: IPickerProps +): React.ReactElement => ( +
    + +
    ); -PickerInMultiselectModeWithSelectedOptions.args = { - selected: [ - { key: 'two', name: 'Option two' }, - { key: 'four', name: 'Option four' }, - ], - type: 'multi', +PickerWithGroupedOptions.args = { options: defaultExtendedOptions, - selectAllOptionText: 'Select all', }; const CustomPickerOption: React.FC = ({ children }) => (
    {children}
    ); -export const PickerWithOptionsAsCustomElements = StoryTemplate.bind({}); +export const PickerWithOptionsAsCustomElements = ( + args: IPickerProps +): React.ReactElement => ( +
    + + + + + + +
    +); PickerWithOptionsAsCustomElements.args = { options: [ { @@ -157,65 +175,3 @@ PickerWithOptionsAsCustomElements.args = { }, ], }; - -export const PickerInMultiselectModeWithOptionsAsCustomElements = - StoryTemplate.bind({}); -PickerInMultiselectModeWithOptionsAsCustomElements.args = { - type: 'multi', - options: [ - { - key: 'one', - name: 'Example custom element one', - customElement: { - listItemBody: ( - - -
    -
    Example custom element one
    -
    Example custom element
    -
    -
    - ), - selectedItemBody: ( - - -
    Example custom element one
    -
    - ), - }, - }, - { - key: 'two', - name: 'Example custom element two', - customElement: { - listItemBody: ( - - -
    -
    Example custom element two
    -
    Example custom element
    -
    -
    - ), - selectedItemBody: ( - - -
    Example custom element two
    -
    - ), - }, - }, - ], -};