Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pages/autosuggest/simple.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export default function AutosuggestPage() {
ariaLabel={'simple autosuggest'}
selectedAriaLabel="Selected"
empty={empty}
finishedText="Finished"
filteringResultsText={matchesCount => `${matchesCount} items`}
/>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3295,7 +3295,10 @@ because fixed positioning results in a slight, visible lag when scrolling comple
"type": "boolean",
},
{
"description": "Specifies the text to display with the number of matches at the bottom of the dropdown menu while filtering.",
"description": "Specifies the text to display with the number of matches at the bottom of the dropdown menu while filtering.

Note that the \`matchesCount\` includes the \`enteredTextLabel\` ("Use \${value}") item, so in most cases you
should subtract 1 from \`matchesCount\`. If using manual filtering, you should provide your own value for \`totalCount\`.",
"inlineType": {
"name": "(matchesCount: number, totalCount: number) => string",
"parameters": [
Expand Down
40 changes: 31 additions & 9 deletions src/autosuggest/__tests__/autosuggest-dropdown-states.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,13 @@ const defaultProps: AutosuggestProps = {
clearAriaLabel: 'clear input',
};

const ControlledAutosuggest = (props: AutosuggestProps) => {
const [value, setValue] = React.useState(props.value);
return <Autosuggest {...props} value={value} onChange={event => setValue(event.detail.value)} />;
};

function renderAutosuggest(props: Partial<AutosuggestProps>) {
const { container } = render(<Autosuggest {...defaultProps} {...props} />);
const { container } = render(<ControlledAutosuggest {...defaultProps} {...props} />);
const wrapper = createWrapper(container).findAutosuggest()!;
return { container, wrapper };
}
Expand Down Expand Up @@ -127,8 +132,9 @@ describe('footer types', () => {
});

test('results', async () => {
renderAutosuggest({ value: 'x', filteringResultsText: () => '3 items' });
const { wrapper } = renderAutosuggest({ filteringResultsText: () => '3 items' });
focusInput();
wrapper.setInputValue('x');
expectDropdown();
expectFooterSticky(true);
expectFooterContent('3 items');
Expand Down Expand Up @@ -171,9 +177,10 @@ describe('filtering results', () => {
expectFooterContent('No options');
});

test('displays results footer when value is not empty', () => {
renderAutosuggest({ value: ' ', options: [], filteringResultsText: () => '0 items' });
test('displays results footer when value is entered but not filtering', () => {
const { wrapper } = renderAutosuggest({ options: [], filteringResultsText: () => '0 items' });
focusInput();
wrapper.setInputValue(' ');
expectFooterContent('0 items');
});
});
Expand All @@ -185,9 +192,16 @@ describe('filtering results', () => {
expectNoFooter();
});

test('displays results footer when value is not empty', () => {
test('displays no footer when value is not empty', () => {
renderAutosuggest({ value: ' ', statusType: 'pending', filteringResultsText: () => '3 items' });
focusInput();
expectNoFooter();
});

test('displays results footer when value is entered', () => {
const { wrapper } = renderAutosuggest({ statusType: 'pending', filteringResultsText: () => '3 items' });
focusInput();
wrapper.setInputValue(' ');
expectFooterContent('3 items');
});
});
Expand Down Expand Up @@ -233,15 +247,23 @@ describe('filtering results', () => {
expectFooterContent('finished!');
});

test('displays results footer when finished w/o finished text and value is not empty', () => {
renderAutosuggest({ value: ' ', finishedText: undefined, filteringResultsText: () => '3 items' });
test('displays finished footer when finished w/ finished text and value is present but not filtering', () => {
renderAutosuggest({ value: ' ', filteringResultsText: () => '3 items' });
focusInput();
expectFooterContent('finished!');
});

test('displays results footer when finished w/o finished text and value is entered', () => {
const { wrapper } = renderAutosuggest({ finishedText: undefined, filteringResultsText: () => '3 items' });
focusInput();
wrapper.setInputValue(' ');
expectFooterContent('3 items');
});

test('displays results footer when finished w/ finished text and value is not empty', () => {
renderAutosuggest({ value: ' ', filteringResultsText: () => '3 items' });
test('displays results footer when finished w/ finished text and value is entered', () => {
const { wrapper } = renderAutosuggest({ filteringResultsText: () => '3 items' });
focusInput();
wrapper.setInputValue(' ');
expectFooterContent('3 items');
});
});
Expand Down
3 changes: 3 additions & 0 deletions src/autosuggest/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ export interface AutosuggestProps

/**
* Specifies the text to display with the number of matches at the bottom of the dropdown menu while filtering.
*
* Note that the `matchesCount` includes the `enteredTextLabel` ("Use ${value}") item, so in most cases you
Copy link
Member Author

Choose a reason for hiding this comment

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

unfortunately actually fixing this isn't really an option, as there are already a number of teams who do this subtraction already, so changing this behavior would be a breaking change

* should subtract 1 from `matchesCount`. If using manual filtering, you should provide your own value for `totalCount`.
*/
filteringResultsText?: (matchesCount: number, totalCount: number) => string;

Expand Down
3 changes: 1 addition & 2 deletions src/autosuggest/internal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -179,14 +179,13 @@ const InternalAutosuggest = React.forwardRef((props: InternalAutosuggestProps, r
const highlightedOptionId = autosuggestItemsState.highlightedOption ? highlightedOptionIdSource : undefined;

const isEmpty = !value && !autosuggestItemsState.items.length;
const isFiltered = !!value && value.length !== 0;
const isFiltered = !!value && value.length !== 0 && !(filteringType === 'auto' && autosuggestItemsState.showAll);
const filteredText = isFiltered
? filteringResultsText?.(autosuggestItemsState.items.length, options?.length ?? 0)
: undefined;
const dropdownStatus = useDropdownStatus({
...props,
isEmpty,
isFiltered,
recoveryText,
errorIconAriaLabel,
onRecoveryClick: handleRecoveryClick,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,6 @@ describe('useDropdownStatus', () => {
const { getContent } = renderComponent({
statusType: 'pending',
filteringResultsText: '2 matches',
isFiltered: true,
});
expect(getContent()).toBe('2 matches');
});
Expand All @@ -141,7 +140,6 @@ describe('useDropdownStatus', () => {
const { getContent } = renderComponent({
statusType: 'loading',
filteringResultsText: '2 matches',
isFiltered: true,
loadingText: 'Loading',
});
expect(getContent()).toBe('Loading');
Expand All @@ -151,7 +149,6 @@ describe('useDropdownStatus', () => {
const { getContent } = renderComponent({
statusType: 'error',
filteringResultsText: '2 matches',
isFiltered: true,
errorText: 'We got a problem',
recoveryText: 'do not worry',
hasRecoveryCallback: true,
Expand All @@ -162,8 +159,6 @@ describe('useDropdownStatus', () => {
test('render finished text when finished and not filtered', () => {
const { getContent } = renderComponent({
statusType: 'finished',
filteringResultsText: '10 out of 10 items',
isFiltered: false,
finishedText: 'End of results',
});
expect(getContent()).toBe('End of results');
Expand All @@ -173,7 +168,6 @@ describe('useDropdownStatus', () => {
const { getContent } = renderComponent({
statusType: 'finished',
filteringResultsText: '10 out of 10 items',
isFiltered: true,
finishedText: 'End of results',
});
expect(getContent()).toBe('10 out of 10 items');
Expand Down
5 changes: 1 addition & 4 deletions src/internal/components/dropdown-status/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ export { DropdownStatusProps };
export interface DropdownStatusPropsExtended extends DropdownStatusProps {
isEmpty?: boolean;
isNoMatch?: boolean;
isFiltered?: boolean;
noMatch?: React.ReactNode;
filteringResultsText?: string;
/**
Expand Down Expand Up @@ -46,7 +45,6 @@ type UseDropdownStatus = ({
recoveryText,
isEmpty,
isNoMatch,
isFiltered,
noMatch,
hasRecoveryCallback,
onRecoveryClick,
Expand All @@ -68,7 +66,6 @@ export const useDropdownStatus: UseDropdownStatus = ({
recoveryText,
isEmpty,
isNoMatch,
isFiltered,
noMatch,
onRecoveryClick,
hasRecoveryCallback = false,
Expand Down Expand Up @@ -106,7 +103,7 @@ export const useDropdownStatus: UseDropdownStatus = ({
statusResult.content = empty;
} else if (isNoMatch && noMatch) {
statusResult.content = noMatch;
} else if (isFiltered && filteringResultsText) {
} else if (filteringResultsText) {
statusResult.content = filteringResultsText;
} else if (statusType === 'finished' && finishedText) {
statusResult.content = finishedText;
Expand Down
1 change: 0 additions & 1 deletion src/multiselect/use-multiselect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,6 @@ export function useMultiselect({
isEmpty,
isNoMatch,
noMatch,
isFiltered,
filteringResultsText: filteredText,
onRecoveryClick: handleRecoveryClick,
errorIconAriaLabel: errorIconAriaLabel,
Expand Down
1 change: 0 additions & 1 deletion src/select/internal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,6 @@ const InternalSelect = React.forwardRef(
isEmpty,
isNoMatch,
noMatch,
isFiltered,
filteringResultsText: filteredText,
errorIconAriaLabel,
onRecoveryClick: handleRecoveryClick,
Expand Down
Loading