mirror of
https://github.com/nextui-org/nextui.git
synced 2025-12-08 19:26:11 +00:00
* fix: remove unused framer motion features * fix: add changeset * fix: non working tabs animation * fix: remove unchanged changeset * fix: move to patch
95 lines
2.8 KiB
TypeScript
95 lines
2.8 KiB
TypeScript
import {forwardRef, HTMLNextUIProps} from "@nextui-org/system";
|
|
import {useDOMRef} from "@nextui-org/react-utils";
|
|
import {clsx, dataAttr} from "@nextui-org/shared-utils";
|
|
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";
|
|
import {Overlay} from "@react-aria/overlays";
|
|
|
|
import {menuVariants} from "./navbar-menu-transitions";
|
|
import {useNavbarContext} from "./navbar-context";
|
|
|
|
export interface NavbarMenuProps extends HTMLNextUIProps<"ul"> {
|
|
children?: React.ReactNode;
|
|
/**
|
|
* The container element in which the navbar menu overlay portal will be placed.
|
|
* @default document.body
|
|
*/
|
|
portalContainer?: Element;
|
|
/**
|
|
* The props to modify the framer motion animation. Use the `variants` API to create your own animation.
|
|
*/
|
|
motionProps?: HTMLMotionProps<"ul">;
|
|
}
|
|
|
|
const NavbarMenu = forwardRef<"ul", NavbarMenuProps>((props, ref) => {
|
|
const {className, children, portalContainer, motionProps, style, ...otherProps} = props;
|
|
const domRef = useDOMRef(ref);
|
|
|
|
const {slots, isMenuOpen, height, disableAnimation, classNames} = useNavbarContext();
|
|
|
|
const styles = clsx(classNames?.menu, className);
|
|
|
|
const MenuWrapper = useCallback(
|
|
({children}: {children: ReactElement}) => {
|
|
return (
|
|
<RemoveScroll forwardProps enabled={isMenuOpen} removeScrollBar={false}>
|
|
{children}
|
|
</RemoveScroll>
|
|
);
|
|
},
|
|
[isMenuOpen],
|
|
);
|
|
|
|
const contents = disableAnimation ? (
|
|
<MenuWrapper>
|
|
<ul
|
|
ref={domRef}
|
|
className={slots.menu?.({class: styles})}
|
|
data-open={dataAttr(isMenuOpen)}
|
|
style={{
|
|
// @ts-expect-error
|
|
"--navbar-height": height,
|
|
}}
|
|
{...otherProps}
|
|
>
|
|
{children}
|
|
</ul>
|
|
</MenuWrapper>
|
|
) : (
|
|
<AnimatePresence mode="wait">
|
|
{isMenuOpen ? (
|
|
<MenuWrapper>
|
|
<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>
|
|
);
|
|
|
|
return <Overlay portalContainer={portalContainer}>{contents}</Overlay>;
|
|
});
|
|
|
|
NavbarMenu.displayName = "NextUI.NavbarMenu";
|
|
|
|
export default NavbarMenu;
|