From 753358a13bc2f0a1a4b78e25c65b74fca23d820c Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Mon, 11 Dec 2023 18:33:15 -0500 Subject: [PATCH] fix(striker-ui): add button with menu --- striker-ui/components/ButtonWithMenu.tsx | 83 ++++++++++++++++++++++++ striker-ui/types/ButtonWithMenu.d.ts | 6 ++ 2 files changed, 89 insertions(+) create mode 100644 striker-ui/components/ButtonWithMenu.tsx create mode 100644 striker-ui/types/ButtonWithMenu.d.ts diff --git a/striker-ui/components/ButtonWithMenu.tsx b/striker-ui/components/ButtonWithMenu.tsx new file mode 100644 index 00000000..797eff73 --- /dev/null +++ b/striker-ui/components/ButtonWithMenu.tsx @@ -0,0 +1,83 @@ +import { MoreVert as MoreVertIcon } from '@mui/icons-material'; +import { Box } from '@mui/material'; +import { FC, MouseEventHandler, useCallback, useMemo, useState } from 'react'; + +import ContainedButton from './ContainedButton'; +import IconButton from './IconButton/IconButton'; +import Menu from './Menu'; + +const ButtonWithMenu: FC = (props) => { + const { + children, + muiMenuProps, + onButtonClick, + onItemClick, + variant = 'icon', + ...menuProps + } = props; + + const [anchorEl, setAnchorEl] = useState(null); + + const open = useMemo(() => Boolean(anchorEl), [anchorEl]); + + const buttonContent = useMemo(() => children ?? , [children]); + + const buttonClickHandler = useCallback>( + (...args) => { + const { + 0: { currentTarget }, + } = args; + + setAnchorEl(currentTarget); + + return onButtonClick?.call(null, ...args); + }, + [onButtonClick], + ); + + const buttonElement = useMemo(() => { + if (variant === 'contained') { + return ( + + {buttonContent} + + ); + } + + return ( + {buttonContent} + ); + }, [buttonClickHandler, buttonContent, variant]); + + const itemClickHandler = useCallback< + Exclude + >( + (key, value, ...rest) => { + setAnchorEl(null); + + return onItemClick?.call(null, key, value, ...rest); + }, + [onItemClick], + ); + + return ( + + {buttonElement} + setAnchorEl(null), + ...muiMenuProps, + }} + onItemClick={itemClickHandler} + open={open} + {...menuProps} + /> + + ); +}; + +export default ButtonWithMenu as ( + props: ButtonWithMenuProps, +) => ReturnType>>; diff --git a/striker-ui/types/ButtonWithMenu.d.ts b/striker-ui/types/ButtonWithMenu.d.ts new file mode 100644 index 00000000..4d59fa16 --- /dev/null +++ b/striker-ui/types/ButtonWithMenu.d.ts @@ -0,0 +1,6 @@ +type ButtonWithMenuOptionalProps = Omit, 'open'> & { + onButtonClick?: import('react').MouseEventHandler; + variant?: 'contained' | 'icon'; +}; + +type ButtonWithMenuProps = ButtonWithMenuOptionalProps;