Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Autocomplete): add controllable isOpen, inputValue props; extend text behaviour on item select #2567

Merged
merged 5 commits into from
Aug 30, 2023

Conversation

maxcheremisin
Copy link
Member

@maxcheremisin maxcheremisin commented Aug 25, 2023

Purpose of PR

What's changed:

  • ❌ clearAfterSelect (boolean) replaced with πŸ†• textOnAfterSelect ('clear' | 'preserve' | 'replace') to be able to preserve the text input value when item selected
  • πŸ†• inputValue prop added to be able to clear the text input programmatically (e.g. on menu close)
  • πŸ†• isOpen prop added (and corresponding onOpen, onClose handlers) to be able to control menu state and subscribe to its change
Screen.Recording.2023-08-25.at.16.05.03.mov

@vercel
Copy link

vercel bot commented Aug 25, 2023

The latest updates on your projects. Learn more about Vercel for Git β†—οΈŽ

Name Status Preview Updated (UTC)
forma-36 βœ… Ready (Inspect) Visit Preview Aug 29, 2023 9:15pm

@maxcheremisin maxcheremisin force-pushed the feat/Autocomplete-isOpen|textOnAfterSelect branch from 8036755 to d1b88c8 Compare August 25, 2023 14:10
@changeset-bot
Copy link

changeset-bot bot commented Aug 25, 2023

πŸ¦‹ Changeset detected

Latest commit: 13e66bb

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 32 packages
Name Type
@contentful/f36-autocomplete Minor
@contentful/f36-accordion Minor
@contentful/f36-asset Minor
@contentful/f36-badge Minor
@contentful/f36-button Minor
@contentful/f36-card Minor
@contentful/f36-collapse Minor
@contentful/f36-copybutton Minor
@contentful/f36-core Minor
@contentful/f36-datetime Minor
@contentful/f36-datepicker Minor
@contentful/f36-drag-handle Minor
@contentful/f36-entity-list Minor
@contentful/f36-empty-state Minor
@contentful/f36-forms Minor
@contentful/f36-icon Minor
@contentful/f36-list Minor
@contentful/f36-menu Minor
@contentful/f36-modal Minor
@contentful/f36-note Minor
@contentful/f36-notification Minor
@contentful/f36-pagination Minor
@contentful/f36-pill Minor
@contentful/f36-popover Minor
@contentful/f36-skeleton Minor
@contentful/f36-spinner Minor
@contentful/f36-table Minor
@contentful/f36-tabs Minor
@contentful/f36-text-link Minor
@contentful/f36-tooltip Minor
@contentful/f36-typography Minor
@contentful/f36-components Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

}}
onBlur={(e) => {
onBlur?.(e as React.FocusEvent<HTMLInputElement>);
inputProps.onBlur(e);
Copy link
Member Author

Choose a reason for hiding this comment

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

was missing and didn't fire onBlur properly

Comment on lines -255 to -257
if (!closeAfterSelect) {
toggleMenu();
}
Copy link
Member Author

Choose a reason for hiding this comment

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

this logic is moved to stateReducer so it doesnt cause extra rerenders and doesnt fire onIsOpenChange

@github-actions
Copy link

github-actions bot commented Aug 25, 2023

size-limit report πŸ“¦

Path Size Loading time (3g) Running time (snapdragon) Total time
CommonJS 129.48 KB (+0.15% πŸ”Ί) 2.6 s (+0.15% πŸ”Ί) 466 ms (+10.33% πŸ”Ί) 3.1 s
Module 125.96 KB (+0.16% πŸ”Ί) 2.6 s (+0.16% πŸ”Ί) 308 ms (+4.75% πŸ”Ί) 2.9 s

Comment on lines -252 to -254
if (clearAfterSelect) {
handleInputValueChange('');
}
Copy link
Member Author

Choose a reason for hiding this comment

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

moved to onInputValueChange

Copy link
Contributor

@Chaoste Chaoste left a comment

Choose a reason for hiding this comment

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

Looks good to me - just a nitpick on the testing style. I didn't approve as this should be done by the owning team.

Comment on lines 146 to 169
const input = screen.getByTestId('cf-autocomplete-input');
const container = screen.getByTestId('cf-autocomplete-container');

// Type one letter in the input to open the list
fireEvent.input(input, {
target: {
value: 'a',
},
});

// checks if the list is visible
await waitFor(() => {
expect(container).toBeVisible();
});

// go to the list first item
fireEvent.keyDown(input, {
key: 'ArrowDown',
});

// press Enter to select the item
fireEvent.keyDown(input, {
key: 'Enter',
});
Copy link
Contributor

Choose a reason for hiding this comment

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

[nitpick]

Considering that we try to replace usage of fireEvent with userEvent for more realistic input testing, as well as some other recommended testing styles (e.g. avoid test IDs but use realistic queries), I would rewrite it like this:

Suggested change
const input = screen.getByTestId('cf-autocomplete-input');
const container = screen.getByTestId('cf-autocomplete-container');
// Type one letter in the input to open the list
fireEvent.input(input, {
target: {
value: 'a',
},
});
// checks if the list is visible
await waitFor(() => {
expect(container).toBeVisible();
});
// go to the list first item
fireEvent.keyDown(input, {
key: 'ArrowDown',
});
// press Enter to select the item
fireEvent.keyDown(input, {
key: 'Enter',
});
await userEvent.type(screen.getByRole('textbox'), 'a');
expect(await screen.findByRole('menuitem', { name: /apple/ }).toBeInTheDocument();
await userEvent.type(screen.getByRole('textbox'), '{arrowdown}{enter}');

All of these changes are also further explained in this blog post which I can highly recommend to understand why we shouldn't use test IDs, etc.

Copy link
Member Author

Choose a reason for hiding this comment

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

i just copied one of the test cases and adjusted it for the new prop. but i refactored the test file now using user event and getByRole

Copy link
Contributor

Choose a reason for hiding this comment

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

Thank you! I know that many of our repositories are still in this old state. Just want to avoid that reproduce it - maybe we can get rid of these things by slowly refactoring it bit by bit.

Copy link
Collaborator

@denkristoffer denkristoffer left a comment

Choose a reason for hiding this comment

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

Prop changes like this are a breaking change. Since the Autocomplete is considered stable we will have to deprecate instead and remove in v5.

@maxcheremisin maxcheremisin force-pushed the feat/Autocomplete-isOpen|textOnAfterSelect branch from 6f7745d to 75624e3 Compare August 29, 2023 10:06
@maxcheremisin
Copy link
Member Author

Prop changes like this are a breaking change. Since the Autocomplete is considered stable we will have to deprecate instead and remove in v5.

thanks! done

Copy link
Collaborator

@cf-remylenoir cf-remylenoir left a comment

Choose a reason for hiding this comment

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

It looks good, could you please add an example of using the new props in the documentation and storybook as per in the video? I was not able to reproduce it myself πŸ€”

@maxcheremisin
Copy link
Member Author

It looks good, could you please add an example of using the new props in the documentation and storybook as per in the video? I was not able to reproduce it myself πŸ€”

curious what you think - there is an example for textOnAfterSelect, but i didn't add more examples of inputValue and isOpen to the docs because the use case is pretty niche and it might overload the docs with too much information.

but i defo can add more stories to the storybook

@maxcheremisin
Copy link
Member Author

It looks good, could you please add an example of using the new props in the documentation and storybook as per in the video? I was not able to reproduce it myself πŸ€”

curious what you think - there is an example for textOnAfterSelect, but i didn't add more examples of inputValue and isOpen to the docs because the use case is pretty niche and it might overload the docs with too much information.

but i defo can add more stories to the storybook

extended ControlledFromOutside story with more props

Copy link
Collaborator

@cf-remylenoir cf-remylenoir left a comment

Choose a reason for hiding this comment

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

Looking good πŸ‘ I noted down the deprecation for the next major release.

@maxcheremisin maxcheremisin merged commit 51eb9f4 into main Aug 30, 2023
3 checks passed
@maxcheremisin maxcheremisin deleted the feat/Autocomplete-isOpen|textOnAfterSelect branch August 30, 2023 11:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants