From 2d57ae8cbb5a69cf9ba65651feb15ecf7f019e7f Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Fri, 9 Dec 2022 16:37:00 +0100 Subject: [PATCH] feat: Add oneLine mode to AsyncSelect --- .../components/Select/AsyncSelect.stories.tsx | 9 ++++ .../components/Select/AsyncSelect.test.tsx | 48 +++++++++++++++++++ .../src/components/Select/AsyncSelect.tsx | 17 ++++++- 3 files changed, 73 insertions(+), 1 deletion(-) diff --git a/superset-frontend/src/components/Select/AsyncSelect.stories.tsx b/superset-frontend/src/components/Select/AsyncSelect.stories.tsx index 547fc7fa994e9..0bdaf43f2c06f 100644 --- a/superset-frontend/src/components/Select/AsyncSelect.stories.tsx +++ b/superset-frontend/src/components/Select/AsyncSelect.stories.tsx @@ -123,6 +123,15 @@ const ARG_TYPES = { By default label and value. `, }, + oneLine: { + defaultValue: false, + description: `Sets maxTagCount to 1. The overflow tag is always displayed in + the same line, line wrapping is disabled. + When the dropdown is open, sets maxTagCount to 0, + displays only the overflow tag. + Requires '"mode=multiple"'. + `, + }, }; const USERS = [ diff --git a/superset-frontend/src/components/Select/AsyncSelect.test.tsx b/superset-frontend/src/components/Select/AsyncSelect.test.tsx index b11dcde017c48..ac9c78767c4ae 100644 --- a/superset-frontend/src/components/Select/AsyncSelect.test.tsx +++ b/superset-frontend/src/components/Select/AsyncSelect.test.tsx @@ -756,6 +756,54 @@ test('finds an element with a numeric value and does not duplicate the options', expect(await querySelectOption('11')).not.toBeInTheDocument(); }); +test('Renders only 1 tag and an overflow tag in oneLine mode', () => { + render( + , + ); + expect(screen.getByText(OPTIONS[0].label)).toBeVisible(); + expect(screen.queryByText(OPTIONS[1].label)).not.toBeInTheDocument(); + expect(screen.queryByText(OPTIONS[2].label)).not.toBeInTheDocument(); + expect(screen.getByText('+ 2 ...')).toBeVisible(); +}); + +test('Renders only an overflow tag if dropdown is open in oneLine mode', async () => { + render( + , + ); + await open(); + + const withinSelector = within(getElementByClassName('.ant-select-selector')); + await waitFor(() => { + expect( + withinSelector.queryByText(OPTIONS[0].label), + ).not.toBeInTheDocument(); + expect( + withinSelector.queryByText(OPTIONS[1].label), + ).not.toBeInTheDocument(); + expect( + withinSelector.queryByText(OPTIONS[2].label), + ).not.toBeInTheDocument(); + expect(withinSelector.getByText('+ 3 ...')).toBeVisible(); + }); + + await type('{esc}'); + + expect(await withinSelector.findByText(OPTIONS[0].label)).toBeVisible(); + expect(withinSelector.queryByText(OPTIONS[1].label)).not.toBeInTheDocument(); + expect(withinSelector.queryByText(OPTIONS[2].label)).not.toBeInTheDocument(); + expect(withinSelector.getByText('+ 2 ...')).toBeVisible(); +}); + /* TODO: Add tests that require scroll interaction. Needs further investigation. - Fetches more data when scrolling and more data is available diff --git a/superset-frontend/src/components/Select/AsyncSelect.tsx b/superset-frontend/src/components/Select/AsyncSelect.tsx index 71474a341c907..5cbd193c56483 100644 --- a/superset-frontend/src/components/Select/AsyncSelect.tsx +++ b/superset-frontend/src/components/Select/AsyncSelect.tsx @@ -71,6 +71,7 @@ import { TOKEN_SEPARATORS, DEFAULT_SORT_COMPARATOR, } from './constants'; +import { oneLineTagRender } from './CustomTag'; const Error = ({ error }: { error: string }) => ( @@ -125,6 +126,8 @@ const AsyncSelect = forwardRef( tokenSeparators, value, getPopupContainer, + oneLine, + maxTagCount: propsMaxTagCount, ...props }: AsyncSelectProps, ref: RefObject, @@ -148,6 +151,16 @@ const AsyncSelect = forwardRef( : 'multiple'; const allowFetch = !fetchOnlyOnSearch || inputValue; + const [maxTagCount, setMaxTagCount] = useState( + propsMaxTagCount ?? MAX_TAG_COUNT, + ); + + useEffect(() => { + if (oneLine) { + setMaxTagCount(isDropdownVisible ? 0 : 1); + } + }, [isDropdownVisible, oneLine]); + useEffect(() => { selectValueRef.current = selectValue; }, [selectValue]); @@ -487,7 +500,7 @@ const AsyncSelect = forwardRef( } headerPosition={headerPosition} labelInValue - maxTagCount={MAX_TAG_COUNT} + maxTagCount={maxTagCount} mode={mappedMode} notFoundContent={isLoading ? t('Loading...') : notFoundContent} onDeselect={handleOnDeselect} @@ -513,6 +526,8 @@ const AsyncSelect = forwardRef( ) } + oneLine={oneLine} + tagRender={oneLine ? oneLineTagRender : undefined} {...props} ref={ref} >