Skip to content

Commit

Permalink
fix(quantic, searchbox): Issue with searchbox suggestions list flashi…
Browse files Browse the repository at this point in the history
…ng after selecting recent query (#4401)

[SFINT-5606](https://coveord.atlassian.net/browse/SFINT-5606)

### ISSUE:
- After selecting a recent query, the suggestion list was "flashing".
This was caused because the state of the suggestions is not cleared
after selecting a recent query. So it would display first the "old"
suggestions, then because we focused on the input it would THEN display
the suggestions based on the input value.

You can see the issue here: https://go.screenpal.com/watch/cZ1tYTV8YbT


### SOLUTION:
- We are now loading the actions `loadQuerySuggestActions` in the
`quanticSearchbox` in order to allow us to dispatch: `clearQuerySuggest
` after clicking on a recent query. For this we must pass the id of the
suggestion as payload and therefore we needed to add `querySuggestionId
` in the state.
- This allows us to clear the query suggestions state after clicking on
a recent query and therefore prevent the flashing effect.

Tested multiple cases where we select suggestions, recent queries, clear
the recent queries, fast network, slow network, etc. Solution seems to
work well without the "flashing" happening.


### DEMO:


https://github.com/user-attachments/assets/c4f6a4ae-81c8-4677-af4f-b72fafded061


TESTS:

<img width="431" alt="Screenshot 2024-09-16 at 2 42 28 PM"
src="https://github.com/user-attachments/assets/f8a9c399-b705-42d5-80ae-53ccc0d27443">


[SFINT-5606]:
https://coveord.atlassian.net/browse/SFINT-5606?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
  • Loading branch information
SimonMilord authored Sep 19, 2024
1 parent 037b2ca commit 6f75ad6
Show file tree
Hide file tree
Showing 11 changed files with 30 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ describe('headless search box', () => {
describe('#state', () => {
it('is as expected', () => {
expect(searchBox.state).toEqual({
searchBoxId: id,
value: state.querySet[id],
suggestions: state.querySuggest[id]!.completions.map((completion) => ({
highlightedValue: '<a>hi</a>light<i>ed</i>',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ export function buildSearchBox(
: false;

return {
searchBoxId: id,
value: getValue(),
suggestions,
isLoading: getState().commerceSearch.isLoading,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ describe('headless standalone searchBox', () => {

it('should return the right state', () => {
expect(searchBox.state).toEqual({
searchBoxId: id,
value: state.querySet[id],
suggestions: state.querySuggest[id]!.completions.map((completion) => ({
value: completion.expression,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ describe('headless CoreSearchBox', () => {

it('should return the right state', () => {
expect(searchBox.state).toEqual({
searchBoxId: id,
value: state.querySet[id],
suggestions: state.querySuggest[id]!.completions.map((completion) => ({
highlightedValue: '<a>hi<a>light<i>ed<i>',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,11 @@ export interface SearchBoxState {
* Determines if a query suggest request is in progress.
*/
isLoadingSuggestions: boolean;

/**
* The search box ID.
*/
searchBoxId: string;
}

export interface Suggestion {
Expand Down Expand Up @@ -306,6 +311,7 @@ export function buildCoreSearchBox(
: false;

return {
searchBoxId: id,
value: getValue(),
suggestions,
isLoading: state.search.isLoading,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ describe('headless standalone searchBox', () => {

it('should return the right state', () => {
expect(searchBox.state).toEqual({
searchBoxId: id,
value: state.querySet[id],
suggestions: state.querySuggest[id]!.completions.map((completion) => ({
value: completion.expression,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {AsyncThunkAction, PayloadAction} from '@reduxjs/toolkit';
import {AsyncThunkSearchOptions} from '../../api/search/search-api-client';
import {SearchEngine} from '../../app/search-engine/search-engine';
import {CoreEngine} from '../../app/engine';
import {querySetReducer as querySet} from '../../features/query-set/query-set-slice';
import {querySuggestReducer as querySuggest} from '../../features/query-suggest/query-suggest-slice';
import {
Expand Down Expand Up @@ -79,7 +79,7 @@ export interface QuerySuggestActionCreators {
* @returns An object holding the action creators.
*/
export function loadQuerySuggestActions(
engine: SearchEngine
engine: CoreEngine
): QuerySuggestActionCreators {
engine.addReducers({querySuggest, querySet});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export interface QuerySuggestionID {

export interface RegisterQuerySuggestActionCreatorPayload {
/**
* A unique identifier for the new query suggest entity (e.g., `b953ab2e-022b-4de4-903f-68b2c0682942`).
* A unique identifier for the new query suggest entity (e.g., `b953ab2e-022b-4de4-903f-68b2c0682942`). Usually, this will be the ID of the search box controller that requests the query suggestions.
*/
id: string;

Expand Down Expand Up @@ -71,7 +71,7 @@ export const unregisterQuerySuggest = createAction(

export interface SelectQuerySuggestionActionCreatorPayload {
/**
* The unique identifier of the target query suggest entity (e.g., `b953ab2e-022b-4de4-903f-68b2c0682942`).
* The unique identifier of the target query suggest entity (e.g., `b953ab2e-022b-4de4-903f-68b2c0682942`). Usually, this will be the ID of the search box controller that requests the query suggestions.
*/
id: string;

Expand All @@ -92,7 +92,7 @@ export const selectQuerySuggestion = createAction(

export interface ClearQuerySuggestActionCreatorPayload {
/**
* The unique identifier of the target query suggest entity (e.g., `b953ab2e-022b-4de4-903f-68b2c0682942`).
* The unique identifier of the target query suggest entity (e.g., `b953ab2e-022b-4de4-903f-68b2c0682942`). Usually, this will be the ID of the search box controller that requests the query suggestions.
*/
id: string;
}
Expand All @@ -105,7 +105,7 @@ export const clearQuerySuggest = createAction(

export interface FetchQuerySuggestionsActionCreatorPayload {
/**
* The unique identifier of the target query suggest entity (e.g., `b953ab2e-022b-4de4-903f-68b2c0682942`).
* The unique identifier of the target query suggest entity (e.g., `b953ab2e-022b-4de4-903f-68b2c0682942`). Usually, this will be the ID of the search box controller that requests the query suggestions.
*/
id: string;
}
Expand Down
1 change: 1 addition & 0 deletions packages/headless/src/insight.index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export * from './features/analytics/generic-analytics-actions-loader';
export * from './features/question-answering/question-answering-actions-loader';
export * from './features/folding/folding-actions-loader';
export * from './features/insight-user-actions/insight-user-actions-loader';
export * from './features/query-suggest/query-suggest-actions-loader';

// Controllers
export type {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ export default class QuanticSearchBox extends LightningElement {
* @param {SearchEngine} engine
*/
initialize = (engine) => {
this.engine = engine;
this.headless = getHeadlessBundle(this.engineId);
this.searchBox = this.headless.buildSearchBox(engine, {
options: {
Expand All @@ -102,6 +103,10 @@ export default class QuanticSearchBox extends LightningElement {
},
});

this.actions = {
...this.headless.loadQuerySuggestActions(engine),
};

if (!this.disableRecentQueries && this.headless.buildRecentQueriesList) {
this.localStorageKey = `${this.engineId}_quantic-recent-queries`;
this.recentQueriesList = this.headless.buildRecentQueriesList(engine, {
Expand Down Expand Up @@ -202,7 +207,7 @@ export default class QuanticSearchBox extends LightningElement {
};

/**
* Handles the selection of a suggestion.
* Handles the selection of a suggestion or a recent query.
*/
selectSuggestion = (event) => {
event.stopPropagation();
Expand All @@ -214,6 +219,11 @@ export default class QuanticSearchBox extends LightningElement {
this.recentQueriesList.executeRecentQuery(
this.recentQueries.indexOf(value)
);
this.engine.dispatch(
this.actions.clearQuerySuggest({
id: this.state.searchBoxId,
})
);
} else {
this.searchBox?.selectSuggestion(value);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export default class QuanticStandaloneSearchBox extends NavigationMixin(
cause: '',
metadata: null,
},
searchBoxId: '',
redirectTo: null,
suggestions: [],
value: '',
Expand Down

0 comments on commit 6f75ad6

Please sign in to comment.