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(atomic): add configurable query suggestions & recent queries to search box #1261

Merged
merged 6 commits into from
Oct 6, 2021

Conversation

ThibodeauJF
Copy link
Contributor

@github-actions
Copy link

Thanks for your contribution @ThibodeauJF !
When your pull-request is ready to be merged, check the box below to merge it

  • Merge! :shipit:

@github-actions
Copy link

Pull Request Report

PR Title

❌ Title should follow the conventional commit spec:

(optional scope):

Example:

feat(headless): add result-list controller

Bundle Size

File Compression Old (kb) New (kb) Change (%)
headless.js bundled 371.9 371.9 0
minified 165.4 165.4 0
gzipped 48.1 48.1 0
headless.esm.js bundled 362.2 362.2 0
minified 206.2 206.2 0
gzipped 52.8 52.8 0


public initialize() {
this.id = randomID('atomic-search-box-');
this.querySetActions = loadQuerySetActions(this.bindings.engine);
this.searchBox = buildSearchBox(this.bindings.engine, {
options: {
id: this.id,
numberOfSuggestions: 8, // TODO: handle when adding query suggestion component
numberOfSuggestions: 0,
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is the new initial value 0?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can't let the search box manage the registering and fetching of query suggestions, mainly for the promise we need to wait for before rendering all suggestions. The other atomic-search-box-query-suggestions handles it

tag: 'atomic-search-box-query-suggestions',
shadow: true,
})
export class AtomicSearchBoxQuerySuggestions {
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 ending the name with a singular would make it easier to understand? Could it also be possible to shorten by removing SearchBox ? e.g.

AtomicSearchBoxQuerySuggestionList
AtomicQuerySuggestionList

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fair enough, but I wanted it to be clear they are for the search box and you can't see them as independent. I could see these AtomicQuerySuggestions/AtomicRecentQueries being standalone somewhere in the page, like quantic uses recent queries

Comment on lines 21 to 45
({engine, id, searchBoxController, numberOfQueries}) => {
const {registerQuerySuggest, fetchQuerySuggestions} =
loadQuerySuggestActions(engine);

(engine as SearchEngine<QuerySuggestionSection>).dispatch(
registerQuerySuggest({
id,
count: numberOfQueries,
})
);

return {
onInput: () =>
(engine as SearchEngine<QuerySuggestionSection>).dispatch(
fetchQuerySuggestions({
id,
})
),
renderItems: () =>
// TODO: limit values according to maxWithQuery/maxWithoutQuery
searchBoxController.state.suggestions.map((suggestion) => ({
content: <span innerHTML={suggestion.highlightedValue}></span>,
value: suggestion.rawValue,
onClick: () =>
searchBoxController.selectSuggestion(suggestion.rawValue),
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 this block would be easier to follow if it was broken up into multiple smaller functions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep! I'll do it in the other PR

);
if (canceled) {
throw new Error(
'The Atomic search box suggestion component was not handled, as it is not a child of a search box component'
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 it would be nice to include the tag, or an example, in the message to help devs understand, have something that they can copy-paste in case of a typo. e.g.

<atomic-search-box>
    <atomic-search-box-suggestions/>
</atomic-search-box>

element: Element
) => {
const canceled = element.dispatchEvent(
buildCustomEvent('atomic/searchBoxSuggestion', event)
Copy link
Contributor

Choose a reason for hiding this comment

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

Would the event's role be clearer if it included /register or similar at the end? e.g.

atomic/searchBoxSuggestion/register


@State() public error!: Error;

@Prop() public maxWithQuery?: number;
Copy link
Member

Choose a reason for hiding this comment

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

Do we really need two different prop for this ? Just one for both could do, no ? 🤔

Why would it be important to have separate option for both mode ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

From the design (figma), you put as many recent queries as possible when the input is empty, but then you match up to 3 queries. I could remove the options here for query suggest, but I find it more consistent.

* - atomic-search-box-query-suggestions
* - atomic-search-box-recent-queries
*/
@Prop() public numberOfQueries = 8;
Copy link
Member

Choose a reason for hiding this comment

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

numberOfSuggestions ? What do you think ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Like described in the documents, there will also be "numberOfResults" for the other types of suggestions. So these scenarios can be configured:

Screen Shot 2021-09-28 at 3 26 15 PM

Copy link
Contributor

@btaillon-coveo btaillon-coveo Sep 29, 2021

Choose a reason for hiding this comment

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

I think that instead of making this an option here, we could have an opiniated default, and if people want to override it then they need to specify atomic-search-box-query-suggestions and atomic-search-box-recent-queries themselves.

Otherwise, I find it confusing to predict what number of suggestions & recent queries will each appear based on this option.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is why each of the sub elements, atomic-search-box-query-suggestions and atomic-search-box-recent-queries, have maximums, which when not defined, fill up the numberOfQueries value. How else could we configure the following:

  • I want a max of 8 queries at all times (any type)
  • When there is no query in the input, I want all the recent queries I can up to 8, but fill the rest with query suggestions
  • When there is a query, I want up to 3 matching recent queries, and fill the rest with query suggestions

import {buildCustomEvent} from '../../utils/event-utils';
import {Bindings} from '../../utils/initialization-utils';

export interface SearchBoxSuggestionElement {
Copy link
Member

Choose a reason for hiding this comment

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

When we want to make the "Custom Atomic component" API official, it means we will need to make the mechanism to extend "search box suggestions" provider public. And that can be a pretty tricky thing to get right.

A couple notes/thoughts:

  • Since the content (the VNode) is ultimately rendered inside an ul / li in atomic-search-box, I guess that not all HTML elements would be valid ? I'm perfectly fine with this, by the way, but if there's any restriction, they need to be clear and (potentially) automatically handled (read: rejected) by the system so that users don't get random errors. Another approach would be to accept anything here, but to make it possible to control the "container" in atomic-search-box (being able to change ul / li to something else. This does add complexity, however.

  • If someone wants to provide very rich/complex suggestion (eg: A product image with lots of metadata section), how would the keyboard navigation plays into that ? If you could navigate to different subsection on a suggestion. Should the system forbid that ?

  • What happens if you want to have multiple clickable/interactive element in a given suggestion element ? Would the onClick cause a problem then ?

  • Is the integration of that dispatchSearchBoxSuggestionsEvent inside the componentWillLoad function as clean as it could be ? Could it be a more straightforward interface that you need to implement (or clever usage of an annotation).

Copy link
Contributor Author

@ThibodeauJF ThibodeauJF Sep 28, 2021

Choose a reason for hiding this comment

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

  1. I want that limitation, the search box manages all the interactivity with the search box. The li is needed to be correctly accessible too.
  2. Yes, a single element means a single possible interaction, more than that get's too complex for all our use cases.
  3. Same as point 2
  4. What would you propose like interface? I will certainly be extended upon in the future, modify with our needs. It's not public yet and before it is we will have improved upon it to support instant results and recently viewed.

import {Bindings} from '../../utils/initialization-utils';

export interface SearchBoxSuggestionElement {
value: string;
Copy link
Member

Choose a reason for hiding this comment

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

Unless I am mistaken, we use value here as a key for JSX code.

Could we just name it key then ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This could change when adding results, but the way suggestion worked is the value (used for key & data-value) will affect the query when you use the arrows, just like on google.com & the JSUI


@State() public error!: Error;

@Prop() public maxWithQuery?: number;
Copy link
Member

Choose a reason for hiding this comment

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

Similar as above, why do we need two prop for this ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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


export interface SearchBoxSuggestionElement {
value: string;
onClick(): void;
Copy link
Member

Choose a reason for hiding this comment

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

Suggestion: onSelect since it's not always going to be a click. eg: touch on mobile, or enter is using a keyboard.

export interface SearchBoxSuggestionElement {
value: string;
onClick(): void;
content: VNode;
Copy link
Contributor

Choose a reason for hiding this comment

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

The type VNode works great in Stencil and maybe in other JSX frameworks, but I don't know if it's possible without those frameworks to provide a VNode.

@ThibodeauJF ThibodeauJF changed the title feat(atomic): add configurable query suggestions & recent queries to search box (TODOs still remain, more PRs coming) feat(atomic): add configurable query suggestions & recent queries to search box Sep 29, 2021
});

return {
onInput: () => {},
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we show all recent queries in the suggestions or only those that include what we typed so far?

@johnnyCoveo

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's in the mockups, when no query, we display them as is, when there is a query, we filter them out, you can refer to the part 2 for the implementation!

@ThibodeauJF ThibodeauJF merged commit bb38b27 into master Oct 6, 2021
@ThibodeauJF ThibodeauJF deleted the KIT-853 branch October 6, 2021 12:27
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