Skip to content

Commit

Permalink
Merge pull request #293 from WestpacGEL/151-autocomplete-no-options-d…
Browse files Browse the repository at this point in the history
…isplay-and-icon-rendering

fixes #151 autocomplete no option option
  • Loading branch information
samithaf authored Nov 16, 2023
2 parents bf5547c + 22fb720 commit ca1180d
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use client';

import * as React from 'react';
import { useMemo } from 'react';
import { useButton, useComboBox, useFilter, useSearchField } from 'react-aria';
import { Item, useComboBoxState, useSearchFieldState } from 'react-stately';

Expand All @@ -11,6 +12,22 @@ import { styles as autocompleteStyles } from './autocomplete.styles.js';
import { type AutocompleteProps } from './autocomplete.types.js';
import { ListBox, Popover } from './components/index.js';

const STATIC_IS_OPEN_STATE = {
isOpen: true,
setOpen: () => {
return;
},
open: () => {
return;
},
close: () => {
return;
},
toggle: () => {
return;
},
};

export function Autocomplete<T extends object>({
size = 'medium',
invalid = false,
Expand All @@ -19,6 +36,7 @@ export function Autocomplete<T extends object>({
portalContainer,
errorMessage,
hintMessage,
noOptionsMessage,
...props
}: AutocompleteProps<T>) {
const { contains } = useFilter({ sensitivity: 'base' });
Expand Down Expand Up @@ -60,6 +78,14 @@ export function Autocomplete<T extends object>({
const { buttonProps } = useButton(clearButtonProps, clearButtonRef);
const outerRef = React.useRef(null);

const isNoOptionPopOverOpen = useMemo(() => {
return (
noOptionsMessage &&
((!state.isOpen && state.isFocused && searchProps.value.length > 0 && !state.selectedItem) ||
(state.collection.size === 0 && searchProps.value.length > 0))
);
}, [state, searchProps, noOptionsMessage]);

return (
<div className={styles.base()}>
<FormLabel {...labelProps}>{props.label}</FormLabel>
Expand All @@ -78,7 +104,17 @@ export function Autocomplete<T extends object>({
<ClearIcon aria-hidden="true" color="muted" size="small" />
</button>
</div>

{isNoOptionPopOverOpen && (
<Popover
state={STATIC_IS_OPEN_STATE}
isNonModal
placement="bottom start"
portalContainer={portalContainer}
triggerRef={outerRef}
>
<div className="px-3 py-2">{noOptionsMessage}</div>
</Popover>
)}
{state.isOpen && (
<Popover
popoverRef={popoverRef}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ export const ErrorMessageAndLabel: Story = {
errorMessage: 'This is an inline error message',
validationState: 'invalid',
hintMessage: 'Hint: choose from one of the following options',
noOptionsMessage: 'No options',
children: [
<Autocomplete.Item key="Option 1">Option 1</Autocomplete.Item>,
<Autocomplete.Item key="Option 2">Option 2</Autocomplete.Item>,
Expand Down
4 changes: 4 additions & 0 deletions packages/ui/src/components/autocomplete/autocomplete.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ export type AutocompleteProps<T extends object> = {
* Whether autocomplete is disabled
*/
isDisabled?: Variants['isDisabled'];
/**
* No option message
*/
noOptionsMessage?: ReactNode;
/**
* Element where the popover will be rendered, by default it will be into the body
*/
Expand Down

1 comment on commit ca1180d

@vercel
Copy link

@vercel vercel bot commented on ca1180d Nov 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

gel-next-site – ./apps/site

gel-next-site.vercel.app
gel-next-site-westpacgel.vercel.app
gel-next-site-git-main-westpacgel.vercel.app

Please sign in to comment.