forked from crowetic/commerce
Removes Framer Motion (#1055)
This commit is contained in:
parent
9678306b23
commit
8c8240956a
@ -22,10 +22,10 @@ type MerchandiseSearchParams = {
|
|||||||
|
|
||||||
export default function CartModal({ cart, cartIdUpdated }: { cart: Cart; cartIdUpdated: boolean }) {
|
export default function CartModal({ cart, cartIdUpdated }: { cart: Cart; cartIdUpdated: boolean }) {
|
||||||
const [, setCookie] = useCookies(['cartId']);
|
const [, setCookie] = useCookies(['cartId']);
|
||||||
const [cartIsOpen, setCartIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const quantityRef = useRef(cart.totalQuantity);
|
const quantityRef = useRef(cart.totalQuantity);
|
||||||
const openCart = () => setCartIsOpen(true);
|
const openCart = () => setIsOpen(true);
|
||||||
const closeCart = () => setCartIsOpen(false);
|
const closeCart = () => setIsOpen(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (cartIdUpdated) {
|
if (cartIdUpdated) {
|
||||||
@ -42,21 +42,21 @@ export default function CartModal({ cart, cartIdUpdated }: { cart: Cart; cartIdU
|
|||||||
// Open cart modal when when quantity changes.
|
// Open cart modal when when quantity changes.
|
||||||
if (cart.totalQuantity !== quantityRef.current) {
|
if (cart.totalQuantity !== quantityRef.current) {
|
||||||
// But only if it's not already open (quantity also changes when editing items in cart).
|
// But only if it's not already open (quantity also changes when editing items in cart).
|
||||||
if (!cartIsOpen) {
|
if (!isOpen) {
|
||||||
setCartIsOpen(true);
|
setIsOpen(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always update the quantity reference
|
// Always update the quantity reference
|
||||||
quantityRef.current = cart.totalQuantity;
|
quantityRef.current = cart.totalQuantity;
|
||||||
}
|
}
|
||||||
}, [cartIsOpen, cart.totalQuantity, quantityRef]);
|
}, [isOpen, cart.totalQuantity, quantityRef]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<button aria-label="Open cart" onClick={openCart} data-testid="open-cart">
|
<button aria-label="Open cart" onClick={openCart} data-testid="open-cart">
|
||||||
<CartIcon quantity={cart.totalQuantity} />
|
<CartIcon quantity={cart.totalQuantity} />
|
||||||
</button>
|
</button>
|
||||||
<Transition show={cartIsOpen}>
|
<Transition show={isOpen}>
|
||||||
<Dialog onClose={closeCart} className="relative z-50" data-testid="cart">
|
<Dialog onClose={closeCart} className="relative z-50" data-testid="cart">
|
||||||
<Transition.Child
|
<Transition.Child
|
||||||
as={Fragment}
|
as={Fragment}
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Dialog } from '@headlessui/react';
|
import { Dialog, Transition } from '@headlessui/react';
|
||||||
import { AnimatePresence, motion } from 'framer-motion';
|
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { usePathname, useSearchParams } from 'next/navigation';
|
import { usePathname, useSearchParams } from 'next/navigation';
|
||||||
import { useEffect, useState } from 'react';
|
import { Fragment, useEffect, useState } from 'react';
|
||||||
|
|
||||||
import CloseIcon from 'components/icons/close';
|
import CloseIcon from 'components/icons/close';
|
||||||
import MenuIcon from 'components/icons/menu';
|
import MenuIcon from 'components/icons/menu';
|
||||||
@ -14,73 +13,61 @@ import Search from './search';
|
|||||||
export default function MobileMenu({ menu }: { menu: Menu[] }) {
|
export default function MobileMenu({ menu }: { menu: Menu[] }) {
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const [mobileMenuIsOpen, setMobileMenuIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
const openMobileMenu = () => setIsOpen(true);
|
||||||
|
const closeMobileMenu = () => setIsOpen(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleResize = () => {
|
const handleResize = () => {
|
||||||
if (window.innerWidth > 768) {
|
if (window.innerWidth > 768) {
|
||||||
setMobileMenuIsOpen(false);
|
setIsOpen(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
window.addEventListener('resize', handleResize);
|
window.addEventListener('resize', handleResize);
|
||||||
return () => window.removeEventListener('resize', handleResize);
|
return () => window.removeEventListener('resize', handleResize);
|
||||||
}, [mobileMenuIsOpen]);
|
}, [isOpen]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setMobileMenuIsOpen(false);
|
setIsOpen(false);
|
||||||
}, [pathname, searchParams]);
|
}, [pathname, searchParams]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={openMobileMenu}
|
||||||
setMobileMenuIsOpen(!mobileMenuIsOpen);
|
|
||||||
}}
|
|
||||||
aria-label="Open mobile menu"
|
aria-label="Open mobile menu"
|
||||||
className="md:hidden"
|
className="md:hidden"
|
||||||
data-testid="open-mobile-menu"
|
data-testid="open-mobile-menu"
|
||||||
>
|
>
|
||||||
<MenuIcon className="h-6" />
|
<MenuIcon className="h-6" />
|
||||||
</button>
|
</button>
|
||||||
<AnimatePresence initial={false}>
|
<Transition show={isOpen}>
|
||||||
{mobileMenuIsOpen && (
|
<Dialog onClose={closeMobileMenu} className="relative z-50">
|
||||||
<Dialog
|
<Transition.Child
|
||||||
as={motion.div}
|
as={Fragment}
|
||||||
initial="closed"
|
enter="transition-all ease-in-out duration-300"
|
||||||
animate="open"
|
enterFrom="opacity-0 backdrop-blur-none"
|
||||||
exit="closed"
|
enterTo="opacity-100 backdrop-blur-[.5px]"
|
||||||
key="dialog"
|
leave="transition-all ease-in-out duration-200"
|
||||||
static
|
leaveFrom="opacity-100 backdrop-blur-[.5px]"
|
||||||
open={mobileMenuIsOpen}
|
leaveTo="opacity-0 backdrop-blur-none"
|
||||||
onClose={() => {
|
|
||||||
setMobileMenuIsOpen(false);
|
|
||||||
}}
|
|
||||||
className="relative z-50"
|
|
||||||
>
|
>
|
||||||
<motion.div
|
<div className="fixed inset-0 bg-black/30" aria-hidden="true" />
|
||||||
variants={{
|
</Transition.Child>
|
||||||
open: { opacity: 1, backdropFilter: 'blur(0.5px)' },
|
<Transition.Child
|
||||||
closed: { opacity: 0, backdropFilter: 'blur(0px)' }
|
as={Fragment}
|
||||||
}}
|
enter="transition-all ease-in-out duration-300"
|
||||||
className="fixed inset-0 bg-black/30"
|
enterFrom="translate-x-[-100%]"
|
||||||
aria-hidden="true"
|
enterTo="translate-x-0"
|
||||||
/>
|
leave="transition-all ease-in-out duration-200"
|
||||||
<div className="fixed inset-0 flex justify-end" data-testid="mobile-menu">
|
leaveFrom="translate-x-0"
|
||||||
<Dialog.Panel
|
leaveTo="translate-x-[-100%]"
|
||||||
as={motion.div}
|
|
||||||
variants={{
|
|
||||||
open: { translateX: 0 },
|
|
||||||
closed: { translateX: '-100%' }
|
|
||||||
}}
|
|
||||||
transition={{ type: 'spring', bounce: 0, duration: 0.3 }}
|
|
||||||
className="flex w-full flex-col bg-white pb-6 dark:bg-black"
|
|
||||||
>
|
>
|
||||||
|
<Dialog.Panel className="fixed bottom-0 left-0 right-0 top-0 flex h-full w-full flex-col bg-white pb-6 dark:bg-black">
|
||||||
<div className="p-4">
|
<div className="p-4">
|
||||||
<button
|
<button
|
||||||
className="mb-4"
|
className="mb-4"
|
||||||
onClick={() => {
|
onClick={closeMobileMenu}
|
||||||
setMobileMenuIsOpen(false);
|
|
||||||
}}
|
|
||||||
aria-label="Close mobile menu"
|
aria-label="Close mobile menu"
|
||||||
data-testid="close-mobile-menu"
|
data-testid="close-mobile-menu"
|
||||||
>
|
>
|
||||||
@ -97,9 +84,7 @@ export default function MobileMenu({ menu }: { menu: Menu[] }) {
|
|||||||
<Link
|
<Link
|
||||||
href={item.path}
|
href={item.path}
|
||||||
className="rounded-lg py-1 text-xl text-black transition-colors hover:text-gray-500 dark:text-white"
|
className="rounded-lg py-1 text-xl text-black transition-colors hover:text-gray-500 dark:text-white"
|
||||||
onClick={() => {
|
onClick={closeMobileMenu}
|
||||||
setMobileMenuIsOpen(false);
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{item.title}
|
{item.title}
|
||||||
</Link>
|
</Link>
|
||||||
@ -109,10 +94,9 @@ export default function MobileMenu({ menu }: { menu: Menu[] }) {
|
|||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</Dialog.Panel>
|
</Dialog.Panel>
|
||||||
</div>
|
</Transition.Child>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
)}
|
</Transition>
|
||||||
</AnimatePresence>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
"@headlessui/react": "^1.7.15",
|
"@headlessui/react": "^1.7.15",
|
||||||
"@vercel/og": "^0.5.6",
|
"@vercel/og": "^0.5.6",
|
||||||
"clsx": "^1.2.1",
|
"clsx": "^1.2.1",
|
||||||
"framer-motion": "^10.12.16",
|
|
||||||
"is-empty-iterable": "^3.0.0",
|
"is-empty-iterable": "^3.0.0",
|
||||||
"next": "13.4.6",
|
"next": "13.4.6",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
|
34
pnpm-lock.yaml
generated
34
pnpm-lock.yaml
generated
@ -10,9 +10,6 @@ dependencies:
|
|||||||
clsx:
|
clsx:
|
||||||
specifier: ^1.2.1
|
specifier: ^1.2.1
|
||||||
version: 1.2.1
|
version: 1.2.1
|
||||||
framer-motion:
|
|
||||||
specifier: ^10.12.16
|
|
||||||
version: 10.12.16(react-dom@18.2.0)(react@18.2.0)
|
|
||||||
is-empty-iterable:
|
is-empty-iterable:
|
||||||
specifier: ^3.0.0
|
specifier: ^3.0.0
|
||||||
version: 3.0.0
|
version: 3.0.0
|
||||||
@ -117,19 +114,6 @@ packages:
|
|||||||
regenerator-runtime: 0.13.11
|
regenerator-runtime: 0.13.11
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@emotion/is-prop-valid@0.8.8:
|
|
||||||
resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==}
|
|
||||||
requiresBuild: true
|
|
||||||
dependencies:
|
|
||||||
'@emotion/memoize': 0.7.4
|
|
||||||
dev: false
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
/@emotion/memoize@0.7.4:
|
|
||||||
resolution: {integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==}
|
|
||||||
dev: false
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
/@eslint-community/eslint-utils@4.4.0(eslint@8.42.0):
|
/@eslint-community/eslint-utils@4.4.0(eslint@8.42.0):
|
||||||
resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
|
resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
@ -1635,24 +1619,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==}
|
resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/framer-motion@10.12.16(react-dom@18.2.0)(react@18.2.0):
|
|
||||||
resolution: {integrity: sha512-w/SfWEIWJkYSgRHYBmln7EhcNo31ao8Xexol8lGXf1pR/tlnBtf1HcxoUmEiEh6pacB4/geku5ami53AAQWHMQ==}
|
|
||||||
peerDependencies:
|
|
||||||
react: ^18.0.0
|
|
||||||
react-dom: ^18.0.0
|
|
||||||
peerDependenciesMeta:
|
|
||||||
react:
|
|
||||||
optional: true
|
|
||||||
react-dom:
|
|
||||||
optional: true
|
|
||||||
dependencies:
|
|
||||||
react: 18.2.0
|
|
||||||
react-dom: 18.2.0(react@18.2.0)
|
|
||||||
tslib: 2.5.3
|
|
||||||
optionalDependencies:
|
|
||||||
'@emotion/is-prop-valid': 0.8.8
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/fs.realpath@1.0.0:
|
/fs.realpath@1.0.0:
|
||||||
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
|
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
|
||||||
dev: true
|
dev: true
|
||||||
|
Loading…
x
Reference in New Issue
Block a user