From 9ae219706e4447179997ca0240a011bbf34ce5fd Mon Sep 17 00:00:00 2001 From: dangthang1903 Date: Wed, 17 Jul 2024 15:07:49 +0700 Subject: [PATCH 1/3] chore: update drawer --- app/components/Drawer.tsx | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/app/components/Drawer.tsx b/app/components/Drawer.tsx index f693d87..e6288ca 100644 --- a/app/components/Drawer.tsx +++ b/app/components/Drawer.tsx @@ -1,9 +1,9 @@ import {cn} from '@/lib/utils'; import {Dialog, Transition} from '@headlessui/react'; +import {useLocation} from '@remix-run/react'; import {Fragment, useEffect, useState} from 'react'; import {IconArrowLeft, IconClose} from './Icon'; import {Heading} from './Text'; -import { useLocation } from '@remix-run/react'; /** * Drawer component that opens on user click. @@ -72,7 +72,9 @@ export function Drawer({ 'transform text-left align-middle shadow-xl transition-all', openFrom === 'left' ? 'h-screen-dynamic w-screen max-w-96 bg-background-subtle-1' - : 'h-screen-dynamic w-screen max-w-96', + : openFrom === 'top' + ? 'h-fit w-screen bg-background-subtle-1' + : 'h-screen-dynamic w-screen max-w-96', isForm === 'cart' ? 'bg-background-basic' : 'bg-background-subtle-1', @@ -80,9 +82,11 @@ export function Drawer({ >
{isBackMenu && ( @@ -93,7 +97,7 @@ export function Drawer({ data-test="close-cart" > @@ -134,7 +138,7 @@ Drawer.Title = Dialog.Title; export function useDrawer(openDefault = false) { const [isOpen, setIsOpen] = useState(openDefault); - let { pathname } = useLocation(); + let {pathname} = useLocation(); useEffect(() => { if (isOpen) { closeDrawer(); From b0e915f07cc10e75444bfd8dce6e9925311b70a4 Mon Sep 17 00:00:00 2001 From: dangthang1903 Date: Wed, 17 Jul 2024 15:08:50 +0700 Subject: [PATCH 2/3] chore: update setting search type --- app/weaverse/schema.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/app/weaverse/schema.ts b/app/weaverse/schema.ts index c173691..bc31a98 100644 --- a/app/weaverse/schema.ts +++ b/app/weaverse/schema.ts @@ -33,7 +33,7 @@ export const themeSchema: HydrogenThemeSchema = { inputs: [ { type: "toggle-group", - label: "Header menu type", + label: "Header menu type for desktop", name: "typeMenuHeader", configs: { options: [ @@ -71,6 +71,18 @@ export const themeSchema: HydrogenThemeSchema = { height: 116, }, }, + { + type: "toggle-group", + label: "Search type for desktop", + name: "searchType", + configs: { + options: [ + { value: "headerSearch", label: "Header search" }, + { value: "drawerSearch", label: "Drawer search" }, + ] + }, + defaultValue: "headerSearch" + }, ], }, { From 38c8ff55cf84de6d5c794bc84f62e762bff78e99 Mon Sep 17 00:00:00 2001 From: dangthang1903 Date: Wed, 17 Jul 2024 15:09:45 +0700 Subject: [PATCH 3/3] chore: update predictive search --- app/components/Header/MenuDrawerHeader.tsx | 29 +---- app/components/Header/MenuMegaHeader.tsx | 26 +--- app/components/Header/SearchToggle.tsx | 58 +++++++++ .../SearchDrawer/SearchTypeDrawer.tsx} | 12 +- .../SearchDrawer/SearchTypeDrawerResults.tsx} | 51 ++++---- .../SearchHeader/SearchTypeHeader.tsx | 42 +++++++ .../SearchHeader/SearchTypeHeaderResults.tsx | 118 ++++++++++++++++++ 7 files changed, 254 insertions(+), 82 deletions(-) create mode 100644 app/components/Header/SearchToggle.tsx rename app/components/predictive-search/{PredictiveSearch.tsx => PredictiveSearch/SearchDrawer/SearchTypeDrawer.tsx} (75%) rename app/components/predictive-search/{PredictiveSearchResults.tsx => PredictiveSearch/SearchDrawer/SearchTypeDrawerResults.tsx} (73%) create mode 100644 app/components/predictive-search/PredictiveSearch/SearchHeader/SearchTypeHeader.tsx create mode 100644 app/components/predictive-search/PredictiveSearch/SearchHeader/SearchTypeHeaderResults.tsx diff --git a/app/components/Header/MenuDrawerHeader.tsx b/app/components/Header/MenuDrawerHeader.tsx index 6487839..80644d7 100644 --- a/app/components/Header/MenuDrawerHeader.tsx +++ b/app/components/Header/MenuDrawerHeader.tsx @@ -1,4 +1,4 @@ -import {Await, useLocation} from '@remix-run/react'; +import {Await} from '@remix-run/react'; import {CartForm} from '@shopify/hydrogen'; import {useThemeSettings} from '@weaverse/hydrogen'; import {useCartFetchers} from '~/hooks/useCartFetchers'; @@ -15,8 +15,8 @@ import {IconAccount, IconLogin, IconSearch} from '../Icon'; import {Link} from '../Link'; import {Logo} from '../Logo'; import {DrawerMenu} from './menu/DrawerMenu'; -import {PredictiveSearch} from '../predictive-search/PredictiveSearch'; import {CartCount} from './CartCount'; +import { SearchToggle } from './SearchToggle'; export function UseMenuDrawerHeader({ header, @@ -112,7 +112,7 @@ function HeaderMenuDrawer({menu}: {menu?: EnhancedMenu | null | undefined}) { - + ); } - -function SearchToggle() { - const {isOpen, closeDrawer, openDrawer} = useDrawer(); - return ( - <> - - - - - - ); -} diff --git a/app/components/Header/MenuMegaHeader.tsx b/app/components/Header/MenuMegaHeader.tsx index e06d21e..26f40dc 100644 --- a/app/components/Header/MenuMegaHeader.tsx +++ b/app/components/Header/MenuMegaHeader.tsx @@ -1,4 +1,4 @@ -import {Await, useLocation} from '@remix-run/react'; +import {Await} from '@remix-run/react'; import {CartForm} from '@shopify/hydrogen'; import {useThemeSettings} from '@weaverse/hydrogen'; import {useCartFetchers} from '~/hooks/useCartFetchers'; @@ -15,8 +15,8 @@ import {IconAccount, IconLogin, IconSearch} from '../Icon'; import {Link} from '../Link'; import {Logo} from '../Logo'; import {MegaMenu} from './menu/MegaMenu'; -import {PredictiveSearch} from '../predictive-search/PredictiveSearch'; import {CartCount} from './CartCount'; +import { SearchToggle } from './SearchToggle'; export function UseMenuMegaHeader({ header, @@ -126,25 +126,3 @@ function AccountLink({className}: {className?: string}) { ); } -function SearchToggle() { - const {isOpen, closeDrawer, openDrawer} = useDrawer(); - return ( - <> - - - - - - ); -} diff --git a/app/components/Header/SearchToggle.tsx b/app/components/Header/SearchToggle.tsx new file mode 100644 index 0000000..0482253 --- /dev/null +++ b/app/components/Header/SearchToggle.tsx @@ -0,0 +1,58 @@ +import {useThemeSettings} from '@weaverse/hydrogen'; +import {Drawer, useDrawer} from '../Drawer'; +import {IconSearch} from '../Icon'; +import { SearchTypeHeader } from '../predictive-search/PredictiveSearch/SearchHeader/SearchTypeHeader'; +import { SearchTypeDrawer } from '../predictive-search/PredictiveSearch/SearchDrawer/SearchTypeDrawer'; +import { useEffect, useState } from 'react'; + +type TypeOpenFrom = 'top' | 'right' | 'left'; + +export function SearchToggle({isOpenDrawerHearder}: {isOpenDrawerHearder?: boolean}) { + const {isOpen, closeDrawer, openDrawer} = useDrawer(); + let settings = useThemeSettings(); + const [searchType, setSearchType] = useState(settings?.searchType); + const [openFrom, setOpenFrom] = useState( + searchType === 'headerSearch' ? 'top' : 'right' + ); + + useEffect(() => { + const handleResize = () => { + if (window.innerWidth <= 1280) { + setSearchType('drawerSearch'); + setOpenFrom('left'); + } else { + setSearchType(settings?.searchType); + if (settings?.searchType === 'drawerSearch' && isOpenDrawerHearder) { + setOpenFrom('left'); + } else { + setOpenFrom(settings?.searchType === 'headerSearch' ? 'top' : 'right'); + } + } + }; + + window.addEventListener('resize', handleResize); + handleResize(); + + return () => window.removeEventListener('resize', handleResize); + }, [settings?.searchType, isOpenDrawerHearder]); + return ( + <> + + + {searchType === 'headerSearch' && } + {searchType === 'drawerSearch' && } + + + ); +} diff --git a/app/components/predictive-search/PredictiveSearch.tsx b/app/components/predictive-search/PredictiveSearch/SearchDrawer/SearchTypeDrawer.tsx similarity index 75% rename from app/components/predictive-search/PredictiveSearch.tsx rename to app/components/predictive-search/PredictiveSearch/SearchDrawer/SearchTypeDrawer.tsx index b977016..2978297 100644 --- a/app/components/predictive-search/PredictiveSearch.tsx +++ b/app/components/predictive-search/PredictiveSearch/SearchDrawer/SearchTypeDrawer.tsx @@ -1,14 +1,14 @@ -import {IconSearch} from '../Icon'; -import {Input} from '../Input'; -import {PredictiveSearchResults} from './PredictiveSearchResults'; -import {PredictiveSearchForm} from './SearchForm'; +import {IconSearch} from '../../../Icon'; +import {Input} from '../../../Input'; +import {PredictiveSearchForm} from '../../SearchForm'; +import { SearchTypeDrawerResults } from './SearchTypeDrawerResults'; interface PredictiveSearchProps { // Predictive search props isOpen?: boolean; } -export function PredictiveSearch(props: PredictiveSearchProps) { +export function SearchTypeDrawer(props: PredictiveSearchProps) { let {isOpen} = props; return (
@@ -36,7 +36,7 @@ export function PredictiveSearch(props: PredictiveSearchProps) {
)} - {isOpen && } + {isOpen && } ); } diff --git a/app/components/predictive-search/PredictiveSearchResults.tsx b/app/components/predictive-search/PredictiveSearch/SearchDrawer/SearchTypeDrawerResults.tsx similarity index 73% rename from app/components/predictive-search/PredictiveSearchResults.tsx rename to app/components/predictive-search/PredictiveSearch/SearchDrawer/SearchTypeDrawerResults.tsx index 82d029a..6a1ae75 100644 --- a/app/components/predictive-search/PredictiveSearchResults.tsx +++ b/app/components/predictive-search/PredictiveSearch/SearchDrawer/SearchTypeDrawerResults.tsx @@ -1,8 +1,8 @@ import {Link} from '@remix-run/react'; -import {PredictiveSearchResult} from './PredictiveSearchResult'; -import {usePredictiveSearch} from './usePredictiveSearch'; +import {PredictiveSearchResult} from '../../PredictiveSearchResult'; +import {usePredictiveSearch} from '../../usePredictiveSearch'; -export function PredictiveSearchResults() { +export function SearchTypeDrawerResults() { const {results, totalResults, searchTerm, searchInputRef} = usePredictiveSearch(); @@ -70,29 +70,30 @@ export function PredictiveSearchResults() { type={products.type} /> {/* view all results /search?q=term */} - )} {pages && ( -
- -
- )} +
+ +
+ )} {searchTerm.current && ( - -

Show All Results ({totalResultsCount})

- - )} + +

+ Show All Results ({totalResultsCount}) +

+ + )} ); @@ -108,10 +109,8 @@ function NoPredictiveSearchResults({ } return (
-

- NO RESULTS -

-

+

NO RESULTS

+

No results found for {searchTerm.current}

diff --git a/app/components/predictive-search/PredictiveSearch/SearchHeader/SearchTypeHeader.tsx b/app/components/predictive-search/PredictiveSearch/SearchHeader/SearchTypeHeader.tsx new file mode 100644 index 0000000..a5d8f8a --- /dev/null +++ b/app/components/predictive-search/PredictiveSearch/SearchHeader/SearchTypeHeader.tsx @@ -0,0 +1,42 @@ +import {IconSearch} from '~/components/Icon'; +import {Input} from '~/components/Input'; +import {PredictiveSearchForm} from '../../SearchForm'; +import { SearchTypeHeaderResults } from './SearchTypeHeaderResults'; + +interface PredictiveSearchProps { + // Predictive search props + isOpen?: boolean; +} + +export function SearchTypeHeader(props: PredictiveSearchProps) { + let {isOpen} = props; + return ( +
+ + {({fetchResults, inputRef}) => ( +
+ + + + } + autoFocus={true} + /> +
+ )} +
+ {isOpen && } +
+ ); +} diff --git a/app/components/predictive-search/PredictiveSearch/SearchHeader/SearchTypeHeaderResults.tsx b/app/components/predictive-search/PredictiveSearch/SearchHeader/SearchTypeHeaderResults.tsx new file mode 100644 index 0000000..05b43d9 --- /dev/null +++ b/app/components/predictive-search/PredictiveSearch/SearchHeader/SearchTypeHeaderResults.tsx @@ -0,0 +1,118 @@ +import {Link} from '@remix-run/react'; +import {PredictiveSearchResult} from '../../PredictiveSearchResult'; +import {usePredictiveSearch} from '../../usePredictiveSearch'; + +export function SearchTypeHeaderResults() { + const {results, totalResults, searchTerm, searchInputRef} = + usePredictiveSearch(); + + let queries = results?.find((result) => result.type === 'queries'); + let articles = results?.find((result) => result.type === 'articles'); + let products = results?.find((result) => result.type === 'products'); + let pages = results?.find((result) => result.type === 'pages'); + let totalResultsCount = totalResults || 0; + function goToSearchResult(event: React.MouseEvent) { + let type = event.currentTarget.dataset.type; + if (!searchInputRef.current) return; + if (type === 'SearchQuerySuggestion') { + searchInputRef.current.value = event.currentTarget.innerText; + // dispatch event onchange for the search + searchInputRef.current.focus(); + } else { + searchInputRef.current.blur(); + searchInputRef.current.value = ''; + // close the aside + window.location.href = event.currentTarget.href; + } + } + + if (!totalResults) { + return ( +
+ +
+ ); + } + return ( +
+
+
+ {queries && ( +
+ +
+ )} + {articles && ( +
+ +
+ )} +
+ {products && ( +
+ + {/* view all results /search?q=term */} + {searchTerm.current && ( + +

+ Show All Results ({totalResultsCount}) +

+ + )} +
+ )} + {pages && ( +
+ +
+ )} +
+
+ ); +} + +function NoPredictiveSearchResults({ + searchTerm, +}: { + searchTerm: React.MutableRefObject; +}) { + if (!searchTerm.current) { + return null; + } + return ( +
+

NO RESULTS

+

+ No results found for {searchTerm.current} +

+
+ ); +}