Skip to content

Conversation

@bobylito
Copy link
Contributor

@bobylito bobylito commented Sep 18, 2018

Alex S added 6 commits September 17, 2018 14:12
@algobot
Copy link
Contributor

algobot commented Sep 18, 2018

Deploy preview for algolia-instantsearch ready!

Built with commit 0c4f45a

https://deploy-preview-3127--algolia-instantsearch.netlify.com

@francoischalifour francoischalifour changed the title Feat/3.0 searchbox feat(searchbox): implement InstantSearch.css Sep 18, 2018
Copy link
Contributor

@francoischalifour francoischalifour left a comment

Choose a reason for hiding this comment

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

A few notes before approving.

const containerNode = getContainerNode(container);

if (containerNode.tagName === 'INPUT') {
throw new Error(`container should not be an INPUT`);
Copy link
Contributor

Choose a reason for hiding this comment

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

Be more explicit? (friendly error message, link to the migration guide)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK will provide a link to the current documentation.

loadingIndicator,
searchAsYouType,
showReset,
showSubmit,
Copy link
Contributor

Choose a reason for hiding this comment

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

Where does that option name come from?

It's not in the specs, is it InstantSearch.js-specific?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

When we were writing this component, we thought it was a good idea to let the user choose if they wanted the magnifying glass and the cross (with submit and reset behavior). The former name of the option is magnifier actually, I just renamed it.

Happy to change things here.

Copy link
Contributor

Choose a reason for hiding this comment

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

I see. It seems like React InstantSearch provides submit and reset options to provide node elements. The way we deal with that in InstantSearch.js for now is having boolean to show/hide these elements.

Let's keep it that way for now.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, this seems implemented, but not documented?

Copy link
Contributor

Choose a reason for hiding this comment

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

@francoischalifour
Copy link
Contributor

I would also rename SearchBox/index.js to SearchBox/SearchBox.js for consistency.

@samouss
Copy link
Contributor

samouss commented Sep 20, 2018

Now that the input is inside a form when we press enter the page is reloaded.

input.parentNode.insertBefore(htmlNode, input.nextSibling);
}
const form = document.createElement('form');
form.className = cx(suit({ descendantName: 'form' }), cssClasses.form);
Copy link
Contributor

@Haroenv Haroenv Sep 20, 2018

Choose a reason for hiding this comment

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

is this kept in vanilla JS for compat reasons?

The form needs an onSubmit handler with preventDefault and the focus moving like in RIS

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can you tell me more about the behavior of the focus @Haroenv ?

Copy link
Contributor

Choose a reason for hiding this comment

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

https://blog.algolia.com/mobile-search-ux-tips/ should have most of it explained :) for the rest you can base on the React InstantSearch one, which I know is correct :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you think it's good now @Haroenv ? :)

Copy link
Contributor

Choose a reason for hiding this comment

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

I think so based on the code, but the dev novel still has the old code 🤔

@bobylito
Copy link
Contributor Author

I would also rename SearchBox/index.js to SearchBox/SearchBox.js for consistency.

This searchbox is used for the refinement list searchable feature. So it's kinda out of scope.

});
addListener(input, 'keyup', e => {
if (e.keyCode === KEY_ENTER) refine(getValue(e));
if (e.keyCode === 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.

since we have a form now, this can be done in a submit event on the form instead, and the ENTER code can be removed :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes indeed :)

Copy link
Contributor

@francoischalifour francoischalifour left a comment

Choose a reason for hiding this comment

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

KEY_ENTER is unused and should be removed (see yarn run lint).

autofocus should be set to false by default now according to the specs, not to "autofocus".

Will review all changes more attentively later in the day :)

@bobylito
Copy link
Contributor Author

autofocus should be set to false by default now according to the specs, not to "autofocus".

Indeed and I completely agree with that :)

@francoischalifour
Copy link
Contributor

@bobylito autofocus documentation and stories should also be updated.

});
} else {
addListener(input, 'input', e => {
refine(getValue(e), false);
Copy link
Contributor

Choose a reason for hiding this comment

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

We can drop the call to getValue since we dropped the support of IE8.

const form = input.parentElement;

if (searchAsYouType) {
addListener(input, 'input', getInputValueAndCall(refine));
Copy link
Contributor

Choose a reason for hiding this comment

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

We can drop the call to getInputValueAndCall since we dropped the support of IE8.

}

function addListener(el, type, fn) {
if (el.addEventListener) {
Copy link
Contributor

Choose a reason for hiding this comment

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

We can drop the call to addListener since we dropped the support of IE8.

: containerNode.querySelector(resetBtnSelector);
resetButton.style.display = query && query.trim() ? 'block' : 'none';
}
renderAfterInit({
Copy link
Contributor

Choose a reason for hiding this comment

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

With the previous implement we trigger this function only on render but now it also trigger on init, not sure about the implications. But we almost never render on the init lifecycle to avoid a flash with the empty state.

addListener(input, 'input', getInputValueAndCall(refine));
addListener(form, 'submit', e => {
e.preventDefault();
input.addEventListener('input', refine);
Copy link
Contributor

Choose a reason for hiding this comment

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

It doesn't work anymore since we provide the event to refine rather than the value. It should probably be catch with a test.

addListener(input, 'input', e => {
refine(getValue(e), false);
input.addEventListener('input', event => {
refine(event, false);
Copy link
Contributor

Choose a reason for hiding this comment

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

It doesn't work anymore since we provide the event to refine rather than the value. It should probably be catch with a test.

Copy link
Contributor

@Haroenv Haroenv left a comment

Choose a reason for hiding this comment

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

seems correct now, doc question and migration change


With the drop of `wrapInput`, we decided not to accept `input`s as containers anymore. If you want complete control over the rendering, you should use the `connectSearchBox` connector.

The search box does not support `powered-by`. If you're using a community plan, you should now use the `poweredBy` widget to display the Algolia logo.
Copy link
Contributor

Choose a reason for hiding this comment

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

You have to use the poweredBy widget

loadingIndicator,
searchAsYouType,
showReset,
showSubmit,
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, this seems implemented, but not documented?

Copy link
Contributor

@Haroenv Haroenv left a comment

Choose a reason for hiding this comment

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

  • action="" on the form for iOS keyboard
  • firing "reset" should focus the input

Copy link
Contributor

@Haroenv Haroenv left a comment

Choose a reason for hiding this comment

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

would be nice to have a story of autofocus: true now too (since it's no longer the defautl)

@francoischalifour francoischalifour merged commit c68c1fe into feat/3.0 Oct 16, 2018
@francoischalifour francoischalifour deleted the feat/3.0-searchbox branch October 16, 2018 16:09
francoischalifour added a commit that referenced this pull request Dec 10, 2018
<a name=3.0.0-beta.0></a>
# [3.0.0-beta.0](v2.10.3...v3.0.0-beta.0) (2018-12-10)

### Bug Fixes

* **api:** remove transformData ([#3241](#3241)) ([5232936](5232936))
* **breadcrumb:** fix story with transformed label ([5a39312](5a39312))
* **breadcrumb:** rename item's name to label ([#3273](#3273)) ([0189cb4](0189cb4))
* **breadcrumb:** rename noRefinement to noRefinementRoot ([#3272](#3272)) ([21a5c61](21a5c61))
* **community:** fix search config ([#3142](#3142)) ([2b41982](2b41982))
* **connectRangeSlider:** remove deprecated connector ([#3189](#3189)) ([096ebeb](096ebeb))
* **current-refinements:** remove alphabetic sorting ([#3249](#3249)) ([9914f87](9914f87)), closes [/github.com/algolia/instantsearch.js/blob/011d47909894837f2c2da5088bc81803135d201b/src/lib/utils.js#L249](https://github.com//github.com/algolia/instantsearch.js/blob/011d47909894837f2c2da5088bc81803135d201b/src/lib/utils.js/issues/L249)
* **getRefinements:** provide attributeName for type: query ([6006fe1](6006fe1)), closes [#3205](#3205)
* **highlight:** avoid to ignore highlightedTagName ([#3323](#3323)) ([9871829](9871829))
* **highlight:** HighLight -> Highlight ([#3324](#3324)) ([5b4600d](5b4600d))
* **hits:** transform items after escaping ([#3251](#3251)) ([c46b82a](c46b82a)), closes [#3250](#3250)
* **infiniteHits:** move  option to templates ([#3300](#3300)) ([1828d66](1828d66))
* **InfiniteHits:** set the correct class for the last page ([#3232](#3232)) ([f604835](f604835))
* **lint:** remove unused import ([a9ec14c](a9ec14c))
* **pagination:** rename  to  ([#3275](#3275)) ([336945b](336945b))
* **range-input:** fix button classname ([#3234](#3234)) ([56695e1](56695e1)), closes [algolia/instantsearch-specs#92](algolia/instantsearch-specs#92)
* **range-input:** remove templates ([#3128](#3128)) ([94a1ce5](94a1ce5))
* **rangeInput:** convert labels to templates ([#3312](#3312)) ([cdf91e8](cdf91e8))
* **rangeSlider:** fix CSS classes ([#3316](#3316)) ([56a5255](56a5255))
* **refinement-list:** remove  in story ([0bf8db1](0bf8db1))
* **routing:** enforce RoutingManager is the last widget ([#3149](#3149)) ([1e86b2e](1e86b2e)), closes [#3148](#3148)
* **searchbox:** fix  and  templates ([#3313](#3313)) ([4e13122](4e13122))
* **tests:** add react-test-renderer ([176494b](176494b))
* **toggleRefinement:** provide  to templates ([#3303](#3303)) ([f515b62](f515b62))

### Features

* **3.0:** remove named exports on widgets ([#3129](#3129)) ([e718ea3](e718ea3))
* **breadcrumb:** implement InstantSearch.css ([#3115](#3115)) ([84d9f18](84d9f18))
* **clearRefinements:** implement InstantSearch.css ([#3308](#3308)) ([d98ecaf](d98ecaf)), closes [#3299](#3299)
* **clearRefinements:** implement is.css ([#3114](#3114)) ([11cdc14](11cdc14))
* **current-refinements:** implement InstantSearch.css ([#3190](#3190)) ([a70917d](a70917d))
* **GeoSearch:** implement InstantSearch.css ([#3138](#3138)) ([1867d30](1867d30))
* **hierarchical-menu:** implement InstantSearch.css ([#3182](#3182)) ([be0890d](be0890d))
* **hierarchical-menu:** implement show more feature ([#3151](#3151)) ([f54fccd](f54fccd))
* **hierarchicalMenu:** merge showMore templates ([#3318](#3318)) ([0059251](0059251))
* **highlight:** export highlight function ([#3137](#3137)) ([d4b6fb1](d4b6fb1))
* **highlight:** implement InstantSearch.css ([#3132](#3132)) ([260a0b8](260a0b8))
* **hits:** implement InstantSearch.css ([#3096](#3096)) ([b3cc413](b3cc413))
* **hits-per-page:** implement InstantSearch.css ([#3125](#3125)) ([49e7096](49e7096))
* **menu:** implement InstantSearch.css ([#3181](#3181)) ([a274ab7](a274ab7))
* **menuSelect:** implement is.css ([#3109](#3109)) ([43e654a](43e654a))
* **numeric-menu:** implement InstantSearch.css ([#3162](#3162)) ([f5358f4](f5358f4))
* **numericSelector:** remove widget ([#3183](#3183)) ([e9063c0](e9063c0))
* **pagination:** implement InstantSearch.css ([#3119](#3119)) ([f3c3343](f3c3343))
* **panel:** add Panel widget ([#3253](#3253)) ([82e19fc](82e19fc))
* **poweredBy:** implement InstantSearch.css ([#3164](#3164)) ([bcc18a0](bcc18a0))
* **poweredBy:** update logo ([#3256](#3256)) ([838abec](838abec))
* **price-ranges:** implement InstantSearch.css ([#3124](#3124)) ([335339b](335339b))
* **range-input:** implement InstantSearch.css ([#3098](#3098)) ([ee6bc7e](ee6bc7e))
* **range-slider:** implement InstantSearch.css ([#3126](#3126)) ([b9b8d31](b9b8d31))
* **rating-menu:** implement InstantSearch.css ([#3161](#3161)) ([d039e11](d039e11))
* **ratingMenu:** merge labels and templates ([#3317](#3317)) ([505a2e7](505a2e7))
* **refinement-list:** implement InstantSearch.css ([#3152](#3152)) ([11c5580](11c5580))
* **refinement-list:** implement InstantSearch.css (2) ([#3179](#3179)) ([0365641](0365641))
* **refinement-list:** implement InstantSearch.css to searchbox ([#3263](#3263)) ([ad905c7](ad905c7))
* **search-client:** use search client ([#3133](#3133)) ([8e70a3e](8e70a3e))
* **searchbox:** implement InstantSearch.css ([#3127](#3127)) ([c68c1fe](c68c1fe))
* **snippet:** implement InstantSearch.css ([#3134](#3134)) ([fa56657](fa56657))
* **sort-by:** implement InstantSearch.css ([#3120](#3120)) ([5f21723](5f21723))
* **sortBy:** rename item  to  ([#3230](#3230)) ([9e24a68](9e24a68))
* **stats:** implement InstantSearch.css ([#3097](#3097)) ([63a688e](63a688e))
* **stories:** add default CurrentRefinements story ([#3252](#3252)) ([45a8fd5](45a8fd5))
* **suit:** Default component names to empty object ([0b26356](0b26356))
* **suit-helper:** provide a helper to create suit css classnames ([f142496](f142496))
* **toggleRefinement:** implement InstantSearch.css ([#3135](#3135)) ([d67a437](d67a437))
* compress templates ([#3176](#3176)) ([54f2f77](54f2f77)), closes [#3095](#3095)
* **widgets:** use warn utils ([#3175](#3175)) ([3164b06](3164b06))
francoischalifour added a commit that referenced this pull request Dec 14, 2018
<a name=3.0.0-beta.1></a>
# [3.0.0-beta.1](v2.10.3...v3.0.0-beta.1) (2018-12-14)

### Bug Fixes

* **api:** remove transformData ([#3241](#3241)) ([5232936](5232936))
* **breadcrumb:** fix story with transformed label ([5a39312](5a39312))
* **breadcrumb:** rename item's name to label ([#3273](#3273)) ([0189cb4](0189cb4))
* **breadcrumb:** rename noRefinement to noRefinementRoot ([#3272](#3272)) ([21a5c61](21a5c61))
* **community:** fix search config ([#3142](#3142)) ([2b41982](2b41982))
* **configure:** make lifecycle functions optional ([#3339](#3339)) ([2b88cfa](2b88cfa))
* **connectRangeSlider:** remove deprecated connector ([#3189](#3189)) ([096ebeb](096ebeb))
* **current-refinements:** remove alphabetic sorting ([#3249](#3249)) ([9914f87](9914f87)), closes [/github.com/algolia/instantsearch.js/blob/011d47909894837f2c2da5088bc81803135d201b/src/lib/utils.js#L249](https://github.com//github.com/algolia/instantsearch.js/blob/011d47909894837f2c2da5088bc81803135d201b/src/lib/utils.js/issues/L249)
* **getRefinements:** provide attributeName for type: query ([6006fe1](6006fe1)), closes [#3205](#3205)
* **highlight:** avoid to ignore highlightedTagName ([#3323](#3323)) ([9871829](9871829))
* **highlight:** HighLight -> Highlight ([#3324](#3324)) ([5b4600d](5b4600d))
* **hits:** transform items after escaping ([#3251](#3251)) ([c46b82a](c46b82a)), closes [#3250](#3250)
* **infiniteHits:** move  option to templates ([#3300](#3300)) ([1828d66](1828d66))
* **InfiniteHits:** set the correct class for the last page ([#3232](#3232)) ([f604835](f604835))
* **lint:** remove unused import ([a9ec14c](a9ec14c))
* **pagination:** rename  to  ([#3275](#3275)) ([336945b](336945b))
* **poweredBy:** export connectPoweredBy connector ([#3331](#3331)) ([7d48c46](7d48c46))
* **poweredBy:** fix CSS classes ([#3332](#3332)) ([abc9b82](abc9b82))
* **range-input:** fix button classname ([#3234](#3234)) ([56695e1](56695e1)), closes [algolia/instantsearch-specs#92](algolia/instantsearch-specs#92)
* **range-input:** remove templates ([#3128](#3128)) ([94a1ce5](94a1ce5))
* **rangeInput:** convert labels to templates ([#3312](#3312)) ([cdf91e8](cdf91e8))
* **rangeSlider:** fix CSS classes ([#3316](#3316)) ([56a5255](56a5255))
* **refinement-list:** remove  in story ([0bf8db1](0bf8db1))
* **routing:** enforce RoutingManager is the last widget ([#3149](#3149)) ([1e86b2e](1e86b2e)), closes [#3148](#3148)
* **searchbox:** fix  and  templates ([#3313](#3313)) ([4e13122](4e13122))
* **tests:** add react-test-renderer ([176494b](176494b))
* **toggleRefinement:** provide  to templates ([#3303](#3303)) ([f515b62](f515b62))

### Features

* **3.0:** remove named exports on widgets ([#3129](#3129)) ([e718ea3](e718ea3))
* **breadcrumb:** implement InstantSearch.css ([#3115](#3115)) ([84d9f18](84d9f18))
* **bundle:** update bundle strategy ([#3260](#3260)) ([a7dab81](a7dab81))
* **clearRefinements:** implement InstantSearch.css ([#3308](#3308)) ([d98ecaf](d98ecaf)), closes [#3299](#3299)
* **clearRefinements:** implement is.css ([#3114](#3114)) ([11cdc14](11cdc14))
* **current-refinements:** implement InstantSearch.css ([#3190](#3190)) ([a70917d](a70917d))
* **GeoSearch:** implement InstantSearch.css ([#3138](#3138)) ([1867d30](1867d30))
* **hierarchical-menu:** implement InstantSearch.css ([#3182](#3182)) ([be0890d](be0890d))
* **hierarchical-menu:** implement show more feature ([#3151](#3151)) ([f54fccd](f54fccd))
* **hierarchicalMenu:** merge showMore templates ([#3318](#3318)) ([0059251](0059251))
* **highlight:** export highlight function ([#3137](#3137)) ([d4b6fb1](d4b6fb1))
* **highlight:** implement InstantSearch.css ([#3132](#3132)) ([260a0b8](260a0b8))
* **hits:** implement InstantSearch.css ([#3096](#3096)) ([b3cc413](b3cc413))
* **hits-per-page:** implement InstantSearch.css ([#3125](#3125)) ([49e7096](49e7096))
* **infiniteHits:** rename showMore template to showMoreText ([#3330](#3330)) ([babad39](babad39))
* **menu:** implement InstantSearch.css ([#3181](#3181)) ([a274ab7](a274ab7))
* **menu:** merge showMore templates ([#3328](#3328)) ([73a450b](73a450b))
* **menuSelect:** implement is.css ([#3109](#3109)) ([43e654a](43e654a))
* **numeric-menu:** implement InstantSearch.css ([#3162](#3162)) ([f5358f4](f5358f4))
* **numericSelector:** remove widget ([#3183](#3183)) ([e9063c0](e9063c0))
* **pagination:** implement InstantSearch.css ([#3119](#3119)) ([f3c3343](f3c3343))
* **pagination:** rename labels to templates ([#3333](#3333)) ([9f24098](9f24098))
* **panel:** add Panel widget ([#3253](#3253)) ([82e19fc](82e19fc))
* **poweredBy:** disable setting URL from widget ([#3334](#3334)) ([a5ff6af](a5ff6af))
* **poweredBy:** implement InstantSearch.css ([#3164](#3164)) ([bcc18a0](bcc18a0))
* **poweredBy:** update logo ([#3256](#3256)) ([838abec](838abec))
* **price-ranges:** implement InstantSearch.css ([#3124](#3124)) ([335339b](335339b))
* **range-input:** implement InstantSearch.css ([#3098](#3098)) ([ee6bc7e](ee6bc7e))
* **range-slider:** implement InstantSearch.css ([#3126](#3126)) ([b9b8d31](b9b8d31))
* **rating-menu:** implement InstantSearch.css ([#3161](#3161)) ([d039e11](d039e11))
* **ratingMenu:** merge labels and templates ([#3317](#3317)) ([505a2e7](505a2e7))
* **refinement-list:** implement InstantSearch.css ([#3152](#3152)) ([11c5580](11c5580))
* **refinement-list:** implement InstantSearch.css (2) ([#3179](#3179)) ([0365641](0365641))
* **refinement-list:** implement InstantSearch.css to searchbox ([#3263](#3263)) ([ad905c7](ad905c7))
* **refinementList:** merge showMore templates ([#3329](#3329)) ([9b6a9c4](9b6a9c4))
* **search-client:** use search client ([#3133](#3133)) ([8e70a3e](8e70a3e))
* **searchbox:** implement InstantSearch.css ([#3127](#3127)) ([c68c1fe](c68c1fe))
* **snippet:** implement InstantSearch.css ([#3134](#3134)) ([fa56657](fa56657))
* **sort-by:** implement InstantSearch.css ([#3120](#3120)) ([5f21723](5f21723))
* **sortBy:** rename item  to  ([#3230](#3230)) ([9e24a68](9e24a68))
* **stats:** implement InstantSearch.css ([#3097](#3097)) ([63a688e](63a688e))
* **stories:** add default CurrentRefinements story ([#3252](#3252)) ([45a8fd5](45a8fd5))
* **suit:** Default component names to empty object ([0b26356](0b26356))
* **suit-helper:** provide a helper to create suit css classnames ([f142496](f142496))
* **toggleRefinement:** implement InstantSearch.css ([#3135](#3135)) ([d67a437](d67a437))
* **widgets:** use warn utils ([#3175](#3175)) ([3164b06](3164b06))
* compress templates ([#3176](#3176)) ([54f2f77](54f2f77)), closes [#3095](#3095)
// Only possible values are 'auto', true and false
if (typeof autofocus !== 'boolean') {
autofocus = 'auto';
if (containerNode.tagName === 'INPUT') {

Choose a reason for hiding this comment

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

Hello,
Why would you force user to not use an already existing input as a search input?

Copy link
Contributor

Choose a reason for hiding this comment

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

This change was made to be more consistent across all widgets in all InstantSearch flavors. You probably want to use connectSearchBox now.

Please file an issue if you have trouble migrating.

francoischalifour added a commit that referenced this pull request Feb 7, 2019
This updates the usage errors messages for `searchBox`.

- `input`s are not valid containers anymore
- `autofocus` used to accept string values for `"auto"`, which is not a valid value for the HTML attribute `autofocus` (converted to a warning).

> Related: #3127 (review)
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.

7 participants