diff --git a/app/components/Drawer.tsx b/app/components/Drawer.tsx index e6288ca..60fde8c 100644 --- a/app/components/Drawer.tsx +++ b/app/components/Drawer.tsx @@ -83,7 +83,7 @@ export function Drawer({
- - {heading} - + {heading} )}
diff --git a/app/components/Footer.tsx b/app/components/Footer.tsx index 72bf779..aef904a 100644 --- a/app/components/Footer.tsx +++ b/app/components/Footer.tsx @@ -103,7 +103,7 @@ function MenuLink(props: SingleMenuItem) { <>

- {title} + {title}

    {items.map((subItem, ind) => ( @@ -160,101 +160,5 @@ function MenuLink(props: SingleMenuItem) { } function HeaderText({title, to}: {title: string; to: string}) { - return

    {title}

    ; -} - -// function FooterMenu({ -// menu, -// primaryDomainUrl, -// }: { -// menu: FooterQuery['menu']; -// primaryDomainUrl: FooterQuery['shop']['primaryDomain']['url']; -// }) { -// const {publicStoreDomain} = useRootLoaderData(); - -// return ( -// -// ); -// } - -const FALLBACK_FOOTER_MENU = { - id: 'gid://shopify/Menu/199655620664', - items: [ - { - id: 'gid://shopify/MenuItem/461633060920', - resourceId: 'gid://shopify/ShopPolicy/23358046264', - tags: [], - title: 'Privacy Policy', - type: 'SHOP_POLICY', - url: '/policies/privacy-policy', - items: [], - }, - { - id: 'gid://shopify/MenuItem/461633093688', - resourceId: 'gid://shopify/ShopPolicy/23358013496', - tags: [], - title: 'Refund Policy', - type: 'SHOP_POLICY', - url: '/policies/refund-policy', - items: [], - }, - { - id: 'gid://shopify/MenuItem/461633126456', - resourceId: 'gid://shopify/ShopPolicy/23358111800', - tags: [], - title: 'Shipping Policy', - type: 'SHOP_POLICY', - url: '/policies/shipping-policy', - items: [], - }, - { - id: 'gid://shopify/MenuItem/461633159224', - resourceId: 'gid://shopify/ShopPolicy/23358079032', - tags: [], - title: 'Terms of Service', - type: 'SHOP_POLICY', - url: '/policies/terms-of-service', - items: [], - }, - ], -}; - -function activeLinkStyle({ - isActive, - isPending, -}: { - isActive: boolean; - isPending: boolean; -}) { - return { - fontWeight: isActive ? 'bold' : undefined, - color: isPending ? 'grey' : 'white', - }; + return

    {title}

    ; } diff --git a/app/components/Header/MenuDrawerHeader.tsx b/app/components/Header/MenuDrawerHeader.tsx index f4425ef..82de667 100644 --- a/app/components/Header/MenuDrawerHeader.tsx +++ b/app/components/Header/MenuDrawerHeader.tsx @@ -11,7 +11,7 @@ import {CartApiQueryFragment} from 'storefrontapi.generated'; import {CartMain} from '../Cart'; import {CartLoading} from '../CartLoading'; import {Drawer, useDrawer} from '../Drawer'; -import {IconAccount, IconLogin} from '../Icon'; +import {IconAccount, IconListMenu, IconLogin} from '../Icon'; import {Link} from '../Link'; import {Logo} from '../Logo'; import {CartCount} from './CartCount'; @@ -115,23 +115,15 @@ function HeaderMenuDrawer({menu}: {menu?: EnhancedMenu | null | undefined}) { role="navigation" > - {/* */} diff --git a/app/components/Header/SearchToggle.tsx b/app/components/Header/SearchToggle.tsx index e529ac2..fb518af 100644 --- a/app/components/Header/SearchToggle.tsx +++ b/app/components/Header/SearchToggle.tsx @@ -47,7 +47,7 @@ export function SearchToggle({isOpenDrawerHearder}: {isOpenDrawerHearder?: boole open={isOpen} onClose={closeDrawer} openFrom={openFrom} - heading="Search" + heading={settings?.searchType === 'drawerSearch' ? 'Search' : ''} isForm="search" > {searchType === 'popupSearch' && } diff --git a/app/components/Icon.tsx b/app/components/Icon.tsx index fccee71..110dba4 100644 --- a/app/components/Icon.tsx +++ b/app/components/Icon.tsx @@ -606,7 +606,7 @@ export function IconTag(props: IconProps) { export function IconListMenu(props: IconProps){ return( - + ); } diff --git a/app/components/global-loading.tsx b/app/components/global-loading.tsx new file mode 100644 index 0000000..80f2d4c --- /dev/null +++ b/app/components/global-loading.tsx @@ -0,0 +1,47 @@ +import { useNavigation } from "@remix-run/react"; +import clsx from "clsx"; +import { useEffect, useRef, useState } from "react"; + +export function GlobalLoading() { + let transition = useNavigation(); + let active = transition.state !== "idle"; + + let ref = useRef(null); + let [animating, setAnimating] = useState(false); + + useEffect(() => { + if (!ref.current) return; + + Promise.allSettled( + ref.current.getAnimations().map(({ finished }) => finished), + ).then(() => { + if (!active) setAnimating(false); + }); + + if (active) { + let id = setTimeout(() => setAnimating(true), 100); + return () => clearTimeout(id); + } + }, [active]); + + return ( +
    + role="progressbar" + aria-hidden={!active} + aria-valuetext={active ? "Loading" : undefined} + className="fixed inset-x-0 left-0 top-0 z-50 h-1 animate-pulse" + > +
    +
    + ); +} diff --git a/app/components/predictive-search/PredictiveSearch/SearchDrawer/SearchTypeDrawerResults.tsx b/app/components/predictive-search/PredictiveSearch/SearchDrawer/SearchTypeDrawerResults.tsx index 68e0d25..383bb32 100644 --- a/app/components/predictive-search/PredictiveSearch/SearchDrawer/SearchTypeDrawerResults.tsx +++ b/app/components/predictive-search/PredictiveSearch/SearchDrawer/SearchTypeDrawerResults.tsx @@ -83,12 +83,13 @@ export function SearchTypeDrawerResults() { />
    )} -
    +
    {searchTerm.current && (

    Show All Results ({totalResultsCount}) diff --git a/app/components/product-form/product-media.tsx b/app/components/product-form/product-media.tsx index c82243a..aa63212 100644 --- a/app/components/product-form/product-media.tsx +++ b/app/components/product-form/product-media.tsx @@ -1,12 +1,9 @@ import { Image } from "@shopify/hydrogen"; import clsx from "clsx"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import type { MediaFragment } from "storefrontapi.generated"; import { FreeMode, Pagination, Thumbs } from "swiper/modules"; import { Swiper, type SwiperClass, SwiperSlide } from "swiper/react"; -import 'swiper/css/free-mode'; -import 'swiper/css/navigation'; -import 'swiper/css/thumbs'; interface ProductMediaProps { selectedVariant: any; @@ -21,43 +18,23 @@ export function ProductMedia(props: ProductMediaProps) { let media = _media.filter((med) => med.__typename === "MediaImage"); let [thumbsSwiper, setThumbsSwiper] = useState(null); let [activeIndex, setActiveIndex] = useState(0); + console.log("🚀 ~ thumbsSwiper:", thumbsSwiper) + + useEffect(() => { + if (thumbsSwiper) { + thumbsSwiper.slideTo(activeIndex); + } + }, [thumbsSwiper]); return ( -

    - - {media.map((med, i) => { - let image = { ...med.image, altText: med.alt || "Product image" }; - return ( - - - - ); - })} - +
    { + setActiveIndex(swiper.activeIndex); + }} thumbs={ thumbsSwiper ? { @@ -66,9 +43,6 @@ export function ProductMedia(props: ProductMediaProps) { } : undefined } - onSlideChange={(swiper) => { - setActiveIndex(swiper.activeIndex); - }} className="vt-product-image max-w-full pb-14 md:pb-0 md:[&_.swiper-pagination-fraction]:hidden" style={ { @@ -91,6 +65,36 @@ export function ProductMedia(props: ProductMediaProps) { ); })} + + {media.map((med, i) => { + let image = { ...med.image, altText: med.alt || "Product image" }; + return ( + + + + ); + })} +
    ); } diff --git a/app/root.tsx b/app/root.tsx index b8a95f3..80d94ad 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -34,6 +34,7 @@ import {CustomAnalytics} from '~/components/Analytics'; import {seoPayload} from '~/lib/seo.server'; import {getErrorMessage} from './lib/defineMessageError'; import {parseMenu} from './lib/utils'; +import { GlobalLoading } from './components/global-loading'; /** * This is important to avoid re-fetching root queries on sub-navigations @@ -171,6 +172,7 @@ function IndexLayout({children}: {children?: React.ReactNode}) { ) : ( children )} + diff --git a/app/sections/all-products/index.tsx b/app/sections/all-products/index.tsx index ab8feae..06a6a67 100644 --- a/app/sections/all-products/index.tsx +++ b/app/sections/all-products/index.tsx @@ -1,89 +1,69 @@ +import {Button} from '@/components/button'; import {useLoaderData} from '@remix-run/react'; import {Pagination} from '@shopify/hydrogen'; import type { HydrogenComponentProps, HydrogenComponentSchema, } from '@weaverse/hydrogen'; -import {Children, forwardRef} from 'react'; -import type {AllProductsQuery} from 'storefrontapi.generated'; -import { Section} from '~/components/Text'; -import {ProductCard} from '~/components/ProductCard'; import {Grid} from '~/components/Grid'; +import {ProductCard} from '~/components/ProductCard'; import {getImageLoadingPriority} from '~/lib/const'; -import { Button } from '@/components/button'; +import {Children, forwardRef} from 'react'; +import type {AllProductsQuery} from 'storefrontapi.generated'; +import {layoutInputs, Section, SectionProps} from '../atoms/Section'; interface AllProductsProps extends HydrogenComponentProps { heading: string; - prevPageText: string; - nextPageText: string; - paddingTop: number; - paddingBottom: number; } -let AllProducts = forwardRef((props, ref) => { - let { - heading, - prevPageText, - nextPageText, - paddingTop, - paddingBottom, - children, - ...rest - } = props; - let {products} = useLoaderData(); +let AllProducts = forwardRef( + (props, ref) => { + let {heading, children, ...rest} = props; + let {products} = useLoaderData(); - return ( -
    -
    - {!!Children.count(children) && ( -
    - {children} -
    - )} - - {({nodes, isLoading, NextLink, PreviousLink}) => { - let itemsMarkup = nodes.map((product, i) => ( - - )); + return ( +
    + {!!Children.count(children) && ( +
    {children}
    + )} + + {({nodes, isLoading, NextLink, PreviousLink}) => { + let itemsMarkup = nodes.map((product, i) => ( + + )); - return ( - <> -
    - -
    - {itemsMarkup} -
    - -
    - - ); - }} -
    -
    -
    - ); -}); + return ( + <> +
    + +
    + + {itemsMarkup} + +
    + +
    + + ); + }} + + + ); + }, +); export default AllProducts; @@ -98,55 +78,16 @@ export let schema: HydrogenComponentSchema = { inspector: [ { group: 'All products', - inputs: [ - { - type: 'text', - name: 'prevPageText', - label: 'Previous page text', - defaultValue: 'Previous', - placeholder: 'Previous', - }, - { - type: 'text', - name: 'nextPageText', - label: 'Next page text', - defaultValue: 'Next', - placeholder: 'Next', - }, - { - type: 'range', - label: 'Top padding', - name: 'paddingTop', - configs: { - min: 0, - max: 100, - step: 4, - unit: 'px', - }, - defaultValue: 32, - }, - { - type: 'range', - label: 'Bottom padding', - name: 'paddingBottom', - configs: { - min: 0, - max: 100, - step: 4, - unit: 'px', - }, - defaultValue: 32, - }, - ], + inputs: layoutInputs.filter(({ name }) => name !== 'borderRadius'), }, ], childTypes: ['heading'], - presets: { - children: [ - { - type: 'heading', - content: "All products", - }, - ], - }, + presets: { + children: [ + { + type: 'heading', + content: 'All products', + }, + ], + }, }; diff --git a/app/sections/blog-post/blog-post.tsx b/app/sections/blog-post/blog-post.tsx index 9f06d97..f16e6be 100644 --- a/app/sections/blog-post/blog-post.tsx +++ b/app/sections/blog-post/blog-post.tsx @@ -2,18 +2,15 @@ import {useLoaderData} from '@remix-run/react'; import {Image} from '@shopify/hydrogen'; import type {Article} from '@shopify/hydrogen/storefront-api-types'; import type { - HydrogenComponentProps, HydrogenComponentSchema, } from '@weaverse/hydrogen'; import {forwardRef} from 'react'; +import { layoutInputs, Section, SectionProps } from '../atoms/Section'; -interface BlogPostProps extends HydrogenComponentProps { - paddingTop: number; - paddingBottom: number; -} +type BlogPostProps = SectionProps; let BlogPost = forwardRef((props, ref) => { - let {paddingTop, paddingBottom, ...rest} = props; + let { ...rest} = props; let {article, formattedDate} = useLoaderData<{ article: Article; formattedDate: string; @@ -21,12 +18,8 @@ let BlogPost = forwardRef((props, ref) => { let {title, image, contentHtml, author, tags} = article; if (article) { return ( -
    +
    @@ -46,7 +39,7 @@ let BlogPost = forwardRef((props, ref) => {

    {formattedDate}

    -
    +
    ); } return
    ; @@ -65,32 +58,7 @@ export let schema: HydrogenComponentSchema = { inspector: [ { group: 'Blog post', - inputs: [ - { - type: 'range', - label: 'Top padding', - name: 'paddingTop', - configs: { - min: 0, - max: 100, - step: 4, - unit: 'px', - }, - defaultValue: 0, - }, - { - type: 'range', - label: 'Bottom padding', - name: 'paddingBottom', - configs: { - min: 0, - max: 100, - step: 4, - unit: 'px', - }, - defaultValue: 0, - }, - ], + inputs: layoutInputs.filter(({ name }) => name !== 'divider' && name !== 'borderRadius'), }, ], }; diff --git a/app/sections/blogs/index.tsx b/app/sections/blogs/index.tsx index cf057fa..e508a7f 100644 --- a/app/sections/blogs/index.tsx +++ b/app/sections/blogs/index.tsx @@ -77,6 +77,7 @@ type BlogData = { blogs: WeaverseBlog; backgroundColor: string; articlePerRow: number; + gapRow: number; showSeperator: boolean; as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; minSize?: number; @@ -101,6 +102,7 @@ const Blogs = forwardRef((props, ref) => { blogs, backgroundColor, articlePerRow, + gapRow, showSeperator, as: Tag = 'h4', size, @@ -119,6 +121,7 @@ const Blogs = forwardRef((props, ref) => { '--min-size-px': `${minSize}px`, '--min-size': minSize, '--max-size': maxSize, + '--gap-row': `${gapRow}px`, } as CSSProperties; const defaultArticles = Array.from({length: 3}).map((_, i) => ({ @@ -143,7 +146,7 @@ const Blogs = forwardRef((props, ref) => { {children}
    @@ -155,7 +158,7 @@ const Blogs = forwardRef((props, ref) => { >
    {idx.image ? ( {}; +let variants = cva("relative lg:pb-20 pb-12", { + variants: { + width: { + full: "w-full h-full", + stretch: "w-full h-full", + fixed: "w-full h-full max-w-[var(--page-width,1440px)] mx-auto", + }, + padding: { + full: "", + stretch: "px-3 md:px-10 lg:px-16", + fixed: "px-3 md:px-4 lg:px-6 mx-auto", + }, + gap: { + 0: "", + 4: "space-y-1", + 8: "space-y-2", + 12: "space-y-3", + 16: "space-y-4", + 20: "space-y-5", + 24: "space-y-3 lg:space-y-6", + 28: "space-y-3.5 lg:space-y-7", + 32: "space-y-4 lg:space-y-8", + 36: "space-y-4 lg:space-y-9", + 40: "space-y-5 lg:space-y-10", + 44: "space-y-5 lg:space-y-11", + 48: "space-y-6 lg:space-y-12", + 52: "space-y-6 lg:space-y-[52px]", + 56: "space-y-7 lg:space-y-14", + 60: "space-y-7 lg:space-y-[60px]", + }, + }, +}); let CollectionFilters = forwardRef( (props, sectionRef) => { - let {children, ...rest} = props; + let {width, gap, ...rest} = props; let {ref, inView} = useInView(); let {collection, collections, appliedFilters} = useLoaderData< CollectionDetailsQuery & { @@ -30,7 +63,7 @@ let CollectionFilters = forwardRef( if (collection?.products && collections) { return ( -
    +
    ( state, }) => ( <> -
    -
    ( hasNextPage={hasNextPage} state={state} /> -
    -
    )} -
    +
    ); } return
    ; @@ -88,9 +121,33 @@ export let schema: HydrogenComponentSchema = { inspector: [ { group: 'Collection filters', - inputs: layoutInputs.filter( - ({name}) => name !== 'divider' && name !== 'borderRadius', - ), + inputs: [ + { + type: "select", + name: "width", + label: "Content width", + configs: { + options: [ + { value: "full", label: "Full page" }, + { value: "stretch", label: "Stretch" }, + { value: "fixed", label: "Fixed" }, + ], + }, + defaultValue: "fixed", + }, + { + type: "range", + name: "gap", + label: "Items spacing", + configs: { + min: 0, + max: 60, + step: 4, + unit: "px", + }, + defaultValue: 20, + }, + ] }, ], }; diff --git a/app/sections/hightlight/item.tsx b/app/sections/hightlight/item.tsx index 5962ad1..a29d929 100644 --- a/app/sections/hightlight/item.tsx +++ b/app/sections/hightlight/item.tsx @@ -30,10 +30,10 @@ const HighlightItem = forwardRef( > {React.Children.map(children, (child, index) => ( <> -
    +
    {index === 0 && (
    - + {(parentInstance?._store?.children as { id: string }[])?.findIndex((c) => c.id === child?.props.parentId) + 1}
    diff --git a/app/sections/scrolling-text/index.tsx b/app/sections/scrolling-text/index.tsx index d70bfc8..2158b16 100644 --- a/app/sections/scrolling-text/index.tsx +++ b/app/sections/scrolling-text/index.tsx @@ -55,7 +55,8 @@ const ScrollingText = forwardRef((props, ref) => { !visibleOnMobile && 'hidden sm:block', )} > -
      +
      {content}
      +
        {Array.from({length: 50}).map((_, i) => (