Skip to content

Commit

Permalink
[WNMGDS-2505] Fix react-aria's react support and remove downshift (#2667
Browse files Browse the repository at this point in the history
)

* Replace react-aria dependency with local copy

* Removed locales we don't need, and it shaved of 30k from our bundle

* Fix the Preact bug in react-aria

* Configure the doc site to build Preact storybook again

* Add comment explaining the fix

* Remove Downshift and references to it

Nonen of the documentation I removed seemed very useful, so I didn't bother rewriting it

* Fix bug where you could get it to show more items than it should

1. In the default example with all the drugs, type "ac" and select "Acetaminophen"
2. Arrow down and select that drug by pressing ENTER
3. Now type "c" at the end of the word
4. Previously you could see both "No results" and all the drugs (or just Acetaminophen), but with the fix, you should only see "No results"

* Don't make Preact the default for storybook build command right now

* Clear the text when clear search button is pressed too

now with this fix, it calls `onInputValueChange` with `""` where it didn’t in the previous version, but I actually think that’s more correct, especially for controlled components

* Give a clue about the origin of these imports
  • Loading branch information
pwolfert authored Sep 11, 2023
1 parent fe0b6d0 commit bee9773
Show file tree
Hide file tree
Showing 15 changed files with 7,252 additions and 109 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ packages/docs/static/**
packages/coverage/**
packages/design-system-tokens/sketch/cmsds-token-importer/cmsds-token-importer.sketchplugin/**
packages/design-system/scripts/cmsds-migrate/test/**
packages/design-system/src/components/react-aria/**
1 change: 0 additions & 1 deletion packages/design-system/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@
"classnames": "^2.2.5",
"core-js": "^3.6.5",
"date-fns": "^2.28.0",
"downshift": "^7.6.0",
"ev-emitter": "^1.1.1",
"focus-trap-react": "^10.0.0",
"lodash": "^4.17.21",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import DropdownMenu from '../Dropdown/DropdownMenu';
import classNames from 'classnames';
import mergeRefs from '../utilities/mergeRefs';
import useId from '../utilities/useId';
import { ComboBoxState, useComboBoxState } from 'react-stately';
import { errorPlacementDefault } from '../flags';
import {
renderReactStatelyItems,
Expand All @@ -13,7 +12,8 @@ import {
getActiveDescendant,
} from './utils';
import { t } from '../i18n';
import { useComboBox } from 'react-aria';
import { useComboBox } from '../react-aria'; // from react-aria
import { useComboBoxState } from '../react-aria'; // from react-stately

export interface AutocompleteItem extends Omit<React.HTMLAttributes<'option'>, 'name'> {
/**
Expand Down Expand Up @@ -80,8 +80,8 @@ export interface AutocompleteProps {
*/
id?: string;
/**
* Customize the default status messages announced to screen reader users via aria-live when autocomplete results are populated. [Read more on downshift docs.](https://github.com/downshift-js/downshift/tree/master/src/hooks/useCombobox#geta11ystatusmessage)
* @deprecated This is deprecated in favor of autoFocus
* Customize the default status messages announced to screen reader users via aria-live when autocomplete results are populated.
* @deprecated This is no longer used
* @hide-prop [Deprecated]
*/
getA11yStatusMessage?: any;
Expand Down Expand Up @@ -122,11 +122,11 @@ export interface AutocompleteProps {
*/
noResultsMessage?: React.ReactNode;
/**
* Called when the user selects an item and the selected item has changed. Called with the item that was selected and the new state. [Read more on downshift docs.](https://github.com/paypal/downshift#onchange)
* Called when the user selects an item and the selected item has changed. Called with the item that was selected.
*/
onChange?: (selectedItem: AutocompleteItem) => void;
/**
* Called when the child `TextField` value changes. Returns a String `inputValue`. [Read more on downshift docs.](https://github.com/downshift-js/downshift#oninputvaluechange)
* Called when the child `TextField` value changes. Is called with a string representing the input value.
*/
onInputValueChange?: (inputValue: string) => void;
}
Expand Down Expand Up @@ -278,7 +278,10 @@ export const Autocomplete = (props: AutocompleteProps) => {
className="ds-u-padding-right--0 ds-c-autocomplete__clear-btn"
onClick={() => {
state.setSelectedKey(null);
onChange?.(null);
state.setInputValue('');
if (state.selectedKey) {
onChange?.(null);
}
}}
size="small"
variation="ghost"
Expand Down
15 changes: 0 additions & 15 deletions packages/design-system/src/components/Autocomplete/WrapperDiv.tsx

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { default as Autocomplete } from './Autocomplete';
export * from './Autocomplete';
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { ReactElement, ReactNode } from 'react';
import { AutocompleteProps, AutocompleteItem } from './Autocomplete';
import { ComboBoxState, Item } from 'react-stately';
import { ComboBoxState, Item } from '../react-aria'; // from react-stately
import { TextField } from '../TextField';
import { getOptionId } from '../Dropdown/DropdownMenuOption';

Expand Down
4 changes: 2 additions & 2 deletions packages/design-system/src/components/Dropdown/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import useAutofocus from '../utilities/useAutoFocus';
import { FormFieldProps, FormLabel, useFormLabel } from '../FormLabel';
import { SvgIcon } from '../Icons';
import { getFirstOptionValue, isOptGroup, parseChildren, validateProps } from './utils';
import { Item, Section, useSelectState } from 'react-stately';
import { HiddenSelect, useButton, useSelect } from 'react-aria';
import { Item, Section, useSelectState } from '../react-aria'; // from react-stately
import { HiddenSelect, useButton, useSelect } from '../react-aria'; // from react-aria
import DropdownMenu from './DropdownMenu';
import useClickOutsideHandler from '../utilities/useClickOutsideHandler';
import useId from '../utilities/useId';
Expand Down
27 changes: 17 additions & 10 deletions packages/design-system/src/components/Dropdown/DropdownMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React, { RefObject, useRef } from 'react';
import { DropdownMenuOption } from './DropdownMenuOption';
import { DropdownMenuSection } from './DropdownMenuSection';
import { ListState, OverlayTriggerState } from 'react-stately';
import { AriaPopoverProps, AriaListBoxOptions, useListBox } from 'react-aria';
import { ListState, OverlayTriggerState } from '../react-aria'; // from react-stately
import { AriaPopoverProps, AriaListBoxOptions, useListBox } from '../react-aria'; // from react-aria
import usePressEscapeHandler from '../utilities/usePressEscapeHandler';
import { DropdownSize } from './Dropdown';
import classNames from 'classnames';
Expand Down Expand Up @@ -57,6 +57,20 @@ export function DropdownMenu<T>({

const sharedProps = { state, rootId, componentClass };

// These must be mutually exclusive, because when we force the menu to render open when
// react-aria's state doesn't consider it open (state.isOpen), it seems to actually
// render unexpected items. Currently we don't have a reason to render both at the same
// time, so this is fine.
const contents =
children ??
[...state.collection].map((item) =>
item.type === 'section' ? (
<DropdownMenuSection key={item.key} section={item} {...sharedProps} />
) : (
<DropdownMenuOption key={item.key} item={item} {...sharedProps} />
)
);

return (
<div className={containerClass} ref={containerRef} onKeyDown={handleTabKey}>
{heading && (
Expand All @@ -71,14 +85,7 @@ export function DropdownMenu<T>({
className={`${componentClass}__menu`}
ref={listBoxRef}
>
{children}
{[...state.collection].map((item) =>
item.type === 'section' ? (
<DropdownMenuSection key={item.key} section={item} {...sharedProps} />
) : (
<DropdownMenuOption key={item.key} item={item} {...sharedProps} />
)
)}
{contents}
</ul>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useRef } from 'react';
import { ListState, Node } from 'react-stately';
import { ListState, Node } from '../react-aria'; // from react-stately
import { SvgIcon } from '../Icons';
import { useOption } from 'react-aria';
import { useOption } from '../react-aria'; // from react-aria
import classNames from 'classnames';

export function getOptionId(rootId: string, index: number): string {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import { DropdownMenuOption } from './DropdownMenuOption';
import { ListState, Node } from 'react-stately';
import { useListBoxSection } from 'react-aria';
import { ListState, Node } from '../react-aria'; // from react-stately
import { useListBoxSection } from '../react-aria'; // from react-aria

export interface DropdownMenuOptionProps<T> {
componentClass: string;
Expand Down
12 changes: 12 additions & 0 deletions packages/design-system/src/components/react-aria/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export { Item, Section, useComboBoxState, useSelectState } from 'react-stately';
export {
HiddenSelect,
useButton,
useComboBox,
useListBox,
useListBoxSection,
useOption,
useSelect,
} from 'react-aria';
export type { ComboBoxState, ListState, Node, OverlayTriggerState } from 'react-stately';
export type { AriaListBoxOptions, AriaPopoverProps } from 'react-aria';
Loading

0 comments on commit bee9773

Please sign in to comment.