Skip to content

Commit

Permalink
feat: Introduces autosuggest without entered text option
Browse files Browse the repository at this point in the history
  • Loading branch information
pan-kot committed Dec 4, 2024
1 parent 7948389 commit 3de35ac
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 4 deletions.
99 changes: 99 additions & 0 deletions pages/autosuggest/search.page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import React, { useContext, useRef, useState } from 'react';

import { Badge, Box, Checkbox, ExpandableSection, Header, SpaceBetween } from '~components';
import Autosuggest, { AutosuggestProps } from '~components/autosuggest';

import AppContext, { AppContextType } from '../app/app-context';

type PageContext = React.Context<
AppContextType<{
empty?: boolean;
showEnteredTextOption?: boolean;
showMatchesCount?: boolean;
}>
>;

const options = [
{ value: '__apple__', label: 'Apple' },
{ value: '__orange__', label: 'Orange', tags: ['sweet'] },
{ value: '__banana__', label: 'Banana', tags: ['sweet'] },
{ value: '__pineapple__', label: 'Pineapple', description: 'pine+apple' },
];
const enteredTextLabel = (value: string) => `Use: ${value}`;

export default function AutosuggestPage() {
const {
urlParams: { empty = false, showEnteredTextOption = true, showMatchesCount = true },
setUrlParams,
} = useContext(AppContext as PageContext);
const [value, setValue] = useState('');
const [selection, setSelection] = useState('');
const ref = useRef<AutosuggestProps.Ref>(null);
return (
<Box margin="m">
<SpaceBetween size="m">
<Header
variant="h1"
description="This demo shows how an updated version of Autosuggest can be used as a search input"
>
Search
</Header>

<ExpandableSection defaultExpanded={true} headerText="Settings">
<Checkbox checked={empty} onChange={({ detail }) => setUrlParams({ empty: detail.checked })}>
Empty
</Checkbox>
<Checkbox
checked={showEnteredTextOption}
onChange={({ detail }) => setUrlParams({ showEnteredTextOption: detail.checked })}
>
Show entered text option
</Checkbox>
<Checkbox
checked={showMatchesCount}
onChange={({ detail }) => setUrlParams({ showMatchesCount: detail.checked })}
>
Show matches count
</Checkbox>
</ExpandableSection>

<Autosuggest
ref={ref}
value={value}
options={empty ? [] : options}
onChange={event => setValue(event.detail.value)}
onSelect={event => {
if (options.some(o => o.value === event.detail.value)) {
setSelection(event.detail.value);
setValue('');
}
}}
enteredTextLabel={enteredTextLabel}
ariaLabel={'simple autosuggest'}
selectedAriaLabel="Selected"
empty="No suggestions"
showEnteredTextOption={showEnteredTextOption}
filteringResultsText={
showMatchesCount
? matchesCount => {
matchesCount = showEnteredTextOption ? matchesCount - 1 : matchesCount;
return matchesCount ? `${matchesCount} items` : `No matches`;
}
: undefined
}
/>

<SpaceBetween size="s" direction="horizontal">
<Box>Selection: {selection || 'none'}</Box>
{options.map(option => (
<Badge key={option.value} color={selection === option.value ? 'green' : 'grey'}>
{option.label}
</Badge>
))}
</SpaceBetween>
</SpaceBetween>
</Box>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2052,6 +2052,14 @@ This is required to provide a good screen reader experience. For more informatio
"optional": true,
"type": "string",
},
{
"defaultValue": "true",
"description": "Defines whether entered text option is shown as the first option in the dropdown when value is non-empty.
Defaults to \`true\`.",
"name": "showEnteredTextOption",
"optional": true,
"type": "boolean",
},
{
"defaultValue": "'finished'",
"description": "Specifies the current status of loading more options.
Expand Down
10 changes: 9 additions & 1 deletion src/autosuggest/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@ export { AutosuggestProps };

const Autosuggest = React.forwardRef(
(
{ filteringType = 'auto', statusType = 'finished', disableBrowserAutocorrect = false, ...props }: AutosuggestProps,
{
filteringType = 'auto',
statusType = 'finished',
disableBrowserAutocorrect = false,
showEnteredTextOption = true,
...props
}: AutosuggestProps,
ref: React.Ref<AutosuggestProps.Ref>
) => {
const baseComponentProps = useBaseComponent('Autosuggest', {
Expand All @@ -26,6 +32,7 @@ const Autosuggest = React.forwardRef(
filteringType,
readOnly: props.readOnly,
virtualScroll: props.virtualScroll,
showEnteredTextOption,
},
});

Expand All @@ -43,6 +50,7 @@ const Autosuggest = React.forwardRef(
filteringType={filteringType}
statusType={statusType}
disableBrowserAutocorrect={disableBrowserAutocorrect}
showEnteredTextOption={showEnteredTextOption}
{...externalProps}
{...baseComponentProps}
ref={ref}
Expand Down
6 changes: 6 additions & 0 deletions src/autosuggest/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ export interface AutosuggestProps
*/
enteredTextLabel?: AutosuggestProps.EnteredTextLabel;

/**
* Defines whether entered text option is shown as the first option in the dropdown when value is non-empty.
* Defaults to `true`.
*/
showEnteredTextOption?: boolean;

/**
* Specifies the text to display with the number of matches at the bottom of the dropdown menu while filtering.
*/
Expand Down
9 changes: 6 additions & 3 deletions src/autosuggest/internal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const InternalAutosuggest = React.forwardRef((props: InternalAutosuggestProps, r
ariaLabel,
ariaRequired,
enteredTextLabel,
showEnteredTextOption,
filteringResultsText,
onKeyDown,
virtualScroll,
Expand Down Expand Up @@ -91,7 +92,7 @@ const InternalAutosuggest = React.forwardRef((props: InternalAutosuggestProps, r
filterText: value,
filteringType,
enteredTextLabel,
hideEnteredTextLabel: false,
hideEnteredTextLabel: !showEnteredTextOption,
onSelectItem: (option: AutosuggestItem) => {
const value = option.value || '';
fireNonCancelableEvent(onChange, { value });
Expand Down Expand Up @@ -196,6 +197,7 @@ const InternalAutosuggest = React.forwardRef((props: InternalAutosuggestProps, r
});

const shouldRenderDropdownContent = !isEmpty || dropdownStatus.content;
const dropdownExpanded = autosuggestItemsState.items.length > 1 || dropdownStatus.content !== null;

return (
<AutosuggestInput
Expand All @@ -222,9 +224,10 @@ const InternalAutosuggest = React.forwardRef((props: InternalAutosuggestProps, r
expandToViewport={expandToViewport}
ariaControls={listId}
ariaActivedescendant={highlightedOptionId}
dropdownExpanded={autosuggestItemsState.items.length > 1 || dropdownStatus.content !== null}
dropdownExpanded={dropdownExpanded}
dropdownContent={
shouldRenderDropdownContent && (
shouldRenderDropdownContent &&
dropdownExpanded && (
<AutosuggestOptionsList
statusType={statusType}
autosuggestItemsState={autosuggestItemsState}
Expand Down

0 comments on commit 3de35ac

Please sign in to comment.