diff --git a/app/components/Cart.tsx b/app/components/Cart.tsx index d1480a1..cbbcdb8 100644 --- a/app/components/Cart.tsx +++ b/app/components/Cart.tsx @@ -9,7 +9,7 @@ import {Input} from '@/components/input'; import {cn} from '@/lib/utils'; import clsx from "clsx"; -type CartLine = CartApiQueryFragment['lines']['nodes'][0]; +type CartLine = CartApiQueryFragment['lines']['edges'][0]['node']; type CartMainProps = { cart: CartApiQueryFragment | null; @@ -17,7 +17,7 @@ type CartMainProps = { }; export function CartMain({layout, cart}: CartMainProps) { - const linesCount = Boolean(cart?.lines?.nodes?.length || 0); + const linesCount = Boolean(cart?.lines?.edges?.length || 0); const withDiscount = cart && Boolean(cart.discountCodes.filter((code) => code.applicable).length); @@ -40,6 +40,7 @@ function CartDetails({layout, cart}: CartMainProps) { aside: 'cart-details flex flex-col gap-6 relative justify-between h-screen-in-drawer', }; + if (!cart) return null; return (
@@ -84,7 +85,7 @@ function CartLines({ )} - {lines.nodes.map((line) => ( + {lines?.edges?.map(({node: line}) => ( ))} diff --git a/app/components/Footer.tsx b/app/components/Footer.tsx index a513ded..72bf779 100644 --- a/app/components/Footer.tsx +++ b/app/components/Footer.tsx @@ -61,7 +61,7 @@ export function Footer({footerMenu}: FooterProps) {
{footerMenu && } -
+

{footerTextCopyright}

diff --git a/app/components/Header/AnnouncementBar.tsx b/app/components/Header/AnnouncementBar.tsx index fb0d84c..1e7de45 100644 --- a/app/components/Header/AnnouncementBar.tsx +++ b/app/components/Header/AnnouncementBar.tsx @@ -1,9 +1,12 @@ import {useThemeSettings} from '@weaverse/hydrogen'; import clsx from 'clsx'; -import {CSSProperties, useState} from 'react'; +import {CSSProperties, useEffect, useRef, useState} from 'react'; export function AnnouncementBar() { const [isVisible, setIsVisible] = useState(true); + const [shouldScroll, setShouldScroll] = useState(false); + const contentRef = useRef(null); + const containerRef = useRef(null); const settings = useThemeSettings(); let { content, @@ -30,10 +33,30 @@ export function AnnouncementBar() { setIsVisible(false); }; + useEffect(() => { + const checkScrollCondition = () => { + if (contentRef.current && containerRef.current) { + const contentWidth = contentRef.current.scrollWidth; + const containerWidth = containerRef.current.clientWidth; + if (contentWidth > containerWidth || enableScrollingText) { + setShouldScroll(true); + } else { + setShouldScroll(false); + } + } + }; + setTimeout(checkScrollCondition, 0); + window.addEventListener('resize', checkScrollCondition); + return () => { + window.removeEventListener('resize', checkScrollCondition); + }; + }, [content, enableScrollingText]); + if (!isVisible) return null; return (
× - {enableScrollingText && ( + {shouldScroll && ( <>
+
    + {Array.from({length: 15}).map((_, i) => ( +
  • + {content} +
  • + ))} +
)} - {!enableScrollingText && ( -
{content}
- )} - {enableScrollingText && ( -
    - {Array.from({length: 15}).map((_, i) => ( -
  • - {content} -
  • - ))} -
- )} +
+
+ {content} +
+
); } diff --git a/app/components/Header/Header.tsx b/app/components/Header/Header.tsx index 0888df4..a692871 100644 --- a/app/components/Header/Header.tsx +++ b/app/components/Header/Header.tsx @@ -4,9 +4,9 @@ import {UseMenuMegaHeader} from './MenuMegaHeader'; import type {LayoutProps} from '../Layout'; import { AnnouncementBar } from './AnnouncementBar'; -type HeaderProps = Pick; +type HeaderProps = Pick; -export function Header({headerMenu, isLoggedIn, cart}: HeaderProps) { +export function Header({headerMenu, cart}: HeaderProps) { let settings = useThemeSettings(); let typeMenu = settings?.typeMenuHeader; let enableTrialShipping = settings?.enableTrialShipping; @@ -16,7 +16,6 @@ export function Header({headerMenu, isLoggedIn, cart}: HeaderProps) { {typeMenu === 'mega' && ( @@ -24,13 +23,11 @@ export function Header({headerMenu, isLoggedIn, cart}: HeaderProps) { {typeMenu === 'drawer' ? ( ) : ( diff --git a/app/components/Header/MenuDrawerHeader.tsx b/app/components/Header/MenuDrawerHeader.tsx index 44f9b56..f4425ef 100644 --- a/app/components/Header/MenuDrawerHeader.tsx +++ b/app/components/Header/MenuDrawerHeader.tsx @@ -20,12 +20,10 @@ import {SearchToggle} from './SearchToggle'; export function UseMenuDrawerHeader({ header, - isLoggedIn, cart, className, }: { header: EnhancedMenu | null | undefined; - isLoggedIn: Promise; cart: Promise; className?: string; }) { diff --git a/app/components/Header/MenuMegaHeader.tsx b/app/components/Header/MenuMegaHeader.tsx index af41c9c..3921bba 100644 --- a/app/components/Header/MenuMegaHeader.tsx +++ b/app/components/Header/MenuMegaHeader.tsx @@ -20,12 +20,10 @@ import {SearchToggle} from './SearchToggle'; export function UseMenuMegaHeader({ header, - isLoggedIn, cart, className, }: { header: EnhancedMenu | null | undefined; - isLoggedIn: Promise; cart: Promise; className?: string; }) { diff --git a/app/components/Layout.tsx b/app/components/Layout.tsx index 5c8ef2a..f25ced1 100644 --- a/app/components/Layout.tsx +++ b/app/components/Layout.tsx @@ -12,7 +12,6 @@ export type LayoutProps = { children?: React.ReactNode; footerMenu: EnhancedMenu | undefined | null; headerMenu: EnhancedMenu | undefined | null; - isLoggedIn: Promise; }; export function Layout({ @@ -20,7 +19,6 @@ export function Layout({ children = null, footerMenu, headerMenu, - isLoggedIn, }: LayoutProps) { return ( @@ -28,7 +26,7 @@ export function Layout({ {/* */} {/* */} {/* */} - {headerMenu &&
} + {headerMenu &&
}
{children}
diff --git a/app/components/ProductCard.tsx b/app/components/ProductCard.tsx index e197c6d..9c5a521 100644 --- a/app/components/ProductCard.tsx +++ b/app/components/ProductCard.tsx @@ -73,7 +73,7 @@ export function ProductCard({ return (
-
+
{image && ( +
-
+
-
-
- - - - - + +
+
+ +
+
+

{errorStatus}

+ {errorMessage && ( + + {errorMessage} + + )} + +
+
+
); } -export let ErrorBoundary = withWeaverse(ErrorBoundaryComponent); const MENU_FRAGMENT = `#graphql fragment MenuItem on MenuItem { diff --git a/app/sections/blogs/index.tsx b/app/sections/blogs/index.tsx index ff3ecc9..cf057fa 100644 --- a/app/sections/blogs/index.tsx +++ b/app/sections/blogs/index.tsx @@ -1,3 +1,4 @@ +import {cn} from '@/lib/utils'; import {Image} from '@shopify/hydrogen'; import type { ComponentLoaderArgs, @@ -8,18 +9,85 @@ import type { import {IconImageBlank} from '~/components/Icon'; import {Link} from '~/components/Link'; import {BLOG_QUERY} from '~/data/queries'; +import {cva, VariantProps} from 'class-variance-authority'; import clsx from 'clsx'; import {CSSProperties, forwardRef} from 'react'; +let fontSizeVariants = cva('', { + variants: { + mobileSize: { + xs: 'text-xs', + sm: 'text-sm', + base: 'text-base', + lg: 'text-lg', + xl: 'text-xl', + '2xl': 'text-2xl', + '3xl': 'text-3xl', + '4xl': 'text-4xl', + '5xl': 'text-5xl', + '6xl': 'text-6xl', + '7xl': 'text-7xl', + '8xl': 'text-8xl', + '9xl': 'text-9xl', + }, + desktopSize: { + xs: 'md:text-xs', + sm: 'md:text-sm', + base: 'md:text-base', + lg: 'md:text-lg', + xl: 'md:text-xl', + '2xl': 'md:text-2xl', + '3xl': 'md:text-3xl', + '4xl': 'md:text-4xl', + '5xl': 'md:text-5xl', + '6xl': 'md:text-6xl', + '7xl': 'md:text-7xl', + '8xl': 'md:text-8xl', + '9xl': 'md:text-9xl', + }, + }, +}); + +let variants = cva('heading', { + variants: { + size: { + default: '', + custom: '', + scale: 'text-scale', + }, + weight: { + '100': 'font-thin', + '200': 'font-extralight', + '300': 'font-light', + '400': 'font-normal', + '500': 'font-medium', + '600': 'font-semibold', + '700': 'font-bold', + '800': 'font-extrabold', + '900': 'font-black', + }, + }, + defaultVariants: { + size: 'default', + weight: '400', + }, +}); + type BlogData = { blogs: WeaverseBlog; backgroundColor: string; articlePerRow: number; showSeperator: boolean; + as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; + minSize?: number; + maxSize?: number; }; -type BlogProps = HydrogenComponentProps>> & - BlogData; +export interface BlogProps + extends HydrogenComponentProps>>, + BlogData, + VariantProps, + VariantProps {} let articlesPerRowClasses: {[item: number]: string} = { 1: 'sm:grid-cols-1', @@ -34,6 +102,13 @@ const Blogs = forwardRef((props, ref) => { backgroundColor, articlePerRow, showSeperator, + as: Tag = 'h4', + size, + mobileSize, + desktopSize, + weight, + minSize, + maxSize, loaderData, children, ...rest @@ -41,18 +116,22 @@ const Blogs = forwardRef((props, ref) => { let sectionStyle: CSSProperties = { '--background-color': backgroundColor, + '--min-size-px': `${minSize}px`, + '--min-size': minSize, + '--max-size': maxSize, } as CSSProperties; - const defaultArticles = Array.from({ length: 3 }).map((_, i) => ({ + const defaultArticles = Array.from({length: 3}).map((_, i) => ({ id: i, title: 'Trendy items for this Winter Fall 2025 season', - excerpt: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s.", + excerpt: + "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s.", image: null, handle: null, })); const res = loaderData?.blog?.articles.nodes ?? defaultArticles; - + return (
((props, ref) => {
)}
-

{idx.title}

+ + {idx.title} + {showSeperator && (
)} -

- {idx.excerpt} -

+

{idx.excerpt}

@@ -131,7 +216,7 @@ export const schema: HydrogenComponentSchema = { toolbar: ['general-settings', ['duplicate', 'delete']], inspector: [ { - group: 'Blogs', + group: 'Blog', inputs: [ { type: 'blog', @@ -163,6 +248,135 @@ export const schema: HydrogenComponentSchema = { }, ], }, + { + group: 'Heading title (optional)', + inputs: [ + { + type: 'select', + name: 'as', + label: 'HTML tag', + configs: { + options: [ + {value: 'h1', label: '

(Heading 1)'}, + {value: 'h2', label: '

(Heading 2)'}, + {value: 'h3', label: '

(Heading 3)'}, + {value: 'h4', label: '

(Heading 4)'}, + {value: 'h5', label: '

(Heading 5)'}, + {value: 'h6', label: '
(Heading 6)'}, + ], + }, + defaultValue: 'h4', + }, + { + type: 'select', + name: 'size', + label: 'Text size', + configs: { + options: [ + {value: 'default', label: 'Default'}, + {value: 'scale', label: 'Auto scale'}, + {value: 'custom', label: 'Custom'}, + ], + }, + defaultValue: 'default', + }, + { + type: 'range', + name: 'minSize', + label: 'Minimum scale size', + configs: { + min: 12, + max: 32, + step: 1, + unit: 'px', + }, + defaultValue: 16, + condition: 'size.eq.scale', + }, + { + type: 'range', + name: 'maxSize', + label: 'Maximum scale size', + configs: { + min: 40, + max: 96, + step: 1, + unit: 'px', + }, + defaultValue: 64, + condition: 'size.eq.scale', + helpText: + 'See how scale text works here.', + }, + { + type: 'select', + name: 'mobileSize', + label: 'Mobile text size', + condition: 'size.eq.custom', + configs: { + options: [ + {value: 'xs', label: 'Extra small (text-xs)'}, + {value: 'sm', label: 'Small (text-sm)'}, + {value: 'base', label: 'Base (text-base)'}, + {value: 'lg', label: 'Large (text-lg)'}, + {value: 'xl', label: 'Extra large (text-xl)'}, + {value: '2xl', label: '2x large (text-2xl)'}, + {value: '3xl', label: '3x large (text-3xl)'}, + {value: '4xl', label: '4x large (text-4xl)'}, + {value: '5xl', label: '5x large (text-5xl)'}, + {value: '6xl', label: '6x large (text-6xl)'}, + {value: '7xl', label: '7x large (text-7xl)'}, + {value: '8xl', label: '8x large (text-8xl)'}, + {value: '9xl', label: '9x large (text-9xl)'}, + ], + }, + defaultValue: '3xl', + }, + { + type: 'select', + name: 'desktopSize', + label: 'Desktop text size', + condition: 'size.eq.custom', + configs: { + options: [ + {value: 'xs', label: 'Extra small (text-xs)'}, + {value: 'sm', label: 'Small (text-sm)'}, + {value: 'base', label: 'Base (text-base)'}, + {value: 'lg', label: 'Large (text-lg)'}, + {value: 'xl', label: 'Extra large (text-xl)'}, + {value: '2xl', label: '2x large (text-2xl)'}, + {value: '3xl', label: '3x large (text-3xl)'}, + {value: '4xl', label: '4x large (text-4xl)'}, + {value: '5xl', label: '5x large (text-5xl)'}, + {value: '6xl', label: '6x large (text-6xl)'}, + {value: '7xl', label: '7x large (text-7xl)'}, + {value: '8xl', label: '8x large (text-8xl)'}, + {value: '9xl', label: '9x large (text-9xl)'}, + ], + }, + defaultValue: '5xl', + }, + { + type: 'select', + name: 'weight', + label: 'Weight', + configs: { + options: [ + {value: '100', label: '100 - Thin'}, + {value: '200', label: '200 - Extra Light'}, + {value: '300', label: '300 - Light'}, + {value: '400', label: '400 - Normal'}, + {value: '500', label: '500 - Medium'}, + {value: '600', label: '600 - Semi Bold'}, + {value: '700', label: '700 - Bold'}, + {value: '800', label: '800 - Extra Bold'}, + {value: '900', label: '900 - Black'}, + ], + }, + defaultValue: '400', + }, + ], + }, ], childTypes: ['heading'], presets: { diff --git a/app/sections/image-with-text/content.tsx b/app/sections/image-with-text/content.tsx index c6b8e18..0f7d083 100644 --- a/app/sections/image-with-text/content.tsx +++ b/app/sections/image-with-text/content.tsx @@ -33,7 +33,7 @@ let ImageWithTextContent = forwardRef< >((props, ref) => { let {alignment, children, ...rest} = props; return ( -
+
{children}
); diff --git a/app/sections/image-with-text/image.tsx b/app/sections/image-with-text/image.tsx index 6b31fcd..b6049ae 100644 --- a/app/sections/image-with-text/image.tsx +++ b/app/sections/image-with-text/image.tsx @@ -10,7 +10,7 @@ import type {VariantProps} from 'class-variance-authority'; import {cva} from 'class-variance-authority'; import {forwardRef} from 'react'; -let variants = cva('w-full h-auto', { +let variants = cva('w-full h-auto flex-1', { variants: { width: { small: 'md:w-[40%]', diff --git a/app/sections/testimonials/index.tsx b/app/sections/testimonials/index.tsx index cb95adc..03862b4 100644 --- a/app/sections/testimonials/index.tsx +++ b/app/sections/testimonials/index.tsx @@ -44,7 +44,7 @@ const Testimonials = forwardRef((
@@ -92,7 +92,7 @@ export let schema: HydrogenComponentSchema = { inputs: layoutInputs.filter(({ name }) => name !== 'divider' && name !== 'borderRadius' && name !== 'gap'), }, { - group: 'testimonials', + group: 'Testimonials', inputs: [ { type: 'image', diff --git a/app/weaverse/style.tsx b/app/weaverse/style.tsx index 5f7d57b..1b6acfb 100644 --- a/app/weaverse/style.tsx +++ b/app/weaverse/style.tsx @@ -128,7 +128,7 @@ export function GlobalStyle() { body, button, input, select, textarea { -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: 100%; - font-size: calc(var(--body-base-size) * 0.92); + font-size: var(--body-base-size); letter-spacing: var(--body-base-spacing); line-height: var(--body-base-line-height); text-rendering: optimizeSpeed; diff --git a/storefrontapi.generated.d.ts b/storefrontapi.generated.d.ts index e9a84f7..73cbdc7 100644 --- a/storefrontapi.generated.d.ts +++ b/storefrontapi.generated.d.ts @@ -839,8 +839,8 @@ export type CartApiQueryFragment = Pick< >; }; lines: { - nodes: Array< - Pick & { + edges: Array<{ + node: Pick & { attributes: Array>; cost: { totalAmount: Pick; @@ -871,8 +871,8 @@ export type CartApiQueryFragment = Pick< Pick >; }; - } - >; + }; + }>; }; cost: { subtotalAmount: Pick; diff --git a/tailwind.config.js b/tailwind.config.js index 4e21db4..2a8b675 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -12,9 +12,28 @@ module.exports = { }, }, fontFamily: { - body: ["Open Sans Variable", "ui-sans-serif", "system-ui", "sans-serif"], + body: ["Nunito Sans Variable", "ui-sans-serif", "system-ui", "sans-serif"], heading: ["Cormorant Variable", "ui-serif", "Georgia", "Cambria", "Times New Roman", "Times", "serif"], }, + fontSize: { + scale: [ + "calc(var(--min-size-px) + (var(--max-size) - var(--min-size)) * ((100vw - var(--wv-min-viewport-size, 320) * 1px) / (var(--wv-max-viewport-size, 1920) - var(--wv-min-viewport-size, 320))))", + 1, + ], + xs: ["calc(var(--body-base-size) * 0.75)", 1], + sm: ["calc(var(--body-base-size) * 0.875)", 1.25], + base: ["var(--body-base-size)", "var(--body-base-line-height)"], + lg: ["calc(var(--body-base-size) * 1.125)", 1.75], + xl: ["calc(var(--body-base-size) * 1.25)", 1.75], + "2xl": ["calc(var(--body-base-size) * 1.5)", 2], + "3xl": ["calc(var(--body-base-size) * 1.875)", 2.25], + "4xl": ["calc(var(--body-base-size) * 2.25)", 2.5], + "5xl": ["calc(var(--body-base-size) * 3)", 1], + "6xl": ["calc(var(--body-base-size) * 3.75)", 1], + "7xl": ["calc(var(--body-base-size) * 4.5)", 1], + "8xl": ["calc(var(--body-base-size) * 6)", 1], + "9xl": ["calc(var(--body-base-size) * 8)", 1], + }, extend: { colors: { background: {