Skip to content

Commit

Permalink
regression: custom multi select broken layout and fowardRef error (#3…
Browse files Browse the repository at this point in the history
…0215)

Co-authored-by: Guilherme Gazzo <[email protected]>
  • Loading branch information
hugocostadev and ggazzo authored Aug 30, 2023
1 parent 93d5a5c commit 2e2a89e
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 47 deletions.
1 change: 1 addition & 0 deletions apps/meteor/client/views/admin/rooms/RoomsTableFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ const RoomsTableFilters = ({ setFilters }: { setFilters: Dispatch<SetStateAction
>
<Box minWidth='x224' display='flex' m='x4' flexGrow={2}>
<TextInput
name='search-rooms'
alignItems='center'
placeholder={t('Search_rooms')}
addon={<Icon name='magnifier' size='x20' />}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Box } from '@rocket.chat/fuselage';
import { useToggle } from '@rocket.chat/fuselage-hooks';
import { useOutsideClick, useToggle } from '@rocket.chat/fuselage-hooks';
import type { TranslationKey } from '@rocket.chat/ui-contexts';
import type { Dispatch, FormEvent, ReactElement, RefObject, SetStateAction } from 'react';
import { useCallback, useRef } from 'react';
Expand Down Expand Up @@ -53,8 +53,8 @@ export type OptionProp = TitleOptionProp | CheckboxOptionProp;
*/
type DropDownProps = {
dropdownOptions: OptionProp[];
defaultTitle: TranslationKey; // For example: 'All rooms'
selectedOptionsTitle: TranslationKey; // For example: 'Rooms (3)'
defaultTitle: TranslationKey;
selectedOptionsTitle: TranslationKey;
selectedOptions: OptionProp[];
setSelectedOptions: Dispatch<SetStateAction<OptionProp[]>>;
customSetSelected: Dispatch<SetStateAction<OptionProp[]>>;
Expand All @@ -70,7 +70,8 @@ export const MultiSelectCustom = ({
customSetSelected,
searchBarText,
}: DropDownProps): ReactElement => {
const reference = useRef<HTMLButtonElement>(null);
const reference = useRef<HTMLInputElement>(null);
const target = useRef<HTMLElement>(null);
const [collapsed, toggleCollapsed] = useToggle(false);

const onClose = useCallback(
Expand All @@ -85,6 +86,8 @@ export const MultiSelectCustom = ({
[toggleCollapsed],
);

useOutsideClick([target], onClose);

const onSelect = (item: OptionProp, e?: FormEvent<HTMLElement>): void => {
e?.stopPropagation();

Expand Down Expand Up @@ -123,7 +126,7 @@ export const MultiSelectCustom = ({
maxCount={dropdownOptions.length}
/>
{collapsed && (
<MultiSelectCustomListWrapper ref={reference} onClose={onClose}>
<MultiSelectCustomListWrapper ref={target}>
<MultiSelectCustomList options={dropdownOptions} onSelected={onSelect} searchBarText={searchBarText} />
</MultiSelectCustomListWrapper>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type MultiSelectCustomAnchorProps = {
maxCount: number;
} & ComponentProps<typeof Button>;

const MultiSelectCustomAnchor = forwardRef<HTMLButtonElement, MultiSelectCustomAnchorProps>(function MultiSelectCustomAnchor(
const MultiSelectCustomAnchor = forwardRef<HTMLElement, MultiSelectCustomAnchorProps>(function MultiSelectCustomAnchor(
{ onClick, collapsed, selectedOptionsCount, selectedOptionsTitle, defaultTitle, maxCount, ...props },
ref,
) {
Expand All @@ -26,36 +26,42 @@ const MultiSelectCustomAnchor = forwardRef<HTMLButtonElement, MultiSelectCustomA
&:hover,
&:active,
&:focus {
border-color: ${Palette.stroke['stroke-highlight'].toString()};
border-width: 2px;
cursor: pointer;
border-color: ${Palette.stroke['stroke-highlight'].toString()}!important;
box-shadow: 0 0 0 2px ${Palette.shadow['shadow-highlight'].toString()};
}
`
: '';
: css`
& {
cursor: pointer;
}
`;

const isDirty = selectedOptionsCount > 0 && selectedOptionsCount !== maxCount - 1;

return (
<Button
<Box
ref={ref}
onClick={onClick}
display='flex'
justifyContent='space-between'
alignItems='center'
flexDirection='row'
flexGrow='1'
flexShrink='1'
borderColor='none'
borderColor={Palette.stroke['stroke-light'].toString()}
borderWidth='x1'
bg='surface-light'
borderRadius={4}
bg={Palette.surface['surface-light'].toString()}
h='x40'
w='full'
pb={10}
pi={16}
color={isDirty ? Palette.text['font-default'].toString() : Palette.text['font-annotation'].toString()}
className={inputStyle}
{...props}
>
{selectedOptionsCount > 0 && selectedOptionsCount !== maxCount - 1
? `${t(selectedOptionsTitle)} (${selectedOptionsCount})`
: t(defaultTitle)}
<Box mi='x4' display='flex' alignItems='center' justifyContent='center'>
<Icon name='chevron-down' fontSize='x20' color='hint' />
</Box>
</Button>
{isDirty ? `${t(selectedOptionsTitle)} (${selectedOptionsCount})` : t(defaultTitle)}
<Icon name='chevron-down' fontSize='x20' color='hint' />
</Box>
);
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Box, CheckBox, Icon, Option, TextInput, Tile } from '@rocket.chat/fuselage';
import { Box, CheckBox, Icon, Option, SearchInput, Tile } from '@rocket.chat/fuselage';
import type { TranslationKey } from '@rocket.chat/ui-contexts';
import { useTranslation } from '@rocket.chat/ui-contexts';
import type { FormEvent } from 'react';
Expand Down Expand Up @@ -31,15 +31,14 @@ const MultiSelectCustomList = ({
<Tile overflow='auto' pb='x12' pi={0} elevation='2' w='full' bg='light' borderRadius='x2'>
{searchBarText && (
<Option>
<Box mi='x8' mbs='x4' display='flex' flexWrap='wrap' alignItems='center'>
<TextInput
flexGrow={2}
placeholder={t(searchBarText)}
addon={<Icon name='magnifier' size='x20' />}
onChange={handleChange}
value={text}
/>
</Box>
<SearchInput
name='select-search'
placeholder={t(searchBarText)}
autoComplete='off'
addon={<Icon name='magnifier' size='x20' />}
onChange={handleChange}
value={text}
/>
</Option>
)}
{filteredOptions.map((option) => (
Expand All @@ -53,7 +52,7 @@ const MultiSelectCustomList = ({
<Box pis='x4' pb='x4' w='full' display='flex' justifyContent='space-between'>
{t(option.text as TranslationKey)}

<CheckBox checked={option.checked} onChange={(e): void => onSelected(option, e)} pi={0} />
<CheckBox checked={option.checked} onChange={(e): void => onSelected(option, e)} pi={0} name={option.text} />
</Box>
</Option>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
import { Box } from '@rocket.chat/fuselage';
import { useOutsideClick } from '@rocket.chat/fuselage-hooks';
import type { ComponentProps } from 'react';
import { forwardRef, useRef } from 'react';
import { forwardRef, type ComponentProps } from 'react';

const MultiSelectCustomListWrapper = forwardRef<Element, ComponentProps<typeof Box> & { onClose: (e: MouseEvent) => void }>(
function MultiSelectCustomListWrapper({ children, onClose }) {
const target = useRef<HTMLElement>(null);
useOutsideClick([target], onClose);

return (
<Box ref={target} zIndex='99999' w='full' position='absolute' mbs='x40' pbs='x4'>
{children}
</Box>
);
},
);
const MultiSelectCustomListWrapper = forwardRef<Element, ComponentProps<typeof Box>>(function MultiSelectCustomListWrapper(
{ children },
ref,
) {
return (
<Box ref={ref} zIndex='2' w='full' position='absolute' mbs={40} pbs={4}>
{children}
</Box>
);
});

export default MultiSelectCustomListWrapper;

0 comments on commit 2e2a89e

Please sign in to comment.