Skip to content

Commit

Permalink
fix(fuselage): Select/MultiSelect options visibility (#759)
Browse files Browse the repository at this point in the history
  • Loading branch information
dougfabris committed Jul 20, 2022
1 parent 79fdb3e commit e121ad0
Show file tree
Hide file tree
Showing 12 changed files with 63 additions and 78 deletions.
2 changes: 1 addition & 1 deletion packages/fuselage-hooks/src/useOutsideClick.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { useMutableCallback } from './useMutableCallback';
* @public
*/

export function useOutsideClick<T extends HTMLElement>(
export function useOutsideClick<T extends Element>(
elements: RefObject<T>[],
cb: (e: MouseEvent) => void
): void {
Expand Down
37 changes: 24 additions & 13 deletions packages/fuselage/src/components/MultiSelect/MultiSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
useMergedRefs,
useMutableCallback,
useResizeObserver,
useOutsideClick,
} from '@rocket.chat/fuselage-hooks';
import type {
ComponentProps,
Expand Down Expand Up @@ -50,13 +51,15 @@ type MultiSelectProps = Omit<
renderItem?: ElementType;
renderSelected?: ElementType;
addonIcon?: ComponentProps<typeof Icon>['name'];
setFilter?: (filter: string) => void;
};

export const MultiSelect = forwardRef(
(
{
value,
filter,
setFilter,
options = [],
error,
disabled,
Expand All @@ -79,21 +82,21 @@ export const MultiSelect = forwardRef(
);
const [currentOptionValue, setCurrentOption] = useState<SelectOption[0]>();

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);
const newValue = internalValue.filter((item) => item !== value);
setInternalValue(newValue);
return onChange(newValue);
}
setFilter?.('');
setCurrentOption(value);
const newValue = [...internalValue, value];
setInternalValue(newValue);
Expand Down Expand Up @@ -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)) {
Expand All @@ -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 (
<Box
is='div'
rcx-select
className={[error && 'invalid', disabled && 'disabled']}
ref={containerRef}
onClick={useMutableCallback(() => {
if (visible === AnimatedVisibility.VISIBLE) {
return hide();
}
innerRef.current?.focus();
return show();
})}
onClick={handleClick}
disabled={disabled}
{...props}
>
Expand All @@ -169,7 +178,7 @@ export const MultiSelect = forwardRef(
<Margins all='x4'>
{renderAnchor({
ref: anchorRef,
children: !value ? option || placeholder : null,
children: internalValue.length === 0 ? placeholder : null,
disabled: disabled ?? false,
onClick: show,
onBlur: hide,
Expand All @@ -189,6 +198,7 @@ export const MultiSelect = forwardRef(
onMouseDown={(e: SyntheticEvent) => {
prevent(e);
internalChanged(currentOption);
removeFocusClass();
}}
children={getLabel(currentOption)}
/>
Expand All @@ -200,6 +210,7 @@ export const MultiSelect = forwardRef(
onMouseDown={(e: SyntheticEvent) => {
prevent(e);
internalChanged(currentOption);
removeFocusClass();
}}
children={getLabel(currentOption)}
/>
Expand All @@ -218,7 +229,7 @@ export const MultiSelect = forwardRef(
<Icon
name={
visible === AnimatedVisibility.VISIBLE
? 'cross'
? 'chevron-up'
: addonIcon || 'chevron-down'
}
size='x20'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const MultiSelectFiltered = ({
<MultiSelect
{...props}
filter={propFilter || filter}
setFilter={propSetFilter || setFilter}
options={options}
anchor={(params: MultiSelectAnchorParams) => (
<MultiSelectFilteredAnchor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import type { SelectProps } from '..';
import AnimatedVisibility from '../AnimatedVisibility';
import Box from '../Box';
import { Icon } from '../Icon';
import Margins from '../Margins';
import { useVisible } from '../Options/useVisible';
import { OptionsPaginated } from '../OptionsPaginated';
import PositionAnimated from '../PositionAnimated';
import PaginatedSelectAddon from './PaginatedSelectAddon';
import PaginatedSelectFocus from './PaginatedSelectFocus';
import SelectAddon from '../Select/SelectAddon';
import SelectFocus from '../Select/SelectFocus';
import PaginatedSelectWrapper from './PaginatedSelectWrapper';

type PaginatedOptionType = {
Expand Down Expand Up @@ -55,7 +56,7 @@ export const PaginatedSelect = ({
error,
disabled,
options = [],
anchor: Anchor = PaginatedSelectFocus,
anchor: Anchor = SelectFocus,
onChange = () => {},
placeholder = '',
renderOptions: _Options = OptionsPaginated,
Expand Down Expand Up @@ -136,14 +137,18 @@ export const PaginatedSelect = ({
onClick={show}
onBlur={hide}
/>
<PaginatedSelectAddon mi='x4'>
<Icon
name={
visible === AnimatedVisibility.VISIBLE ? 'cross' : 'chevron-down'
}
size='x20'
/>
</PaginatedSelectAddon>
<Margins inline='x4'>
<SelectAddon>
<Icon
name={
visible === AnimatedVisibility.VISIBLE
? 'chevron-up'
: 'chevron-down'
}
size='x20'
/>
</SelectAddon>
</Margins>
</PaginatedSelectWrapper>
<PositionAnimated visible={visible} anchor={containerRef}>
<_Options
Expand Down

This file was deleted.

This file was deleted.

8 changes: 5 additions & 3 deletions packages/fuselage/src/components/Select/Select.spec.tsx
Original file line number Diff line number Diff line change
@@ -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(<Select options={options} onChange={() => undefined} />);
render(<Default {...Default.args} />);
});
});
2 changes: 1 addition & 1 deletion packages/fuselage/src/components/Select/Select.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import React from 'react';
import type { SelectOption } from '../..';
import { Select, SelectFiltered } from '../..';

export const options: SelectOption[] = Array.from({
const options: SelectOption[] = Array.from({
length: 10,
}).map((_, i) => [`${i + 1}`, `a teste ${i + 1}`]);

Expand Down
19 changes: 14 additions & 5 deletions packages/fuselage/src/components/Select/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
useMergedRefs,
useMutableCallback,
useResizeObserver,
useOutsideClick,
} from '@rocket.chat/fuselage-hooks';
import type {
ComponentProps,
Expand Down Expand Up @@ -115,15 +116,19 @@ export const Select = forwardRef(
const [cursor, handleKeyDown, handleKeyUp, reset, [visible, hide, show]] =
useCursor(index, filteredOptions, internalChangedByKeyboard);

const innerRef = useRef<HTMLInputElement | null>(null);
const anchorRef = useMergedRefs(ref, innerRef);

const removeFocusClass = () =>
innerRef.current?.classList.remove('focus-visible');

const internalChangedByClick = useMutableCallback(([value]) => {
setInternalValue(value);
onChange(value);
removeFocusClass();
hide();
});

const innerRef = useRef<HTMLInputElement | null>(null);
const anchorRef = useMergedRefs(ref, innerRef);

const renderAnchor = (params: SelectAnchorParams) => {
if (isForwardRefType(Anchor)) {
return <Anchor {...params} />;
Expand All @@ -139,6 +144,7 @@ export const Select = forwardRef(
const { ref: containerRef, borderBoxSize } = useResizeObserver();

useDidUpdate(reset, [filter, internalValue]);
useOutsideClick([containerRef], removeFocusClass);

const valueLabel = getLabel(option);

Expand All @@ -147,9 +153,12 @@ export const Select = forwardRef(
(valueLabel || placeholder || typeof placeholder === 'string');

const handleClick = useMutableCallback(() => {
if (visible === AnimatedVisibility.VISIBLE) {
if (innerRef.current?.classList.contains('focus-visible')) {
removeFocusClass();
return hide();
}

innerRef.current?.classList.add('focus-visible');
innerRef.current?.focus();
return show();
});
Expand Down Expand Up @@ -207,7 +216,7 @@ export const Select = forwardRef(
<Icon
name={
visible === AnimatedVisibility.VISIBLE
? 'cross'
? 'chevron-up'
: addonIcon || 'chevron-down'
}
size='x20'
Expand Down
2 changes: 0 additions & 2 deletions packages/fuselage/src/components/Select/SelectAddon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ import React, { forwardRef } from 'react';

import Box from '../Box';

export type SelectOptions = readonly [value: string, label: string][];

type AddonProps = ComponentProps<typeof Box>;

const SelectAddon = forwardRef(function SelectAddon(
Expand Down
2 changes: 0 additions & 2 deletions packages/fuselage/src/components/Select/SelectFocus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ import React, { forwardRef } from 'react';

import Box from '../Box';

export type SelectOptions = readonly [value: string, label: string][];

type SelectFocusProps = ComponentProps<typeof Box>;

const SelectFocus = forwardRef(function SelectFocus(
Expand Down
1 change: 1 addition & 0 deletions packages/fuselage/src/components/Select/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
}

&__wrapper {
align-items: center;
flex-grow: 1;
flex-shrink: 1;

Expand Down

0 comments on commit e121ad0

Please sign in to comment.