diff --git a/packages/odyssey-react-mui/src/Button.tsx b/packages/odyssey-react-mui/src/Button.tsx index 292e57ad69..bebd794398 100644 --- a/packages/odyssey-react-mui/src/Button.tsx +++ b/packages/odyssey-react-mui/src/Button.tsx @@ -93,7 +93,7 @@ const Button = ({ return ( <> {tooltipText && ( - + {button} )} diff --git a/packages/odyssey-react-mui/src/MenuButton.tsx b/packages/odyssey-react-mui/src/MenuButton.tsx index 6c8897589c..657f53fc74 100644 --- a/packages/odyssey-react-mui/src/MenuButton.tsx +++ b/packages/odyssey-react-mui/src/MenuButton.tsx @@ -20,7 +20,9 @@ import { MenuItem, useUniqueId, } from "./"; -import { memo, MouseEvent, ReactElement, useMemo, useState } from "react"; +import { memo, type ReactElement, useCallback, useMemo, useState } from "react"; + +import { MenuContext, MenuContextType } from "./MenuContext"; export type MenuButtonProps = { /** @@ -29,10 +31,6 @@ export type MenuButtonProps = { children: Array< ReactElement >; - /** - * The end Icon on the trigggering Button - */ - buttonEndIcon?: ReactElement; /** * The label on the triggering Button */ @@ -41,6 +39,10 @@ export type MenuButtonProps = { * The variant of the triggering Button */ buttonVariant?: ButtonProps["variant"]; + /** + * The end Icon on the trigggering Button + */ + endIcon?: ReactElement; /** * The id of the `input` element. */ @@ -53,23 +55,23 @@ export type MenuButtonProps = { const MenuButton = ({ buttonLabel = "", - children, - buttonEndIcon = , buttonVariant = "secondary", + children, + endIcon = , id: idOverride, ariaLabel, }: MenuButtonProps) => { const [anchorEl, setAnchorEl] = useState(null); - const open = Boolean(anchorEl); - - const handleClick = (event: MouseEvent) => { - setAnchorEl(event.currentTarget); - }; + const isOpen = Boolean(anchorEl); - const handleClose = () => { + const closeMenu = useCallback(() => { setAnchorEl(null); - }; + }, []); + + const openMenu = useCallback((event) => { + setAnchorEl(event.currentTarget); + }, []); const uniqueId = useUniqueId(idOverride); @@ -78,27 +80,38 @@ const MenuButton = ({ [uniqueId] ); + const providerValue = useMemo( + () => ({ + closeMenu, + openMenu, + }), + [closeMenu, openMenu] + ); + return (
); diff --git a/packages/odyssey-react-mui/src/MenuContext.ts b/packages/odyssey-react-mui/src/MenuContext.ts new file mode 100644 index 0000000000..93d70bd086 --- /dev/null +++ b/packages/odyssey-react-mui/src/MenuContext.ts @@ -0,0 +1,25 @@ +/*! + * Copyright (c) 2023-present, Okta, Inc. and/or its affiliates. All rights reserved. + * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") + * + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and limitations under the License. + */ + +import { createContext, MouseEventHandler } from "react"; + +export type MenuContextType = { + closeMenu: () => void; + openMenu: MouseEventHandler; +}; + +export const MenuContext = createContext({ + // eslint-disable-next-line @typescript-eslint/no-empty-function + closeMenu: () => {}, + // eslint-disable-next-line @typescript-eslint/no-empty-function + openMenu: () => {}, +}); diff --git a/packages/odyssey-react-mui/src/MenuItem.tsx b/packages/odyssey-react-mui/src/MenuItem.tsx index 7d09a2847e..51747486aa 100644 --- a/packages/odyssey-react-mui/src/MenuItem.tsx +++ b/packages/odyssey-react-mui/src/MenuItem.tsx @@ -10,10 +10,12 @@ * See the License for the specific language governing permissions and limitations under the License. */ -import { memo, forwardRef } from "react"; import { MenuItem as MuiMenuItem } from "@mui/material"; import { menuItemClasses } from "@mui/material/MenuItem"; import type { MenuItemProps as MuiMenuItemProps } from "@mui/material"; +import { memo, useContext } from "react"; + +import { MenuContext } from "./MenuContext"; export interface MenuItemProps extends Omit< @@ -30,19 +32,22 @@ export interface MenuItemProps isDestructive?: boolean; } -const MenuItem = forwardRef( - ({ isDestructive, ...props }, ref) => ( +const MenuItem = ({ isDestructive, ...props }: MenuItemProps) => { + const { closeMenu } = useContext(MenuContext); + console.log(closeMenu); + + return ( {props.children} - ) -); + ); +}; const MemoizedMenuItem = memo(MenuItem); MemoizedMenuItem.displayName = "MenuItem"; diff --git a/packages/odyssey-storybook/src/components/odyssey-mui/MenuButton/MenuButton.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-mui/MenuButton/MenuButton.stories.tsx index 77e773c8c2..6042f321b2 100644 --- a/packages/odyssey-storybook/src/components/odyssey-mui/MenuButton/MenuButton.stories.tsx +++ b/packages/odyssey-storybook/src/components/odyssey-mui/MenuButton/MenuButton.stories.tsx @@ -36,10 +36,13 @@ const storybookMeta: Meta = { buttonLabel: { control: "text", }, - buttonEndIcon: { + buttonVariant: { control: "text", }, - buttonVariant: { + endIcon: { + control: "text", + }, + id: { control: "text", }, }, @@ -51,16 +54,13 @@ const storybookMeta: Meta = { export default storybookMeta; -const DefaultTemplate: StoryObj = {}; - export const Simple: StoryObj = { - ...DefaultTemplate, args: { buttonLabel: "More actions", children: [ - View details, - Edit configuration, - Launch, + View details, + Edit configuration, + Launch, ], }, }; @@ -68,19 +68,19 @@ export const Simple: StoryObj = { export const ActionIcons: StoryObj = { args: { children: [ - + Assign crew , - + View destination , - + @@ -95,9 +95,9 @@ export const ButtonVariant: StoryObj = { buttonLabel: "More actions", buttonVariant: "floating", children: [ - View details, - Edit configuration, - Launch, + View details, + Edit configuration, + Launch, ], }, }; @@ -107,13 +107,13 @@ export const Groupings: StoryObj = { buttonLabel: "More actions", children: [ Crew, - Assign captain, - View roster, + Assign captain, + View roster, Ship, - Configure thrusters, - View cargo, + Configure thrusters, + View cargo, , - Logout, + Logout, ], }, }; @@ -122,22 +122,24 @@ export const WithDestructive: StoryObj = { args: { buttonLabel: "Cargo options", children: [ - View details, - Edit inventory, - Jettison cargo, + View details, + Edit inventory, + + Jettison cargo + , ], }, }; export const IconButton: StoryObj = { args: { + ariaLabel: "Add", children: [ - View details, - Edit configuration, - Launch, + View details, + Edit configuration, + Launch, ], buttonLabel: "", - buttonEndIcon: , - ariaLabel: "Add", + endIcon: , }, };