diff --git a/package.json b/package.json index 5d5c1bbe..09e2bdc6 100644 --- a/package.json +++ b/package.json @@ -80,6 +80,7 @@ "emoji-mart": "5.5.2", "fast-average-color": "9.4.0", "fast-deep-equal": "3.1.3", + "framer-motion": "11.0.3", "gpt-tokenizer": "2.1.2", "hast-util-from-html": "2.0.1", "hast-util-to-html": "9.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 29faa7db..a35d80fb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -159,6 +159,9 @@ dependencies: fast-deep-equal: specifier: 3.1.3 version: 3.1.3 + framer-motion: + specifier: 11.0.3 + version: 11.0.3(react-dom@18.2.0)(react@18.2.0) gpt-tokenizer: specifier: 2.1.2 version: 2.1.2 @@ -1856,6 +1859,20 @@ packages: resolution: {integrity: sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==} dev: false + /@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==} + requiresBuild: true + dev: false + optional: true + /@emotion/memoize@0.8.1: resolution: {integrity: sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==} dev: false @@ -8332,6 +8349,24 @@ packages: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} dev: true + /framer-motion@11.0.3(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-6x2poQpIWBdbZwLd73w6cKZ1I9IEPIU94C6/Swp1Zt3LJ+sB5bPe1E2wC6EH5hSISXNkMJ4afH7AdwS7MrtkWw==} + 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.6.2 + optionalDependencies: + '@emotion/is-prop-valid': 0.8.8 + dev: false + /fs-constants@1.0.0: resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} dev: false diff --git a/src/app/[locale]/framer-lazy-feature.ts b/src/app/[locale]/framer-lazy-feature.ts new file mode 100644 index 00000000..bae59b0f --- /dev/null +++ b/src/app/[locale]/framer-lazy-feature.ts @@ -0,0 +1,3 @@ +import { domMax } from "framer-motion" + +export default domMax diff --git a/src/app/[locale]/providers.tsx b/src/app/[locale]/providers.tsx index 9f0e3873..267fb7a4 100644 --- a/src/app/[locale]/providers.tsx +++ b/src/app/[locale]/providers.tsx @@ -1,5 +1,6 @@ "use client" +import { LazyMotion, MotionConfig } from "framer-motion" import { IntlError, IntlErrorCode, @@ -61,6 +62,9 @@ export const mantineDefaultColorScheme = mantineDefaultColorSchemeT as | "light" | "dark" +const loadFeatures = () => + import("./framer-lazy-feature").then((res) => res.default) + export default function Providers({ children }: { children: React.ReactNode }) { useMobileLayout() useNProgress() @@ -97,7 +101,16 @@ export default function Providers({ children }: { children: React.ReactNode }) { signInStrategy="simple" ignoreWalletDisconnectEvent={true} > - {children} + + + {children} + + {React.cloneElement(target, { ref: refs.setReference })} - - {dropdown} - + + + + {dropdown} + + + ) } @@ -71,7 +88,7 @@ Menu.Item = function MenuItem({ const childElement = ( <> {icon} diff --git a/src/components/ui/Modal.tsx b/src/components/ui/Modal.tsx index 39eaa046..61692535 100644 --- a/src/components/ui/Modal.tsx +++ b/src/components/ui/Modal.tsx @@ -1,9 +1,15 @@ "use client" +import { + AnimatePresence, + m, + useMotionValue, + useMotionValueEvent, +} from "framer-motion" import { useTranslations } from "next-intl" -import React, { forwardRef, Fragment } from "react" +import React, { forwardRef } from "react" -import { Dialog, Transition } from "@headlessui/react" +import { Dialog } from "@headlessui/react" import { cn } from "~/lib/utils" @@ -41,46 +47,57 @@ export const Modal = forwardRef( ref, ) => { const t = useTranslations() + const x = useMotionValue(0) + + useMotionValueEvent(x, "animationComplete", () => { + console.log("animation Complete on x") + afterLeave?.() + }) return ( - - setOpen(false)} - className="relative" - style={{ - zIndex: zIndex ? zIndex : 10, - }} - > - + {open && ( + setOpen(false)} + className="relative" + style={{ + zIndex: zIndex ? zIndex : 10, + }} > -
- -
- {/* The actual dialog panel */} ( {title} setOpen(false)} > @@ -118,10 +135,10 @@ export const Modal = forwardRef( )} - -
-
-
+ + + )} + ) }, ) diff --git a/src/components/ui/Tabs.tsx b/src/components/ui/Tabs.tsx index f31c39eb..85574009 100644 --- a/src/components/ui/Tabs.tsx +++ b/src/components/ui/Tabs.tsx @@ -1,5 +1,6 @@ "use client" +import { AnimatePresence, m } from "framer-motion" import { useTranslations } from "next-intl" import { usePathname } from "next/navigation" import React from "react" @@ -49,38 +50,47 @@ export const Tabs = ({ className, )} > - {items.map((item) => { - if (item.hidden) return null + + {items.map((item) => { + if (item.hidden) return null - return ( - - {item.tooltip ? ( - + return ( + + {item.tooltip ? ( + + <>{t(item.text)} + + ) : ( <>{t(item.text)} - - ) : ( - <>{t(item.text)} - )} - - ) - })} + )} + {type !== "rounded" && item.active && ( + + )} + + ) + })} + ) } diff --git a/src/components/ui/Tooltip.tsx b/src/components/ui/Tooltip.tsx index f505a318..f53177a5 100644 --- a/src/components/ui/Tooltip.tsx +++ b/src/components/ui/Tooltip.tsx @@ -1,5 +1,6 @@ "use client" +import { AnimatePresence, m } from "framer-motion" import { useState } from "react" import { @@ -58,7 +59,7 @@ export const Tooltip = ({ }) return ( - <> +
{children}
- {isMounted && ( -
- {label} -
- )} - + + {isMounted && ( + + {label} + + )} + +
) }