Skip to content

Commit

Permalink
refactor: ♻️ Improve UsersTableFilters and MultiSelectCustom components
Browse files Browse the repository at this point in the history
Changed the implementation of the new users table filters from a fully custom "Box based" code to a standardized use of the FilterByText component with children. Also improved the positioning and styling of the MultiSelectCustom by properly implementing the useOutsideClick and usePosition custom hooks together with reusing the fuselage button and input styles in the anchor of the component.
  • Loading branch information
rique223 committed Jun 24, 2024
1 parent 6176869 commit c6e5b7f
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 44 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import type { IRole } from '@rocket.chat/core-typings';
import { Box, Icon, TextInput } from '@rocket.chat/fuselage';
import { useBreakpoints } from '@rocket.chat/fuselage-hooks';
import type { OptionProp } from '@rocket.chat/ui-client';
import { MultiSelectCustom } from '@rocket.chat/ui-client';
import React, { useCallback, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';

import FilterByText from '../../../../components/FilterByText';
import type { UsersFilters } from '../AdminUsersPage';

type UsersTableFiltersProps = {
Expand All @@ -19,8 +20,7 @@ const UsersTableFilters = ({ roleData, setUsersFilters }: UsersTableFiltersProps
const [text, setText] = useState('');

const handleSearchTextChange = useCallback(
(event) => {
const text = event.currentTarget.value;
({ text }) => {
setUsersFilters({ text, roles: selectedRoles });
setText(text);
},
Expand Down Expand Up @@ -57,37 +57,21 @@ const UsersTableFilters = ({ roleData, setUsersFilters }: UsersTableFiltersProps
[roleData],
);

const breakpoints = useBreakpoints();
const fixFiltersSize = breakpoints.includes('lg') ? { maxWidth: 'x200', minWidth: 'x200' } : null;

return (
<Box
is='form'
onSubmit={useCallback((e) => e.preventDefault(), [])}
mb='x8'
display='flex'
flexWrap='wrap'
alignItems='center'
justifyContent='center'
>
<Box minWidth='x224' display='flex' m='x4' flexGrow={2}>
<TextInput
name='Search_Users'
alignItems='center'
placeholder={t('Search_Users')}
addon={<Icon name='magnifier' size='x20' />}
onChange={handleSearchTextChange}
value={text}
/>
</Box>
<Box minWidth='x224' m='x4'>
<MultiSelectCustom
dropdownOptions={userRolesFilterStructure}
defaultTitle='All_roles'
selectedOptionsTitle='Roles'
setSelectedOptions={handleRolesChange}
selectedOptions={selectedRoles}
searchBarText='Search_roles'
/>
</Box>
</Box>
<FilterByText shouldAutoFocus placeholder={t('Search_Users')} onChange={handleSearchTextChange}>
<MultiSelectCustom
dropdownOptions={userRolesFilterStructure}
defaultTitle='All_roles'
selectedOptionsTitle='Roles'
setSelectedOptions={handleRolesChange}
selectedOptions={selectedRoles}
searchBarText='Search_roles'
{...fixFiltersSize}
/>
</FilterByText>
);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Box } from '@rocket.chat/fuselage';
import { useOutsideClick, useToggle } from '@rocket.chat/fuselage-hooks';
import { Button } from '@rocket.chat/fuselage';
import { useToggle } from '@rocket.chat/fuselage-hooks';
import type { TranslationKey } from '@rocket.chat/ui-contexts';
import type { FormEvent, ReactElement, RefObject } from 'react';
import type { ComponentProps, FormEvent, ReactElement, RefObject } from 'react';
import { useCallback, useRef } from 'react';

import MultiSelectCustomAnchor from './MultiSelectCustomAnchor';
Expand Down Expand Up @@ -48,7 +48,7 @@ type DropDownProps = {
selectedOptions: OptionProp[];
setSelectedOptions: (roles: OptionProp[]) => void;
searchBarText?: TranslationKey;
};
} & ComponentProps<typeof Button>;

export const MultiSelectCustom = ({
dropdownOptions,
Expand All @@ -57,9 +57,9 @@ export const MultiSelectCustom = ({
selectedOptions,
setSelectedOptions,
searchBarText,
...props
}: DropDownProps): ReactElement => {
const reference = useRef<HTMLInputElement>(null);
const target = useRef<HTMLElement>(null);
const [collapsed, toggleCollapsed] = useToggle(false);

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

useOutsideClick([target], onClose);

const onSelect = (item: OptionProp, e?: FormEvent<HTMLElement>): void => {
e?.stopPropagation();
item.checked = !item.checked;
Expand All @@ -92,7 +90,7 @@ export const MultiSelectCustom = ({
const count = dropdownOptions.filter((option) => option.checked).length;

return (
<Box display='flex' flexGrow={1} position='relative'>
<>
<MultiSelectCustomAnchor
ref={reference}
collapsed={collapsed}
Expand All @@ -102,12 +100,13 @@ export const MultiSelectCustom = ({
selectedOptionsTitle={selectedOptionsTitle}
selectedOptionsCount={count}
maxCount={dropdownOptions.length}
{...props}
/>
{collapsed && (
<MultiSelectCustomListWrapper ref={target}>
<MultiSelectCustomListWrapper ref={reference} onClose={onClose}>
<MultiSelectCustomList options={dropdownOptions} onSelected={onSelect} searchBarText={searchBarText} />
</MultiSelectCustomListWrapper>
)}
</Box>
</>
);
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { css } from '@rocket.chat/css-in-js';
import { Box, Icon } from '@rocket.chat/fuselage';
import { Box, Icon, Palette } from '@rocket.chat/fuselage';
import type { TranslationKey } from '@rocket.chat/ui-contexts';
import { useTranslation } from '@rocket.chat/ui-contexts';
import type { ComponentProps } from 'react';
Expand Down Expand Up @@ -27,6 +27,7 @@ const MultiSelectCustomAnchor = forwardRef<HTMLElement, MultiSelectCustomAnchorP

return (
<Box
is='button'
ref={ref}
role='button'
tabIndex={0}
Expand All @@ -35,6 +36,11 @@ const MultiSelectCustomAnchor = forwardRef<HTMLElement, MultiSelectCustomAnchorP
alignItems='center'
h='x40'
className={['rcx-input-box__wrapper', customStyle].filter(Boolean)}
w='full'
pb={10}
pi={16}
color={isDirty ? Palette.text['font-default'].toString() : Palette.text['font-annotation'].toString()}
rcx-input-box
{...props}
>
{isDirty ? `${t(selectedOptionsTitle)} (${selectedOptionsCount})` : t(defaultTitle)}
Expand Down

0 comments on commit c6e5b7f

Please sign in to comment.