From e121ad06ef05b1093052ea9780f36d402623656a Mon Sep 17 00:00:00 2001 From: Douglas Fabris Date: Wed, 20 Jul 2022 17:07:29 -0300 Subject: [PATCH] fix(fuselage): Select/MultiSelect options visibility (#759) --- .../fuselage-hooks/src/useOutsideClick.ts | 2 +- .../components/MultiSelect/MultiSelect.tsx | 37 ++++++++++++------- .../MultiSelect/MultiSelectFiltered.tsx | 1 + .../PaginatedSelect/PaginatedSelect.tsx | 27 ++++++++------ .../PaginatedSelect/PaginatedSelectAddon.tsx | 15 -------- .../PaginatedSelect/PaginatedSelectFocus.tsx | 25 ------------- .../src/components/Select/Select.spec.tsx | 8 ++-- .../src/components/Select/Select.stories.tsx | 2 +- .../fuselage/src/components/Select/Select.tsx | 19 +++++++--- .../src/components/Select/SelectAddon.tsx | 2 - .../src/components/Select/SelectFocus.tsx | 2 - .../src/components/Select/styles.scss | 1 + 12 files changed, 63 insertions(+), 78 deletions(-) delete mode 100644 packages/fuselage/src/components/PaginatedSelect/PaginatedSelectAddon.tsx delete mode 100644 packages/fuselage/src/components/PaginatedSelect/PaginatedSelectFocus.tsx diff --git a/packages/fuselage-hooks/src/useOutsideClick.ts b/packages/fuselage-hooks/src/useOutsideClick.ts index 6a5b89bc7f..69098d2b2b 100644 --- a/packages/fuselage-hooks/src/useOutsideClick.ts +++ b/packages/fuselage-hooks/src/useOutsideClick.ts @@ -10,7 +10,7 @@ import { useMutableCallback } from './useMutableCallback'; * @public */ -export function useOutsideClick( +export function useOutsideClick( elements: RefObject[], cb: (e: MouseEvent) => void ): void { diff --git a/packages/fuselage/src/components/MultiSelect/MultiSelect.tsx b/packages/fuselage/src/components/MultiSelect/MultiSelect.tsx index 021a97ac21..01e466b12e 100644 --- a/packages/fuselage/src/components/MultiSelect/MultiSelect.tsx +++ b/packages/fuselage/src/components/MultiSelect/MultiSelect.tsx @@ -2,6 +2,7 @@ import { useMergedRefs, useMutableCallback, useResizeObserver, + useOutsideClick, } from '@rocket.chat/fuselage-hooks'; import type { ComponentProps, @@ -50,6 +51,7 @@ type MultiSelectProps = Omit< renderItem?: ElementType; renderSelected?: ElementType; addonIcon?: ComponentProps['name']; + setFilter?: (filter: string) => void; }; export const MultiSelect = forwardRef( @@ -57,6 +59,7 @@ export const MultiSelect = forwardRef( { value, filter, + setFilter, options = [], error, disabled, @@ -79,14 +82,13 @@ export const MultiSelect = forwardRef( ); const [currentOptionValue, setCurrentOption] = useState(); - const option = options.find( - (option) => getValue(option) === currentOptionValue - ); - const index = options.findIndex( (option) => getValue(option) === currentOptionValue ); + const removeFocusClass = () => + innerRef.current?.classList.remove('focus-visible'); + const internalChanged = ([value]: SelectOption) => { if (internalValue.includes(value)) { setCurrentOption(undefined); @@ -94,6 +96,7 @@ export const MultiSelect = forwardRef( setInternalValue(newValue); return onChange(newValue); } + setFilter?.(''); setCurrentOption(value); const newValue = [...internalValue, value]; setInternalValue(newValue); @@ -123,6 +126,7 @@ export const MultiSelect = forwardRef( const anchorRef = useMergedRefs(ref, innerRef); const { ref: containerRef, borderBoxSize } = useResizeObserver(); + useOutsideClick([containerRef], removeFocusClass); const renderAnchor = (params: MultiSelectAnchorParams) => { if (isForwardRefType(Anchor)) { @@ -138,19 +142,24 @@ export const MultiSelect = forwardRef( return null; }; + const handleClick = useMutableCallback(() => { + if (innerRef.current?.classList.contains('focus-visible')) { + removeFocusClass(); + return hide(); + } + + innerRef.current?.classList.add('focus-visible'); + innerRef.current?.focus(); + return show(); + }); + return ( { - if (visible === AnimatedVisibility.VISIBLE) { - return hide(); - } - innerRef.current?.focus(); - return show(); - })} + onClick={handleClick} disabled={disabled} {...props} > @@ -169,7 +178,7 @@ export const MultiSelect = forwardRef( {renderAnchor({ ref: anchorRef, - children: !value ? option || placeholder : null, + children: internalValue.length === 0 ? placeholder : null, disabled: disabled ?? false, onClick: show, onBlur: hide, @@ -189,6 +198,7 @@ export const MultiSelect = forwardRef( onMouseDown={(e: SyntheticEvent) => { prevent(e); internalChanged(currentOption); + removeFocusClass(); }} children={getLabel(currentOption)} /> @@ -200,6 +210,7 @@ export const MultiSelect = forwardRef( onMouseDown={(e: SyntheticEvent) => { prevent(e); internalChanged(currentOption); + removeFocusClass(); }} children={getLabel(currentOption)} /> @@ -218,7 +229,7 @@ export const MultiSelect = forwardRef( ( {}, placeholder = '', renderOptions: _Options = OptionsPaginated, @@ -136,14 +137,18 @@ export const PaginatedSelect = ({ onClick={show} onBlur={hide} /> - - - + + + + + <_Options diff --git a/packages/fuselage/src/components/PaginatedSelect/PaginatedSelectAddon.tsx b/packages/fuselage/src/components/PaginatedSelect/PaginatedSelectAddon.tsx deleted file mode 100644 index 0331283c2e..0000000000 --- a/packages/fuselage/src/components/PaginatedSelect/PaginatedSelectAddon.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import type { ComponentProps, Ref } from 'react'; -import React, { forwardRef } from 'react'; - -import Box from '../Box'; - -type PaginatedSelectAddonProps = ComponentProps; - -const PaginatedSelectAddon = forwardRef(function PaginatedSelectAddon( - props: PaginatedSelectAddonProps, - ref: Ref -) { - return ; -}); - -export default PaginatedSelectAddon; diff --git a/packages/fuselage/src/components/PaginatedSelect/PaginatedSelectFocus.tsx b/packages/fuselage/src/components/PaginatedSelect/PaginatedSelectFocus.tsx deleted file mode 100644 index 7e12691b6c..0000000000 --- a/packages/fuselage/src/components/PaginatedSelect/PaginatedSelectFocus.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import type { ComponentProps, Ref } from 'react'; -import React, { forwardRef } from 'react'; - -import Box from '../Box'; - -type PaginatedSelectFocusProps = ComponentProps; - -const PaginatedSelectFocus = forwardRef(function PaginatedSelectFocus( - props: PaginatedSelectFocusProps, - ref: Ref -) { - return ( - - ); -}); - -export default PaginatedSelectFocus; diff --git a/packages/fuselage/src/components/Select/Select.spec.tsx b/packages/fuselage/src/components/Select/Select.spec.tsx index 10176ec77e..5f57450d4e 100644 --- a/packages/fuselage/src/components/Select/Select.spec.tsx +++ b/packages/fuselage/src/components/Select/Select.spec.tsx @@ -1,14 +1,16 @@ +import { composeStories } from '@storybook/testing-react'; import { render } from '@testing-library/react'; import React from 'react'; import { withResizeObserverMock } from 'testing-utils/mocks/withResizeObserverMock'; -import { Select } from '.'; -import { options } from './Select.stories'; +import * as stories from './Select.stories'; + +const { Default } = composeStories(stories); withResizeObserverMock(); describe('[Select Component]', () => { it('renders without crashing', () => { - render(