monday-ui-react-core
Version:
Official monday.com UI resources for application development in React.js
147 lines (134 loc) • 3.56 kB
JSX
import React, { useCallback, useState, useMemo } from "react";
import PropTypes from "prop-types";
import cx from "classnames";
import Dialog from "../Dialog/Dialog";
import Menu from "../Icon/Icons/components/Menu";
import "./MenuButton.scss";
import DialogContentContainer from "../DialogContentContainer/DialogContentContainer";
function BEMClass(className) {
return `menu-button--wrapper--${className}`;
}
const showTrigger = ["click", "enter"];
const MOVE_BY = { main: 0, secondary: -6 };
const MenuButton = ({
componentClassName,
children,
component,
size,
open,
zIndex,
ariaLabel,
closeDialogOnContentClick,
dialogClassName,
dialogPaddingSize
}) => {
const [isOpen, setIsOpen] = useState(open);
const onDialogDidHide = useCallback(() => {
setIsOpen(false);
}, [setIsOpen]);
const onDialogDidShow = useCallback(() => {
setIsOpen(true);
}, [setIsOpen]);
const hideTrigger = useMemo(() => {
const triggers = ["clickoutside", "esckey"];
if (closeDialogOnContentClick) {
triggers.push("onContentClick");
}
return triggers;
}, [closeDialogOnContentClick]);
const content = useMemo(() => {
return (
<DialogContentContainer
size={dialogPaddingSize}
type={DialogContentContainer.types.POPOVER}
>
{children}
</DialogContentContainer>
);
}, [children, dialogPaddingSize]);
const Icon = component;
const iconSize = size - 4;
return (
<Dialog
wrapperClassName={dialogClassName}
position="bottom-start"
startingEdge="bottom"
animationType="expand"
content={content}
moveBy={MOVE_BY}
showTrigger={showTrigger}
hideTrigger={hideTrigger}
onDialogDidShow={onDialogDidHide}
onDialogDidHide={onDialogDidHide}
referenceWrapperClassName={BEMClass("reference-icon")}
zIndex={zIndex}
>
<button
type="button"
role="menu"
className={cx(
"menu-button--wrapper",
componentClassName,
BEMClass(`size-${size}`),
{
[BEMClass("open")]: isOpen
}
)}
aria-haspopup="true"
aria-expanded={isOpen}
aria-label={ariaLabel}
>
<Icon size={Math.min(iconSize, 28).toString()} />
</button>
</Dialog>
);
};
const MenuButtonSizes = {
XXS: "16",
XS: "24",
SMALL: "32",
MEDIUM: "40",
LARGE: "48"
};
MenuButton.sizes = MenuButtonSizes;
MenuButton.paddingSizes = DialogContentContainer.sizes;
MenuButton.propTypes = {
componentClassName: PropTypes.string,
/**
* Receives React Component
*/
component: PropTypes.func,
size: PropTypes.oneOf([
MenuButtonSizes.XXS,
MenuButtonSizes.XS,
MenuButtonSizes.SMALL,
MenuButtonSizes.MEDIUM,
MenuButtonSizes.LARGE
]),
open: PropTypes.bool,
zIndex: PropTypes.number,
ariaLabel: PropTypes.string,
closeDialogOnContentClick: PropTypes.bool,
/*
Class name to provide the element which wraps the popover/modal/dialog
*/
dialogClassName: PropTypes.string,
dialogPaddingSize: PropTypes.oneOf([
MenuButton.paddingSizes.NONE,
MenuButton.paddingSizes.SMALL,
MenuButton.paddingSizes.MEDIUM,
MenuButton.paddingSizes.LARGE
])
};
MenuButton.defaultProps = {
componentClassName: "",
component: Menu,
size: MenuButtonSizes.SMALL,
open: false,
zIndex: null,
ariaLabel: "Menu",
closeDialogOnContentClick: false,
dialogClassName: "",
dialogPaddingSize: DialogContentContainer.sizes.MEDIUM
};
export default MenuButton;