Remove unused framer motion features (#2464)

* fix: remove unused framer motion features

* fix: add changeset

* fix: non working tabs animation

* fix: remove unchanged changeset

* fix: move to patch
This commit is contained in:
Dominik K 2024-03-08 15:43:14 +01:00 committed by GitHub
parent a702bb869d
commit 2894aecca1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 198 additions and 161 deletions

View File

@ -0,0 +1,11 @@
---
"@nextui-org/accordion": patch
"@nextui-org/modal": patch
"@nextui-org/navbar": patch
"@nextui-org/popover": patch
"@nextui-org/ripple": patch
"@nextui-org/tabs": patch
"@nextui-org/tooltip": patch
---
Changes the motion important to the more lightweight m component in framer motion to only load the required features.

View File

@ -1,7 +1,7 @@
import {forwardRef} from "@nextui-org/system";
import {useMemo, ReactNode} from "react";
import {ChevronIcon} from "@nextui-org/shared-icons";
import {AnimatePresence, motion, useWillChange} from "framer-motion";
import {AnimatePresence, LazyMotion, domAnimation, m, useWillChange} from "framer-motion";
import {TRANSITION_VARIANTS} from "@nextui-org/framer-transitions";
import {UseAccordionItemProps, useAccordionItem} from "./use-accordion-item";
@ -53,31 +53,35 @@ const AccordionItem = forwardRef<"button", AccordionItemProps>((props, ref) => {
}
return keepContentMounted ? (
<motion.section
key="accordion-content"
animate={isOpen ? "enter" : "exit"}
exit="exit"
initial="exit"
style={{overflowY: "hidden", willChange}}
variants={TRANSITION_VARIANTS.collapse}
{...motionProps}
>
<div {...getContentProps()}>{children}</div>
</motion.section>
<LazyMotion features={domAnimation}>
<m.section
key="accordion-content"
animate={isOpen ? "enter" : "exit"}
exit="exit"
initial="exit"
style={{overflowY: "hidden", willChange}}
variants={TRANSITION_VARIANTS.collapse}
{...motionProps}
>
<div {...getContentProps()}>{children}</div>
</m.section>
</LazyMotion>
) : (
<AnimatePresence initial={false}>
{isOpen && (
<motion.section
key="accordion-content"
animate="enter"
exit="exit"
initial="exit"
style={{overflowY: "hidden", willChange}}
variants={TRANSITION_VARIANTS.collapse}
{...motionProps}
>
<div {...getContentProps()}>{children}</div>
</motion.section>
<LazyMotion features={domAnimation}>
<m.section
key="accordion-content"
animate="enter"
exit="exit"
initial="exit"
style={{overflowY: "hidden", willChange}}
variants={TRANSITION_VARIANTS.collapse}
{...motionProps}
>
<div {...getContentProps()}>{children}</div>
</m.section>
</LazyMotion>
)}
</AnimatePresence>
);

View File

@ -7,7 +7,7 @@ import {DismissButton} from "@react-aria/overlays";
import {TRANSITION_VARIANTS} from "@nextui-org/framer-transitions";
import {CloseIcon} from "@nextui-org/shared-icons";
import {RemoveScroll} from "react-remove-scroll";
import {motion} from "framer-motion";
import {domAnimation, LazyMotion, m} from "framer-motion";
import {useDialog} from "@react-aria/dialog";
import {mergeProps} from "@react-aria/utils";
import {HTMLNextUIProps} from "@nextui-org/system";
@ -78,13 +78,15 @@ const ModalContent = forwardRef<"div", ModalContentProps, KeysToOmit>((props, _)
}
return (
<motion.div
animate="enter"
exit="exit"
initial="exit"
variants={TRANSITION_VARIANTS.fade}
{...(getBackdropProps() as HTMLMotionProps<"div">)}
/>
<LazyMotion features={domAnimation}>
<m.div
animate="enter"
exit="exit"
initial="exit"
variants={TRANSITION_VARIANTS.fade}
{...(getBackdropProps() as HTMLMotionProps<"div">)}
/>
</LazyMotion>
);
}, [backdrop, disableAnimation, getBackdropProps]);
@ -95,16 +97,18 @@ const ModalContent = forwardRef<"div", ModalContentProps, KeysToOmit>((props, _)
{disableAnimation ? (
<div className={slots.wrapper({class: classNames?.wrapper})}>{content}</div>
) : (
<motion.div
animate="enter"
className={slots.wrapper({class: classNames?.wrapper})}
exit="exit"
initial="exit"
variants={scaleInOut}
{...motionProps}
>
{content}
</motion.div>
<LazyMotion features={domAnimation}>
<m.div
animate="enter"
className={slots.wrapper({class: classNames?.wrapper})}
exit="exit"
initial="exit"
variants={scaleInOut}
{...motionProps}
>
{content}
</m.div>
</LazyMotion>
)}
</RemoveScroll>
</div>

View File

@ -1,7 +1,7 @@
import {forwardRef, HTMLNextUIProps} from "@nextui-org/system";
import {useDOMRef} from "@nextui-org/react-utils";
import {clsx, dataAttr} from "@nextui-org/shared-utils";
import {AnimatePresence, HTMLMotionProps, motion} from "framer-motion";
import {AnimatePresence, domAnimation, HTMLMotionProps, LazyMotion, m} from "framer-motion";
import {mergeProps} from "@react-aria/utils";
import {ReactElement, useCallback} from "react";
import {RemoveScroll} from "react-remove-scroll";
@ -61,24 +61,26 @@ const NavbarMenu = forwardRef<"ul", NavbarMenuProps>((props, ref) => {
<AnimatePresence mode="wait">
{isMenuOpen ? (
<MenuWrapper>
<motion.ul
ref={domRef}
layoutScroll
animate="enter"
className={slots.menu?.({class: styles})}
data-open={dataAttr(isMenuOpen)}
exit="exit"
initial="exit"
style={{
// @ts-expect-error
"--navbar-height": height,
...style,
}}
variants={menuVariants}
{...mergeProps(motionProps, otherProps)}
>
{children}
</motion.ul>
<LazyMotion features={domAnimation}>
<m.ul
ref={domRef}
layoutScroll
animate="enter"
className={slots.menu?.({class: styles})}
data-open={dataAttr(isMenuOpen)}
exit="exit"
initial="exit"
style={{
// @ts-expect-error
"--navbar-height": height,
...style,
}}
variants={menuVariants}
{...mergeProps(motionProps, otherProps)}
>
{children}
</m.ul>
</LazyMotion>
</MenuWrapper>
) : null}
</AnimatePresence>

View File

@ -1,6 +1,6 @@
import {forwardRef} from "@nextui-org/system";
import {pickChildren} from "@nextui-org/react-utils";
import {motion} from "framer-motion";
import {LazyMotion, domAnimation, m} from "framer-motion";
import {mergeProps} from "@react-aria/utils";
import {hideOnScrollVariants} from "./navbar-transitions";
@ -31,14 +31,16 @@ const Navbar = forwardRef<"div", NavbarProps>((props, ref) => {
return (
<NavbarProvider value={context}>
{context.shouldHideOnScroll ? (
<motion.nav
animate={context.isHidden ? "hidden" : "visible"}
initial={false}
variants={hideOnScrollVariants}
{...mergeProps(context.getBaseProps(), context.motionProps)}
>
{content}
</motion.nav>
<LazyMotion features={domAnimation}>
<m.nav
animate={context.isHidden ? "hidden" : "visible"}
initial={false}
variants={hideOnScrollVariants}
{...mergeProps(context.getBaseProps(), context.motionProps)}
>
{content}
</m.nav>
</LazyMotion>
) : (
<Component {...context.getBaseProps()}>{content}</Component>
)}

View File

@ -10,7 +10,7 @@
import * as React from "react";
import {DismissButton, Overlay} from "@react-aria/overlays";
import {forwardRef} from "@nextui-org/system";
import {HTMLMotionProps, motion} from "framer-motion";
import {domAnimation, HTMLMotionProps, LazyMotion, m} from "framer-motion";
import {mergeProps} from "@react-aria/utils";
import {getTransformOrigins} from "@nextui-org/aria-utils";
import {TRANSITION_VARIANTS} from "@nextui-org/framer-transitions";
@ -39,19 +39,21 @@ const FreeSoloPopoverWrapper = ({
return disableAnimation ? (
<div {...otherProps}>{children}</div>
) : (
<motion.div
animate="enter"
exit="exit"
initial="initial"
style={{
...style,
...getTransformOrigins(placement === "center" ? "top" : placement),
}}
variants={TRANSITION_VARIANTS.scaleSpringOpacity}
{...mergeProps(otherProps, motionProps)}
>
{children}
</motion.div>
<LazyMotion features={domAnimation}>
<m.div
animate="enter"
exit="exit"
initial="initial"
style={{
...style,
...getTransformOrigins(placement === "center" ? "top" : placement),
}}
variants={TRANSITION_VARIANTS.scaleSpringOpacity}
{...mergeProps(otherProps, motionProps)}
>
{children}
</m.div>
</LazyMotion>
);
};
@ -87,13 +89,15 @@ const FreeSoloPopover = forwardRef<"div", FreeSoloPopoverProps>((props, ref) =>
}
return (
<motion.div
animate="enter"
exit="exit"
initial="exit"
variants={TRANSITION_VARIANTS.fade}
{...(getBackdropProps() as HTMLMotionProps<"div">)}
/>
<LazyMotion features={domAnimation}>
<m.div
animate="enter"
exit="exit"
initial="exit"
variants={TRANSITION_VARIANTS.fade}
{...(getBackdropProps() as HTMLMotionProps<"div">)}
/>
</LazyMotion>
);
}, [backdrop, disableAnimation, getBackdropProps]);

View File

@ -5,7 +5,7 @@ import {DOMAttributes, ReactNode, useMemo, useRef} from "react";
import {forwardRef} from "@nextui-org/system";
import {DismissButton} from "@react-aria/overlays";
import {TRANSITION_VARIANTS} from "@nextui-org/framer-transitions";
import {motion} from "framer-motion";
import {m, domAnimation, LazyMotion} from "framer-motion";
import {useDialog} from "@react-aria/dialog";
import {mergeProps} from "@react-aria/utils";
import {HTMLNextUIProps} from "@nextui-org/system";
@ -69,13 +69,15 @@ const PopoverContent = forwardRef<"div", PopoverContentProps>((props, _) => {
}
return (
<motion.div
animate="enter"
exit="exit"
initial="exit"
variants={TRANSITION_VARIANTS.fade}
{...(getBackdropProps() as HTMLMotionProps<"div">)}
/>
<LazyMotion features={domAnimation}>
<m.div
animate="enter"
exit="exit"
initial="exit"
variants={TRANSITION_VARIANTS.fade}
{...(getBackdropProps() as HTMLMotionProps<"div">)}
/>
</LazyMotion>
);
}, [backdrop, disableAnimation, getBackdropProps]);
@ -86,18 +88,20 @@ const PopoverContent = forwardRef<"div", PopoverContentProps>((props, _) => {
{disableAnimation ? (
content
) : (
<motion.div
animate="enter"
exit="exit"
initial="initial"
style={{
...getTransformOrigins(placement === "center" ? "top" : placement),
}}
variants={TRANSITION_VARIANTS.scaleSpringOpacity}
{...motionProps}
>
{content}
</motion.div>
<LazyMotion features={domAnimation}>
<m.div
animate="enter"
exit="exit"
initial="initial"
style={{
...getTransformOrigins(placement === "center" ? "top" : placement),
}}
variants={TRANSITION_VARIANTS.scaleSpringOpacity}
{...motionProps}
>
{content}
</m.div>
</LazyMotion>
)}
</RemoveScroll>
</div>

View File

@ -1,5 +1,5 @@
import {FC} from "react";
import {AnimatePresence, HTMLMotionProps, motion} from "framer-motion";
import {AnimatePresence, HTMLMotionProps, m, LazyMotion, domAnimation} from "framer-motion";
import {HTMLNextUIProps} from "@nextui-org/system";
import {RippleType} from "./use-ripple";
@ -26,30 +26,32 @@ const Ripple: FC<RippleProps> = (props) => {
return (
<AnimatePresence key={ripple.key} mode="popLayout">
<motion.span
animate={{transform: "scale(2)", opacity: 0}}
className="nextui-ripple"
exit={{opacity: 0}}
initial={{transform: "scale(0)", opacity: 0.35}}
style={{
position: "absolute",
backgroundColor: color,
borderRadius: "100%",
transformOrigin: "center",
pointerEvents: "none",
zIndex: 10,
top: ripple.y,
left: ripple.x,
width: `${ripple.size}px`,
height: `${ripple.size}px`,
...style,
}}
transition={{duration}}
onAnimationComplete={() => {
onClear(ripple.key);
}}
{...motionProps}
/>
<LazyMotion features={domAnimation}>
<m.span
animate={{transform: "scale(2)", opacity: 0}}
className="nextui-ripple"
exit={{opacity: 0}}
initial={{transform: "scale(0)", opacity: 0.35}}
style={{
position: "absolute",
backgroundColor: color,
borderRadius: "100%",
transformOrigin: "center",
pointerEvents: "none",
zIndex: 10,
top: ripple.y,
left: ripple.x,
width: `${ripple.size}px`,
height: `${ripple.size}px`,
...style,
}}
transition={{duration}}
onAnimationComplete={() => {
onClear(ripple.key);
}}
{...motionProps}
/>
</LazyMotion>
</AnimatePresence>
);
})}

View File

@ -9,7 +9,7 @@ import {useFocusRing} from "@react-aria/focus";
import {Node} from "@react-types/shared";
import {useTab} from "@react-aria/tabs";
import {useHover} from "@react-aria/interactions";
import {motion} from "framer-motion";
import {m, domMax, LazyMotion} from "framer-motion";
import {useIsMounted} from "@nextui-org/use-is-mounted";
import {ValuesType} from "./use-tabs";
@ -118,18 +118,20 @@ const Tab = forwardRef<"button", TabItemProps>((props, ref) => {
onClick={handleClick}
>
{isSelected && !disableAnimation && !disableCursorAnimation && isMounted ? (
<motion.span
className={slots.cursor({class: classNames?.cursor})}
data-slot="cursor"
layoutDependency={false}
layoutId="cursor"
transition={{
type: "spring",
bounce: 0.15,
duration: 0.5,
}}
{...motionProps}
/>
<LazyMotion features={domMax}>
<m.span
className={slots.cursor({class: classNames?.cursor})}
data-slot="cursor"
layoutDependency={false}
layoutId="cursor"
transition={{
type: "spring",
bounce: 0.15,
duration: 0.5,
}}
{...motionProps}
/>
</LazyMotion>
) : null}
<div
className={slots.tabContent({

View File

@ -1,6 +1,6 @@
import {forwardRef} from "@nextui-org/system";
import {OverlayContainer} from "@react-aria/overlays";
import {AnimatePresence, motion} from "framer-motion";
import {AnimatePresence, m, LazyMotion, domAnimation} from "framer-motion";
import {TRANSITION_VARIANTS} from "@nextui-org/framer-transitions";
import {warn} from "@nextui-org/shared-utils";
import {Children, cloneElement, isValidElement} from "react";
@ -57,18 +57,20 @@ const Tooltip = forwardRef<"div", TooltipProps>((props, ref) => {
const animatedContent = (
<div ref={tooltipRef} id={id} style={style}>
<motion.div
animate="enter"
exit="exit"
initial="exit"
variants={TRANSITION_VARIANTS.scaleSpring}
{...mergeProps(motionProps, otherTooltipProps)}
style={{
...getTransformOrigins(placement),
}}
>
<Component {...getTooltipContentProps()}>{content}</Component>
</motion.div>
<LazyMotion features={domAnimation}>
<m.div
animate="enter"
exit="exit"
initial="exit"
variants={TRANSITION_VARIANTS.scaleSpring}
{...mergeProps(motionProps, otherTooltipProps)}
style={{
...getTransformOrigins(placement),
}}
>
<Component {...getTooltipContentProps()}>{content}</Component>
</m.div>
</LazyMotion>
</div>
);