-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Expand file tree
/
Copy pathnavbar-menu.tsx
More file actions
92 lines (82 loc) 路 2.68 KB
/
Copy pathnavbar-menu.tsx
File metadata and controls
92 lines (82 loc) 路 2.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
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 {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>
<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>
</MenuWrapper>
) : null}
</AnimatePresence>
);
return <Overlay portalContainer={portalContainer}>{contents}</Overlay>;
});
NavbarMenu.displayName = "NextUI.NavbarMenu";
export default NavbarMenu;