From 355eb0a5bd133d01252434ad3e9f5bda2f19bc7d Mon Sep 17 00:00:00 2001
From: "Filipe W. Lima"
Date: Wed, 8 Jun 2022 15:02:22 -0300
Subject: [PATCH 01/11] feat: Add search history & top searches
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
A cherry-pick from the Gatsby's merge commit of this same feature.
* Skip rendering the history if there isn't any
* Clear the history when its button is clicked
* Stop trying to open the link in a new tab
In a previous design spec we opened the links in a new tab but we are not doing this anymore
* Remove onClear prop, does not seem to be needed
* Show the search history component
* Show up to 4 search history items max
The design spec mentions 4 max:
https://www.figma.com/file/kJywgfIx8LBIzggCY5AeDy/Handoff-v3.1-(Search)?node-id=2%3A58234
* Add the top searches
* Extract a `formatSearchPath` util function
* Use a link instead of button for the suggested terms
Because the `href` is known so we can use links and not navigate programmatically with buttons.
* Fix search test
I had removed the `navigate` call because it wasn't needed for the
links, but it's also used programmatically to trigger the search in the
input.
# Please enter the commit message for your changes. Lines
starting
* Fix SonarQube warning
* Create a context so the search dropdown can be closed
When terms, history, top search, products are clicked.
* Consider `closeSearchInputDropdown` to be null
Missed including this in the previous commit.
* Fix SonarQube warning
* Rename button from Clear to Clear History
* Adjust Loading text message spacing
* Fix link color for Top Search
* Fix grayish clock icon color in search history
* Limit search to 5 items per category
Noticed sometimes we were showing +5 and, apparently, the `first` pagination doesn't really filter the results.
* Also update the search input with the selected option
* Fix suggested terms link color
* Add the magnifying glass icon to suggested terms
* Run TS Hero extension to organize imports of touched files
* Better handle search input selections
Whenever a selection is made, be it from History, Top Search, Suggested Terms or Products, use the same logic:
- Add term to the history
- Send term to analytics
- Close dropdown
- Update the input with the term
* Do not show an empty gap when there are not results
* Move `SearchInputContext` and `useSearchInput` to `sdk/search/…`
* Fix warning about `SearchHistoryProps` type export
* Fix overflow-x when expanding the search on mobile
* Fix React key warning
* Debounce the search suggestions
* Add entries to the changelog
* Adjust `SuggestionsTopSearch` after the merged changes
* Fix Storybook search stories
* Simplify top search querying by using `useQuery`
Address [this suggestion](https://github.com/vtex-sites/gatsby.store/pull/67#discussion_r882857670).
* Remove debounce package in favor of using `useDeferredValue` from React
Address [this comment](https://github.com/vtex-sites/gatsby.store/pull/67#discussion_r882856990):
> can't we use React18 features like useDefferedValue to not need to implement a debounce function?
* Let TypeScript be aware of new types from React 18
So it doesn't complain when we use the new features (e.g., `useDeferredValue`).
* Let search history also record the path
Instead of using the generic search path for all the searched terms, along with the searched term, also store its path. This way, if a suggested product is selected, we store its name and its PDP path.
* Better organize by extracting `useTopSearch` to its own file
Address this comment:
https://github.com/vtex-sites/gatsby.store/pull/67#discussion_r887397506
* Better organize by extracting `useSuggestions` to its own file
Address this comment:
https://github.com/vtex-sites/gatsby.store/pull/67#discussion_r887397864
* Fix the missing search input (left) padding
Pointed out by this comment:
https://github.com/vtex-sites/gatsby.store/pull/67#pullrequestreview-992765808
> should we add padding-left inside the input?
What happened was that the padding was being overwritten by the styles when the search input is minimized.
---
Conflicts:
- CHANGELOG.md
- src/components/common/SearchInput/SearchInput.tsx
- src/components/search/History/SearchHistory.tsx
- src/components/search/SuggestionProductCard/SuggestionProductCard.tsx
- src/components/search/Suggestions/Suggestions.tsx
- src/components/search/Suggestions/SuggestionsTopSearch.tsx
- src/components/ui/Search/Suggestions/Suggestions.stories.tsx
- src/components/ui/Search/Suggestions/Suggestions.tsx
---
src/components/common/Navbar/navbar.scss | 2 +-
.../common/SearchInput/SearchInput.tsx | 110 +++++++++---------
.../common/SearchInput/search-input.scss | 8 ++
.../search/History/SearchHistory.stories.tsx | 30 +++--
.../search/History/SearchHistory.tsx | 37 +++---
.../SuggestionProductCard.tsx | 20 +++-
.../suggestion-product-card.scss | 7 ++
.../search/Suggestions/Suggestions.tsx | 81 +++----------
.../SuggestionsTopSearch.stories.tsx | 22 ++--
.../Suggestions/SuggestionsTopSearch.tsx | 37 ++++--
.../search/Suggestions/suggestions.scss | 30 ++---
.../Suggestions/Suggestions.stories.tsx | 11 +-
.../ui/Search/Suggestions/Suggestions.tsx | 38 +++---
src/sdk/search/useSearchHistory.ts | 24 ++--
src/sdk/search/useSearchInput.tsx | 43 +++++++
src/sdk/search/useSuggestions.ts | 48 ++++++++
src/sdk/search/useTopSearch.ts | 43 +++++++
tsconfig.json | 1 +
18 files changed, 371 insertions(+), 221 deletions(-)
create mode 100644 src/sdk/search/useSearchInput.tsx
create mode 100644 src/sdk/search/useSuggestions.ts
create mode 100644 src/sdk/search/useTopSearch.ts
diff --git a/src/components/common/Navbar/navbar.scss b/src/components/common/Navbar/navbar.scss
index dbd12b4f..293a80be 100644
--- a/src/components/common/Navbar/navbar.scss
+++ b/src/components/common/Navbar/navbar.scss
@@ -76,7 +76,7 @@
order: 0;
width: min-content;
- [data-store-input] {
+ &[data-store-search-input-dropdown-open="false"] [data-store-input] {
width: 0;
padding: 0;
border-width: 0;
diff --git a/src/components/common/SearchInput/SearchInput.tsx b/src/components/common/SearchInput/SearchInput.tsx
index 93990f5e..3e499b5d 100644
--- a/src/components/common/SearchInput/SearchInput.tsx
+++ b/src/components/common/SearchInput/SearchInput.tsx
@@ -1,17 +1,13 @@
-import {
- formatSearchState,
- initSearchState,
- sendAnalyticsEvent,
-} from '@faststore/sdk'
+import { sendAnalyticsEvent } from '@faststore/sdk'
import { SearchInput as UISearchInput } from '@faststore/ui'
import { useRouter } from 'next/router'
import {
forwardRef,
lazy,
Suspense,
- useCallback,
useRef,
useState,
+ useDeferredValue,
} from 'react'
import type { SearchEvent } from '@faststore/sdk'
import type {
@@ -21,6 +17,11 @@ import type {
import Icon from 'src/components/ui/Icon'
import useSearchHistory from 'src/sdk/search/useSearchHistory'
+import {
+ formatSearchPath,
+ SearchInputProvider,
+} from 'src/sdk/search/useSearchInput'
+import type { SearchInputContextValue } from 'src/sdk/search/useSearchInput'
import useOnClickOutside from 'src/sdk/ui/useOnClickOutside'
const Suggestions = lazy(() => import('src/components/search/Suggestions'))
@@ -30,30 +31,11 @@ declare type SearchInputProps = {
buttonTestId?: string
} & Omit
-const useSearchHandler = (callback: (term: string) => void) => {
- const router = useRouter()
- const { addToSearchHistory } = useSearchHistory()
-
- return useCallback(
- (term: string) => {
- const { pathname, search } = formatSearchState(
- initSearchState({
- term,
- base: '/s',
- })
- )
-
- sendAnalyticsEvent({
- name: 'search',
- params: { search_term: term },
- })
-
- addToSearchHistory(term)
- callback(term)
- router.push(`${pathname}${search}`)
- },
- [addToSearchHistory, callback, router]
- )
+const sendAnalytics = async (term: string) => {
+ sendAnalyticsEvent({
+ name: 'search',
+ params: { search_term: term },
+ })
}
const SearchInput = forwardRef(
@@ -62,12 +44,19 @@ const SearchInput = forwardRef(
ref
) {
const [searchQuery, setSearchQuery] = useState('')
+ const searchQueryDeferred = useDeferredValue(searchQuery)
const [suggestionsOpen, setSuggestionsOpen] = useState(false)
const searchRef = useRef(null)
- const handleSearch = useSearchHandler((term: string) => {
- setSuggestionsOpen(false)
- setSearchQuery(term)
- })
+ const { addToSearchHistory } = useSearchHistory()
+ const router = useRouter()
+
+ const onSearchInputSelection: SearchInputContextValue['onSearchInputSelection'] =
+ (term, path) => {
+ addToSearchHistory({ term, path })
+ sendAnalytics(term)
+ setSuggestionsOpen(false)
+ setSearchQuery(term)
+ }
useOnClickOutside(searchRef, () => setSuggestionsOpen(false))
@@ -77,29 +66,36 @@ const SearchInput = forwardRef(
data-store-search-input-wrapper
data-store-search-input-dropdown-open={suggestionsOpen}
>
-
- }
- placeholder="Search everything at the store"
- onChange={(e) => setSearchQuery(e.target.value)}
- onSubmit={handleSearch}
- onFocus={() => setSuggestionsOpen(true)}
- value={searchQuery}
- {...props}
- />
- {suggestionsOpen && (
-
-
))}
diff --git a/src/sdk/search/useSearchHistory.ts b/src/sdk/search/useSearchHistory.ts
index ffe74b43..7fa4cea5 100644
--- a/src/sdk/search/useSearchHistory.ts
+++ b/src/sdk/search/useSearchHistory.ts
@@ -2,25 +2,29 @@ import { useStorage } from '@faststore/sdk'
const storageKey = 'main::store::searchHistory'
-const MAX_HISTORY_SIZE = 5
+const MAX_HISTORY_SIZE = 4
+
+export interface History {
+ term: string
+ path: string
+}
export default function useSearchHistory(
- history: string[] = [],
+ history: History[] = [],
maxHistorySize: number = MAX_HISTORY_SIZE
) {
- const [searchHistory, setSearchHistory] = useStorage(
+ const [searchHistory, setSearchHistory] = useStorage(
storageKey,
history
)
- function addToSearchHistory(term: string) {
- const newHistory = [...new Set([term, ...searchHistory])]
+ function addToSearchHistory(newHistory: History) {
+ const set = new Set()
+ const newHistoryArray = [newHistory, ...searchHistory]
+ .slice(0, maxHistorySize)
+ .filter((item) => !set.has(item.term) && set.add(item.term), set)
- setSearchHistory(
- newHistory.length > maxHistorySize
- ? newHistory.slice(0, maxHistorySize)
- : newHistory
- )
+ setSearchHistory(newHistoryArray)
}
function clearSearchHistory() {
diff --git a/src/sdk/search/useSearchInput.tsx b/src/sdk/search/useSearchInput.tsx
new file mode 100644
index 00000000..5780857e
--- /dev/null
+++ b/src/sdk/search/useSearchInput.tsx
@@ -0,0 +1,43 @@
+import { formatSearchState, initSearchState } from '@faststore/sdk'
+import type { PropsWithChildren } from 'react'
+import { createContext, useContext } from 'react'
+
+export const formatSearchPath = (term: string) => {
+ const { pathname, search } = formatSearchState(
+ initSearchState({
+ term,
+ base: '/s',
+ })
+ )
+
+ return `${pathname}${search}`
+}
+
+export interface SearchInputContextValue {
+ onSearchInputSelection?: (term: string, path: string) => void
+}
+
+const SearchInputContext = createContext(null)
+
+export function SearchInputProvider({
+ onSearchInputSelection,
+ children,
+}: PropsWithChildren) {
+ return (
+
+ {children}
+
+ )
+}
+
+const useSearchInput = () => {
+ const context = useContext(SearchInputContext)
+
+ if (!context) {
+ throw new Error('Do not use outside the SearchInputContext context.')
+ }
+
+ return context
+}
+
+export default useSearchInput
diff --git a/src/sdk/search/useSuggestions.ts b/src/sdk/search/useSuggestions.ts
new file mode 100644
index 00000000..b2c8ba9d
--- /dev/null
+++ b/src/sdk/search/useSuggestions.ts
@@ -0,0 +1,48 @@
+import { useSession } from '@faststore/sdk'
+import { gql } from '@vtex/graphql-utils'
+
+import { useQuery } from 'src/sdk/graphql/useQuery'
+import type {
+ SearchSuggestionsQueryQuery as Query,
+ SearchSuggestionsQueryQueryVariables as Variables,
+} from '@generated/graphql'
+
+const MAX_SUGGESTIONS = 5
+
+const query = gql`
+ query SearchSuggestionsQuery(
+ $term: String!
+ $selectedFacets: [IStoreSelectedFacet!]
+ ) {
+ search(first: 5, term: $term, selectedFacets: $selectedFacets) {
+ suggestions {
+ terms {
+ value
+ }
+ products {
+ ...ProductSummary_product
+ }
+ }
+ }
+ }
+`
+
+function useSuggestions(term: string, limit: number = MAX_SUGGESTIONS) {
+ const { channel, locale } = useSession()
+
+ const { data, error } = useQuery(query, {
+ term,
+ selectedFacets: [
+ { key: 'channel', value: channel ?? '' },
+ { key: 'locale', value: locale },
+ ],
+ })
+
+ return {
+ terms: (data?.search.suggestions.terms ?? []).slice(0, limit),
+ products: (data?.search.suggestions.products ?? []).slice(0, limit),
+ isLoading: !error && !data,
+ }
+}
+
+export default useSuggestions
diff --git a/src/sdk/search/useTopSearch.ts b/src/sdk/search/useTopSearch.ts
new file mode 100644
index 00000000..8431d18f
--- /dev/null
+++ b/src/sdk/search/useTopSearch.ts
@@ -0,0 +1,43 @@
+import { useSession } from '@faststore/sdk'
+import { gql } from '@vtex/graphql-utils'
+
+import { useQuery } from 'src/sdk/graphql/useQuery'
+import type {
+ StoreSuggestionTerm,
+ SearchSuggestionsQueryQuery as Query,
+ SearchSuggestionsQueryQueryVariables as Variables,
+} from '@generated/graphql'
+
+const MAX_TOP_SEARCH_TERMS = 5
+
+const query = gql`
+ query SearchSuggestionsQuery {
+ search {
+ suggestions {
+ terms
+ }
+ }
+ }
+`
+
+function useTopSearch(
+ initialTerms: StoreSuggestionTerm[] = [],
+ limit: number = MAX_TOP_SEARCH_TERMS
+) {
+ const { channel, locale } = useSession()
+
+ const { data, error } = useQuery(query, {
+ term: '',
+ selectedFacets: [
+ { key: 'channel', value: channel ?? '' },
+ { key: 'locale', value: locale },
+ ],
+ })
+
+ return {
+ terms: (data?.search.suggestions.terms ?? initialTerms).slice(0, limit),
+ isLoading: !error && !data,
+ }
+}
+
+export default useTopSearch
diff --git a/tsconfig.json b/tsconfig.json
index 83f41fdc..eeae7e24 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,6 +1,7 @@
{
"extends": "@vtex/tsconfig",
"compilerOptions": {
+ "types": ["react/next"],
"allowSyntheticDefaultImports": true,
"moduleResolution": "node",
"jsx": "preserve",
From 5be7614495c2d3793be757f07602fff25096f742 Mon Sep 17 00:00:00 2001
From: "Filipe W. Lima"
Date: Fri, 10 Jun 2022 13:51:52 -0300
Subject: [PATCH 02/11] Add entries to the change log
---
CHANGELOG.md | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c44d539e..ca2f9b42 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
+- The search input now includes the last 4 previously searched terms (`SearchHistory`) ([#112](https://github.com/vtex-sites/nextjs.store/pull/112)).
+- The top 5 searches (`SuggestionsTopSearch`) are now integrated into the search input ([#112](https://github.com/vtex-sites/nextjs.store/pull/112)).
- Support for the new type definitions from React 18 ([#113](https://github.com/vtex-sites/nextjs.store/pull/113)).
### Changed
@@ -19,6 +21,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
+- The search input's dropdown not closing when a suggested product was selected ([#112](https://github.com/vtex-sites/nextjs.store/pull/112).
+
### Security
## [22.23.0.beta] - 2022-06-10
From d4ed4e0ca375cf1762bf2a49a6354c8964d30bc4 Mon Sep 17 00:00:00 2001
From: Daniel Zanzini
Date: Thu, 9 Jun 2022 19:29:57 -0300
Subject: [PATCH 03/11] fix: duplicated query at `useTopSearch` hook
Cherry-picked from the `gatsby.store` repo.
* Fixes `useTopSearch` query
* Updates CHANGELOG.md
---
Conflicts:
- @generated/graphql/index.ts
- @generated/graphql/persisted.json
- CHANGELOG.md
---
@generated/graphql/index.ts | 75 +++++++++++++++++--------------
@generated/graphql/persisted.json | 3 +-
src/sdk/search/useTopSearch.ts | 11 +++--
3 files changed, 52 insertions(+), 37 deletions(-)
diff --git a/@generated/graphql/index.ts b/@generated/graphql/index.ts
index 758c5a04..a3bf262a 100644
--- a/@generated/graphql/index.ts
+++ b/@generated/graphql/index.ts
@@ -600,39 +600,6 @@ export type Filter_FacetsFragment = {
}>
}
-export type SearchSuggestionsQueryQueryVariables = Exact<{
- term: Scalars['String']
- selectedFacets: InputMaybe | IStoreSelectedFacet>
-}>
-
-export type SearchSuggestionsQueryQuery = {
- search: {
- suggestions: {
- terms: Array<{ value: string }>
- products: Array<{
- slug: string
- sku: string
- name: string
- gtin: string
- id: string
- brand: { name: string; brandName: string }
- isVariantOf: { productGroupID: string; name: string }
- image: Array<{ url: string; alternateName: string }>
- offers: {
- lowPrice: number
- offers: Array<{
- availability: string
- price: number
- listPrice: number
- quantity: number
- seller: { identifier: string }
- }>
- }
- }>
- }
- }
-}
-
export type ProductDetailsFragment_ProductFragment = {
sku: string
name: string
@@ -872,6 +839,48 @@ export type ProductsQueryQuery = {
}
}
+export type SearchSuggestionsQueryQueryVariables = Exact<{
+ term: Scalars['String']
+ selectedFacets: InputMaybe | IStoreSelectedFacet>
+}>
+
+export type SearchSuggestionsQueryQuery = {
+ search: {
+ suggestions: {
+ terms: Array<{ value: string }>
+ products: Array<{
+ slug: string
+ sku: string
+ name: string
+ gtin: string
+ id: string
+ brand: { name: string; brandName: string }
+ isVariantOf: { productGroupID: string; name: string }
+ image: Array<{ url: string; alternateName: string }>
+ offers: {
+ lowPrice: number
+ offers: Array<{
+ availability: string
+ price: number
+ listPrice: number
+ quantity: number
+ seller: { identifier: string }
+ }>
+ }
+ }>
+ }
+ }
+}
+
+export type TopSearchSuggestionsQueryQueryVariables = Exact<{
+ term: Scalars['String']
+ selectedFacets: InputMaybe | IStoreSelectedFacet>
+}>
+
+export type TopSearchSuggestionsQueryQuery = {
+ search: { suggestions: { terms: Array<{ value: string }> } }
+}
+
export type ValidateSessionMutationVariables = Exact<{
session: IStoreSession
search: Scalars['String']
diff --git a/@generated/graphql/persisted.json b/@generated/graphql/persisted.json
index 8673fcf5..e3f3c4b1 100644
--- a/@generated/graphql/persisted.json
+++ b/@generated/graphql/persisted.json
@@ -1,10 +1,11 @@
{
- "SearchSuggestionsQuery": "query SearchSuggestionsQuery($term: String!, $selectedFacets: [IStoreSelectedFacet!]) {\n search(first: 5, term: $term, selectedFacets: $selectedFacets) {\n suggestions {\n terms {\n value\n }\n products {\n id: productID\n slug\n sku\n brand {\n brandName: name\n name\n }\n name\n gtin\n isVariantOf {\n productGroupID\n name\n }\n image {\n url\n alternateName\n }\n offers {\n lowPrice\n offers {\n availability\n price\n listPrice\n quantity\n seller {\n identifier\n }\n }\n }\n }\n }\n }\n}\n",
"ProductGalleryQuery": "query ProductGalleryQuery($first: Int!, $after: String!, $sort: StoreSort!, $term: String!, $selectedFacets: [IStoreSelectedFacet!]!) {\n search(\n first: $first\n after: $after\n sort: $sort\n term: $term\n selectedFacets: $selectedFacets\n ) {\n products {\n pageInfo {\n totalCount\n }\n }\n facets {\n key\n label\n type\n values {\n label\n value\n selected\n quantity\n }\n }\n }\n}\n",
"ServerCollectionPageQuery": "query ServerCollectionPageQuery($slug: String!) {\n collection(slug: $slug) {\n seo {\n title\n description\n }\n breadcrumbList {\n itemListElement {\n item\n name\n position\n }\n }\n meta {\n selectedFacets {\n key\n value\n }\n }\n }\n}\n",
"ServerProductPageQuery": "query ServerProductPageQuery($id: String!) {\n product(locator: [{key: \"id\", value: $id}]) {\n id: productID\n slug\n seo {\n title\n description\n }\n brand {\n name\n }\n sku\n gtin\n name\n description\n breadcrumbList {\n itemListElement {\n item\n name\n position\n }\n }\n image {\n url\n alternateName\n }\n offers {\n lowPrice\n highPrice\n priceCurrency\n offers {\n availability\n price\n priceValidUntil\n priceCurrency\n itemCondition\n seller {\n identifier\n }\n listPrice\n }\n }\n isVariantOf {\n productGroupID\n name\n }\n additionalProperty {\n propertyID\n name\n value\n valueReference\n }\n }\n}\n",
"ValidateCartMutation": "mutation ValidateCartMutation($cart: IStoreCart!) {\n validateCart(cart: $cart) {\n order {\n orderNumber\n acceptedOffer {\n seller {\n identifier\n }\n quantity\n price\n listPrice\n itemOffered {\n sku\n name\n image {\n url\n alternateName\n }\n brand {\n name\n }\n isVariantOf {\n productGroupID\n name\n }\n gtin\n additionalProperty {\n propertyID\n name\n value\n valueReference\n }\n }\n }\n }\n messages {\n text\n status\n }\n }\n}\n",
"BrowserProductQuery": "query BrowserProductQuery($locator: [IStoreSelectedFacet!]!) {\n product(locator: $locator) {\n id: productID\n sku\n name\n gtin\n description\n isVariantOf {\n productGroupID\n name\n }\n image {\n url\n alternateName\n }\n brand {\n name\n }\n offers {\n lowPrice\n offers {\n availability\n price\n listPrice\n seller {\n identifier\n }\n }\n }\n breadcrumbList {\n itemListElement {\n item\n name\n position\n }\n }\n additionalProperty {\n propertyID\n name\n value\n valueReference\n }\n }\n}\n",
"ProductsQuery": "query ProductsQuery($first: Int!, $after: String, $sort: StoreSort!, $term: String!, $selectedFacets: [IStoreSelectedFacet!]!) {\n search(\n first: $first\n after: $after\n sort: $sort\n term: $term\n selectedFacets: $selectedFacets\n ) {\n products {\n pageInfo {\n totalCount\n }\n edges {\n node {\n id: productID\n slug\n sku\n brand {\n brandName: name\n name\n }\n name\n gtin\n isVariantOf {\n productGroupID\n name\n }\n image {\n url\n alternateName\n }\n offers {\n lowPrice\n offers {\n availability\n price\n listPrice\n quantity\n seller {\n identifier\n }\n }\n }\n }\n }\n }\n }\n}\n",
+ "SearchSuggestionsQuery": "query SearchSuggestionsQuery($term: String!, $selectedFacets: [IStoreSelectedFacet!]) {\n search(first: 5, term: $term, selectedFacets: $selectedFacets) {\n suggestions {\n terms {\n value\n }\n products {\n id: productID\n slug\n sku\n brand {\n brandName: name\n name\n }\n name\n gtin\n isVariantOf {\n productGroupID\n name\n }\n image {\n url\n alternateName\n }\n offers {\n lowPrice\n offers {\n availability\n price\n listPrice\n quantity\n seller {\n identifier\n }\n }\n }\n }\n }\n }\n}\n",
+ "TopSearchSuggestionsQuery": "query TopSearchSuggestionsQuery($term: String!, $selectedFacets: [IStoreSelectedFacet!]) {\n search(first: 5, term: $term, selectedFacets: $selectedFacets) {\n suggestions {\n terms {\n value\n }\n }\n }\n}\n",
"ValidateSession": "mutation ValidateSession($session: IStoreSession!, $search: String!) {\n validateSession(session: $session, search: $search) {\n locale\n channel\n country\n postalCode\n currency {\n code\n symbol\n }\n person {\n id\n email\n givenName\n familyName\n }\n }\n}\n"
}
diff --git a/src/sdk/search/useTopSearch.ts b/src/sdk/search/useTopSearch.ts
index 8431d18f..54e98f0b 100644
--- a/src/sdk/search/useTopSearch.ts
+++ b/src/sdk/search/useTopSearch.ts
@@ -11,10 +11,15 @@ import type {
const MAX_TOP_SEARCH_TERMS = 5
const query = gql`
- query SearchSuggestionsQuery {
- search {
+ query TopSearchSuggestionsQuery(
+ $term: String!
+ $selectedFacets: [IStoreSelectedFacet!]
+ ) {
+ search(first: 5, term: $term, selectedFacets: $selectedFacets) {
suggestions {
- terms
+ terms {
+ value
+ }
}
}
}
From 86aa107bdb2f1cf072c41975bb6dc05229f424de Mon Sep 17 00:00:00 2001
From: "Filipe W. Lima"
Date: Fri, 10 Jun 2022 18:35:37 -0300
Subject: [PATCH 04/11] Undo unnecessary change to `tsconfig.json`
I had done that to add support for types from React 18 on Gatsby but that is not needed in the NextJS case. The support for React 18 types was done in a previous PR.
---
tsconfig.json | 1 -
1 file changed, 1 deletion(-)
diff --git a/tsconfig.json b/tsconfig.json
index eeae7e24..83f41fdc 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,7 +1,6 @@
{
"extends": "@vtex/tsconfig",
"compilerOptions": {
- "types": ["react/next"],
"allowSyntheticDefaultImports": true,
"moduleResolution": "node",
"jsx": "preserve",
From 889d26b4b81053ec0c26bf061299180f80f74b0b Mon Sep 17 00:00:00 2001
From: "Filipe W. Lima"
Date: Mon, 13 Jun 2022 13:51:43 -0300
Subject: [PATCH 05/11] Fix `SearchHistory` storie, it was not loading
---
src/components/search/History/SearchHistory.stories.tsx | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/components/search/History/SearchHistory.stories.tsx b/src/components/search/History/SearchHistory.stories.tsx
index 7ddbcdec..3162cc88 100644
--- a/src/components/search/History/SearchHistory.stories.tsx
+++ b/src/components/search/History/SearchHistory.stories.tsx
@@ -28,7 +28,12 @@ const Template = (props: SearchHistoryProps) => {
export const Default = Template.bind({})
Default.args = {
- history: ['headphone', 'audio & video', 'mh-7000', 'jbl go'],
+ history: [
+ { term: 'headphone', path: '/' },
+ { term: 'audio & video', path: '/' },
+ { term: 'mh-7000', path: '/' },
+ { term: 'jbl go', path: '/' },
+ ],
}
Default.parameters = {
From 655496b572866ad2fce6c7f7e80a2677daebc1c4 Mon Sep 17 00:00:00 2001
From: "Filipe W. Lima"
Date: Mon, 13 Jun 2022 16:34:21 -0300
Subject: [PATCH 06/11] Fix the suggested term's link color
Part of the link had the blue color instead of light gray. That's because the light gray selector had less CSS specificity than the blue one, so I increased the specificity. I think will be addressed when
we got CSS modules working for all components.
---
src/components/search/Suggestions/suggestions.scss | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/components/search/Suggestions/suggestions.scss b/src/components/search/Suggestions/suggestions.scss
index 82f6a11e..94038e5c 100644
--- a/src/components/search/Suggestions/suggestions.scss
+++ b/src/components/search/Suggestions/suggestions.scss
@@ -27,7 +27,9 @@
}
}
-[data-fs-search-suggestion-section="terms"] {
+// Temporarily increased CSS specificity because the normal link blue color
+// was winning. Hoping this will be fixed when using CSS modules.
+[data-fs-search-suggestions] [data-fs-search-suggestion-section="terms"] {
[data-fs-link] {
color: var(--fs-color-text-light);
}
From 829387301cd757cec629e5d64cb26fbf36ff6623 Mon Sep 17 00:00:00 2001
From: "Filipe W. Lima"
Date: Mon, 13 Jun 2022 17:43:34 -0300
Subject: [PATCH 07/11] Trigger CI with an empty commit
From 506d41ade7e0d320976806341895b52dc57f72e0 Mon Sep 17 00:00:00 2001
From: "Filipe W. Lima"
Date: Mon, 13 Jun 2022 19:10:26 -0300
Subject: [PATCH 08/11] Hide Top Search dropdown when there is no data
This week querying for the top search for the storeframework account returned no results, that's because this is based on real usage data. Because of that, we were showing the "Top Search" dropdown with the heading but no data. In this scenario, let's not render anything till we decide what to do.
---
src/components/search/Suggestions/SuggestionsTopSearch.tsx | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/components/search/Suggestions/SuggestionsTopSearch.tsx b/src/components/search/Suggestions/SuggestionsTopSearch.tsx
index 5bf5ba0e..c11102a6 100644
--- a/src/components/search/Suggestions/SuggestionsTopSearch.tsx
+++ b/src/components/search/Suggestions/SuggestionsTopSearch.tsx
@@ -34,6 +34,10 @@ const SuggestionsTopSearch = forwardRef<
return
Loading...
}
+ if (terms.length === 0) {
+ return null
+ }
+
return (
Date: Mon, 13 Jun 2022 19:23:37 -0300
Subject: [PATCH 09/11] Fix entries order in the change log
---
CHANGELOG.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 51246357..e567c5a7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,10 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Added
-- 301 redirects when visiting old VTEX product routes ([#93](https://github.com/vtex-sites/nextjs.store/pull/93))
- The search input now includes the last 4 previously searched terms (`SearchHistory`) ([#112](https://github.com/vtex-sites/nextjs.store/pull/112)).
- The top 5 searches (`SuggestionsTopSearch`) are now integrated into the search input ([#112](https://github.com/vtex-sites/nextjs.store/pull/112)).
+- 301 redirects when visiting old VTEX product routes ([#93](https://github.com/vtex-sites/nextjs.store/pull/93))
- Support for the new type definitions from React 18 ([#113](https://github.com/vtex-sites/nextjs.store/pull/113)).
### Changed
@@ -21,9 +21,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Removed
### Fixed
-- Status code when error occurs (404/500) ([#116](https://github.com/vtex-sites/nextjs.store/pull/116))
- The search input's dropdown not closing when a suggested product was selected ([#112](https://github.com/vtex-sites/nextjs.store/pull/112).
+- Status code when error occurs (404/500) ([#116](https://github.com/vtex-sites/nextjs.store/pull/116))
### Security
From 54d59da041536e171d422e3b3887b8a0ac20bd0c Mon Sep 17 00:00:00 2001
From: "Filipe W. Lima"
Date: Mon, 13 Jun 2022 21:03:58 -0300
Subject: [PATCH 10/11] Fix not showing the outline when focusing on a
suggested product card
And also adjust the padding so the link covers it.
Reported by Fanny!
---
.../SuggestionProductCard/suggestion-product-card.scss | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/src/components/search/SuggestionProductCard/suggestion-product-card.scss b/src/components/search/SuggestionProductCard/suggestion-product-card.scss
index 18ea0792..7c5bfd44 100644
--- a/src/components/search/SuggestionProductCard/suggestion-product-card.scss
+++ b/src/components/search/SuggestionProductCard/suggestion-product-card.scss
@@ -1,8 +1,6 @@
@import "src/styles/scaffold";
[data-fs-suggestion-product-card] {
- padding: var(--fs-spacing-1) 0;
-
[data-card-image] {
display: flex;
}
@@ -40,9 +38,8 @@
}
[data-store-link] {
- padding: 0 var(--fs-spacing-3);
+ padding: var(--fs-spacing-1) var(--fs-spacing-3);
color: inherit;
text-decoration: none;
- outline: none;
}
}
From 6300c54e3803176b1302fec2ec4c43ae5fd4627d Mon Sep 17 00:00:00 2001
From: "Filipe W. Lima"
Date: Wed, 15 Jun 2022 14:30:10 -0300
Subject: [PATCH 11/11] Prefix a comment with TODO for easier reference in the
future
See suggestion:
https://github.com/vtex-sites/nextjs.store/pull/112#discussion_r897236782
---
src/components/search/Suggestions/suggestions.scss | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/search/Suggestions/suggestions.scss b/src/components/search/Suggestions/suggestions.scss
index 20dbbdfa..6bb16496 100644
--- a/src/components/search/Suggestions/suggestions.scss
+++ b/src/components/search/Suggestions/suggestions.scss
@@ -27,7 +27,7 @@
}
}
-// Temporarily increased CSS specificity because the normal link blue color
+// TODO: Temporarily increased CSS specificity because the normal link blue color
// was winning. Hoping this will be fixed when using CSS modules.
[data-fs-search-suggestions] [data-fs-search-suggestion-section="terms"] {
[data-fs-link] {