Skip to content

Commit

Permalink
Regression: Options overlapping input in Users Autocomplete (#26309)
Browse files Browse the repository at this point in the history
  • Loading branch information
gabriellsh authored Jul 20, 2022
1 parent b8097fa commit de983ec
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import React, { memo, ReactElement, useState, ComponentProps } from 'react';
import { useQuery } from 'react-query';

import UserAvatar from '../avatar/UserAvatar';
import renderOptions from './UserAutoCompleteMultipleOptions';
import AutocompleteOptions, { OptionsContext } from './UserAutoCompleteMultipleOptions';

type UserAutoCompleteMultipleFederatedProps = {
onChange: (value: Array<string>) => void;
Expand Down Expand Up @@ -67,27 +67,29 @@ const UserAutoCompleteMultipleFederated = ({
};

return (
<MultiSelectFiltered
placeholder={placeholder}
value={value}
onChange={onChange}
filter={filter}
setFilter={setFilter}
renderSelected={({ value, onMouseDown }: { value: string; onMouseDown: () => void }): ReactElement => {
const currentCachedOption = selectedCache[value];
<OptionsContext.Provider value={{ options, onSelect: onAddSelected }}>
<MultiSelectFiltered
placeholder={placeholder}
value={value}
onChange={onChange}
filter={filter}
setFilter={setFilter}
renderSelected={({ value, onMouseDown }: { value: string; onMouseDown: () => void }): ReactElement => {
const currentCachedOption = selectedCache[value];

return (
<Chip key={value} {...props} height='x20' onMouseDown={onMouseDown} mie='x4' mb='x2'>
{currentCachedOption._federated ? <Icon size='x20' name='globe' /> : <UserAvatar size='x20' username={value} />}
<Box is='span' margin='none' mis='x4'>
{currentCachedOption.name || currentCachedOption.username}
</Box>
</Chip>
);
}}
renderOptions={renderOptions(options, onAddSelected)}
options={options.concat(Object.entries(selectedCache)).map(([, item]) => [item.username, item.name || item.username])}
/>
return (
<Chip key={value} {...props} height='x20' onMouseDown={onMouseDown} mie='x4' mb='x2'>
{currentCachedOption._federated ? <Icon size='x20' name='globe' /> : <UserAvatar size='x20' username={value} />}
<Box is='span' margin='none' mis='x4'>
{currentCachedOption.name || currentCachedOption.username}
</Box>
</Chip>
);
}}
renderOptions={AutocompleteOptions}
options={options.concat(Object.entries(selectedCache)).map(([, item]) => [item.username, item.name || item.username])}
/>
</OptionsContext.Provider>
);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Options } from '@rocket.chat/fuselage';
import React, { forwardRef, ComponentProps, RefAttributes, ReactElement, Ref } from 'react';
import React, { forwardRef, ComponentProps, ReactElement, Ref, createContext, useContext } from 'react';

import { UserAutoCompleteOptionType } from './UserAutoCompleteMultipleFederated';
import UserAutoCompleteMultipleOption from './UserAutoCompleteMultipleOption';
Expand All @@ -9,26 +9,34 @@ type Options = Array<[UserAutoCompleteOptionType['username'], UserAutoCompleteOp
// This is a hack in order to bypass the MultiSelect filter.
// The select requires a forwarded ref component in the renderOptions property
// but we also need to pass internal state to this renderer, as well as the props that also come from the Select.
const renderOptions = (
options: Options,
onSelect: ComponentProps<typeof Options>['onSelect'],
): ((props: ComponentProps<typeof Options> & RefAttributes<HTMLElement>) => ReactElement | null) =>
forwardRef(function UserAutoCompleteMultipleOptions(
{ onSelect: _onSelect, ...props }: ComponentProps<typeof Options>,
ref: Ref<HTMLElement>,
): ReactElement {
return (
<Options
{...props}
options={options}
onSelect={(val): void => {
onSelect(val);
_onSelect(val);
}}
ref={ref}
renderItem={UserAutoCompleteMultipleOption}
/>
);
});

export default renderOptions;
type OptionsContextValue = {
options: ComponentProps<typeof Options>['options'];
onSelect: ComponentProps<typeof Options>['onSelect'];
};

export const OptionsContext = createContext<OptionsContextValue>({
options: [],
onSelect: () => undefined,
});
const UserAutoCompleteMultipleOptions = forwardRef(function UserAutoCompleteMultipleOptions(
{ onSelect: _onSelect, ...props }: ComponentProps<typeof Options>,
ref: Ref<HTMLElement>,
): ReactElement {
const { options, onSelect } = useContext(OptionsContext);
return (
<Options
{...props}
key='AutocompleteOptions'
options={options}
onSelect={(val): void => {
onSelect(val);
_onSelect(val);
}}
ref={ref}
renderItem={UserAutoCompleteMultipleOption}
/>
);
});

export default UserAutoCompleteMultipleOptions;

0 comments on commit de983ec

Please sign in to comment.