Skip to content

Commit

Permalink
Merge pull request #32 from thomasKn/thomas/fv-237-enhance-motion
Browse files Browse the repository at this point in the history
Update cart motion
  • Loading branch information
thomasKn authored Feb 4, 2024
2 parents fef7a99 + 8528d22 commit 8b86442
Show file tree
Hide file tree
Showing 12 changed files with 190 additions and 169 deletions.
13 changes: 4 additions & 9 deletions app/components/Animation.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type {HTMLMotionProps} from 'framer-motion';

import {LazyMotion, m} from 'framer-motion';
import {m} from 'framer-motion';

export function Animation(
props: HTMLMotionProps<'div'> & {
Expand All @@ -9,15 +9,10 @@ export function Animation(
enabled?: boolean | null;
},
) {
const loadFeatures = async () =>
await import('../lib/framerMotionFeatures').then((res) => res.default);

return props.enabled ? (
<LazyMotion features={loadFeatures} strict>
<m.div className={props.className} {...props}>
{props.children}
</m.div>
</LazyMotion>
<m.div className={props.className} {...props}>
{props.children}
</m.div>
) : (
<div className={props.className}>{props.children}</div>
);
Expand Down
2 changes: 1 addition & 1 deletion app/components/QuantitySelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function Button(
'size-10 transition hover:bg-muted [&>*]:pointer-events-none',
variant === 'decrease' && 'disabled:opacity-30',
])}
data-vaul-no-drag
data-vaul-no-drag={true}
name={cx([
variant === 'decrease' && 'decrease-quantity',
variant === 'increase' && 'increase-quantity',
Expand Down
2 changes: 1 addition & 1 deletion app/components/cart/CartDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ function CartCheckoutActions({checkoutUrl}: {checkoutUrl: string}) {
return (
<div className="mt-2 flex flex-col">
<Button asChild>
<a data-vaul-no-drag href={checkoutUrl} target="_self">
<a data-vaul-no-drag={true} href={checkoutUrl} target="_self">
{/* Todo => add theme content string */}
Continue to Checkout
</a>
Expand Down
4 changes: 2 additions & 2 deletions app/components/cart/CartDiscounts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ export function CartDiscounts({
<div className={cx('flex', 'items-center justify-between gap-4')}>
{/* Todo => add theme content string */}
<Input
data-vaul-no-drag
data-vaul-no-drag={true}
name="discountCode"
placeholder="Discount code"
type="text"
/>
<Button data-vaul-no-drag variant="outline">
<Button data-vaul-no-drag={true} variant="outline">
{/* Todo => add theme content string */}
Apply Discount
</Button>
Expand Down
125 changes: 63 additions & 62 deletions app/components/cart/CartLineItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
parseGid,
useOptimisticData,
} from '@shopify/hydrogen';
import {LazyMotion, m} from 'framer-motion';
import {m} from 'framer-motion';

import {useLocalePath} from '~/hooks/useLocalePath';

Expand Down Expand Up @@ -44,9 +44,6 @@ export function CartLineItem({
if (!line?.id) return null;
if (typeof quantity === 'undefined' || !merchandise?.product) return null;

const loadFeatures = async () =>
await import('../../lib/framerMotionFeatures').then((res) => res.default);

const variants = {
hidden: {
height: 0,
Expand All @@ -68,75 +65,79 @@ export function CartLineItem({
marginTop: '1.25rem',
opacity: 1,
transition: {
bounce: 0.3,
bounce: 0.1,
type: 'spring',
},
},
};

return (
<LazyMotion features={loadFeatures} strict>
<m.li
animate={
// Hide the line item if the optimistic data action is remove
// Do not remove the form from the DOM
optimisticData?.action === 'remove' ? 'hidden' : 'visible'
}
initial={{height: 0, marginBottom: 0, marginTop: 0, opacity: 0}}
key={id}
variants={variants}
>
<div className="flex gap-4">
<div className="flex-shrink">
{merchandise.image && (
<Image
alt={merchandise.title}
aspectRatio="1/1"
className="size-24 rounded border border-border object-cover object-center"
data={merchandise.image}
loading="eager"
sizes="96px"
/>
)}
</div>
<m.li
animate={
// Hide the line item if the optimistic data action is remove
// Do not remove the form from the DOM
optimisticData?.action === 'remove' ? 'hidden' : 'visible'
}
initial={{height: 'auto', marginBottom: 0, marginTop: 0, opacity: 0}}
key={id}
variants={variants}
>
<div className="flex gap-4">
<div className="size-16">
{merchandise.image && (
<Image
alt={merchandise.title}
aspectRatio="1/1"
className="h-auto w-full rounded border border-border object-cover object-center"
data={merchandise.image}
data-vaul-no-drag={true}
draggable={false}
loading="eager"
sizes="64px"
/>
)}
</div>

<div className="flex flex-grow justify-between">
<div className="grid gap-2">
<h3 className="text-2xl">
{merchandise?.product?.handle ? (
<Link onClick={onClose} to={productPath}>
{merchandise?.product?.title || ''}
</Link>
) : (
<p>{merchandise?.product?.title || ''}</p>
)}
</h3>
{merchandise?.selectedOptions.find(
(option) => option.value !== 'Default Title',
) && (
<div className="grid pb-2">
{(merchandise?.selectedOptions || []).map((option) => (
<span className="opacity-80" key={option.name}>
{option.name}: {option.value}
</span>
))}
</div>
<div className="flex flex-grow justify-between">
<div className="grid gap-2">
<h3 className="text-2xl" data-vaul-no-drag={true}>
{merchandise?.product?.handle ? (
<Link
data-vaul-no-drag={true}
onClick={onClose}
to={productPath}
>
{merchandise?.product?.title || ''}
</Link>
) : (
<p>{merchandise?.product?.title || ''}</p>
)}
</h3>
{merchandise?.selectedOptions.find(
(option) => option.value !== 'Default Title',
) && (
<div className="grid pb-2">
{(merchandise?.selectedOptions || []).map((option) => (
<span className="opacity-80" key={option.name}>
{option.name}: {option.value}
</span>
))}
</div>
)}

<div className="flex items-center gap-2">
<div className="flex justify-start">
<CartLineQuantityAdjust line={line} />
</div>
<ItemRemoveButton lineId={id} />
<div className="flex items-center gap-2">
<div className="flex justify-start">
<CartLineQuantityAdjust line={line} />
</div>
<ItemRemoveButton lineId={id} />
</div>
<span>
<CartLinePrice as="span" line={line} />
</span>
</div>
<span>
<CartLinePrice as="span" line={line} />
</span>
</div>
</m.li>
</LazyMotion>
</div>
</m.li>
);
}

Expand All @@ -152,8 +153,8 @@ function ItemRemoveButton({lineId}: {lineId: CartLine['id']}) {
route={cartPath}
>
<button
className="flex size-10 items-center justify-center overflow-hidden rounded border border-border hover:bg-muted [&>*]:pointer-events-none"
data-vaul-no-drag
className="flex size-10 items-center justify-center overflow-hidden rounded border border-border hover:bg-muted"
data-vaul-no-drag={true}
type="submit"
>
{/* Todo => add theme content string */}
Expand Down
12 changes: 12 additions & 0 deletions app/components/layout/FramerMotion.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import {LazyMotion} from 'framer-motion';

export function FramerMotion(props: {children: React.ReactNode}) {
const loadFeatures = async () =>
await import('../../lib/framerMotionFeatures').then((res) => res.default);

return (
<LazyMotion features={loadFeatures} strict>
{props.children}
</LazyMotion>
);
}
52 changes: 26 additions & 26 deletions app/components/layout/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import type {CSSProperties} from 'react';
import {Link} from '@remix-run/react';
import {vercelStegaCleanAll} from '@sanity/client/stega';
import {cx} from 'class-variance-authority';
import {LazyMotion, m} from 'framer-motion';
import {m, useTransform} from 'framer-motion';
import React from 'react';

import {useBoundedScroll} from '~/hooks/useBoundedScroll';
import {useLocalePath} from '~/hooks/useLocalePath';
import {useSanityRoot} from '~/hooks/useSanityRoot';
import {useScrollDirection} from '~/hooks/useScrollDirection';
import {useSettingsCssVars} from '~/hooks/useSettingsCssVars';
import {cn} from '~/lib/utils';

Expand Down Expand Up @@ -66,7 +66,7 @@ function HeaderWrapper(props: {children: React.ReactNode}) {

const headerClassName = cx([
'section-padding bg-background text-foreground',
sticky === 'always' && 'sticky top-0 z-50',
sticky !== 'none' && 'sticky top-0 z-50',
blur &&
'bg-opacity-95 backdrop-blur supports-[backdrop-filter]:bg-opacity-85',
headerVariants({
Expand All @@ -87,30 +87,30 @@ function HeaderAnimation(props: {
children: React.ReactNode;
className: string;
}) {
const loadFeatures = async () =>
await import('../../lib/framerMotionFeatures').then((res) => res.default);
const {direction} = useScrollDirection();
const {scrollYBoundedProgress} = useBoundedScroll(400);
const scrollYBoundedProgressDelayed = useTransform(
scrollYBoundedProgress,
[0, 0.75, 1],
[0, 0, 1],
);

// Todo => Remove framer motion and use Top + Bottom position
return (
<LazyMotion features={loadFeatures} strict>
<m.header
animate={{
opacity: direction === 'up' || !direction ? 1 : 0,
y: direction === 'up' || !direction ? 0 : '-100%',
}}
className={cn([
props.className,
direction === 'up' && 'sticky top-0 z-50',
])}
data-direction={direction}
transition={{
duration: 0.1,
ease: 'linear',
}}
>
{props.children}
</m.header>
</LazyMotion>
<m.header
className={cn(props.className)}
style={{
opacity: useTransform(
scrollYBoundedProgressDelayed,
[0, 0.4, 1],
[1, 0, 0],
),
transform: useTransform(
scrollYBoundedProgressDelayed,
[0, 1],
['translateY(0)', 'translateY(-100%)'],
),
}}
>
{props.children}
</m.header>
);
}
27 changes: 15 additions & 12 deletions app/components/layout/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {TailwindIndicator} from '../TailwindIndicator';
import {TogglePreviewMode} from '../sanity/TogglePreviewMode';
import {AnnouncementBar} from './AnnoucementBar';
import {Footer} from './Footer';
import {FramerMotion} from './FramerMotion';
import {Header} from './Header';

const VisualEditing = lazy(() =>
Expand All @@ -34,18 +35,20 @@ export function Layout({children = null}: LayoutProps) {
storefrontApiVersion={env?.PUBLIC_STOREFRONT_API_VERSION!}
storefrontToken={env?.PUBLIC_STOREFRONT_API_TOKEN!}
>
<AnnouncementBar />
<Header />
<main>{children}</main>
<Footer />
<TailwindIndicator />
{previewMode ? (
<Suspense>
<VisualEditing />
</Suspense>
) : (
<TogglePreviewMode />
)}
<FramerMotion>
<AnnouncementBar />
<Header />
<main>{children}</main>
<Footer />
<TailwindIndicator />
{previewMode ? (
<Suspense>
<VisualEditing />
</Suspense>
) : (
<TogglePreviewMode />
)}
</FramerMotion>
</ShopifyProvider>
);
}
Loading

0 comments on commit 8b86442

Please sign in to comment.