diff --git a/docs/pages/experiments/base/render-props.tsx b/docs/pages/experiments/base/render-props.tsx new file mode 100644 index 00000000000000..dd30358e6a6cfd --- /dev/null +++ b/docs/pages/experiments/base/render-props.tsx @@ -0,0 +1,91 @@ +import * as React from 'react'; +import { Menu } from '@mui/base/Menu'; +import { MenuItem } from '@mui/base/MenuItem'; +import { MenuButton, MenuButtonRootSlotProps } from '@mui/base/MenuButton'; +import { Dropdown } from '@mui/base/Dropdown'; +import IconButton from '@mui/joy/IconButton'; +import MenuIcon from '@mui/icons-material/Menu'; +import { CssVarsProvider } from '@mui/joy'; + +function WithRenderProp() { + return ( + + ( + + + + )} + /> + + Profile + My account + Logout + + + ); +} + +function WithSlotsAndSlotProps() { + return ( + + + + + + Profile + My account + Logout + + + ); +} + +const MenuIconButton = React.forwardRef(function MenuIconButton( + props: MenuButtonRootSlotProps, + ref: React.ForwardedRef, +) { + return ( + + {props.children} + + ); +}); + +function WithSlots() { + return ( + + + + + + Profile + My account + Logout + + + ); +} + +export default function RenderProps() { + return ( + + + + + + ); +} diff --git a/packages/mui-base/src/MenuButton/MenuButton.tsx b/packages/mui-base/src/MenuButton/MenuButton.tsx index 74095b9fd09dce..fb7255e17e6752 100644 --- a/packages/mui-base/src/MenuButton/MenuButton.tsx +++ b/packages/mui-base/src/MenuButton/MenuButton.tsx @@ -1,8 +1,8 @@ 'use client'; import * as React from 'react'; import PropTypes from 'prop-types'; -import { MenuButtonOwnerState, MenuButtonProps } from './MenuButton.types'; -import { useSlotProps } from '../utils'; +import { MenuButtonOwnerState, MenuButtonProps, MenuButtonRootSlotProps } from './MenuButton.types'; +import { useSlotProps, WithOptionalOwnerState } from '../utils'; import { useMenuButton } from '../useMenuButton'; import { unstable_composeClasses as composeClasses } from '../composeClasses'; import { useClassNamesOverride } from '../utils/ClassNameConfigurator'; @@ -39,6 +39,7 @@ const MenuButton = React.forwardRef(function MenuButton( slots = {}, slotProps = {}, focusableWhenDisabled = false, + renderRoot, ...other } = props; @@ -59,7 +60,7 @@ const MenuButton = React.forwardRef(function MenuButton( const classes = useUtilityClasses(ownerState); const Root = slots.root || 'button'; - const rootProps = useSlotProps({ + const rootProps: WithOptionalOwnerState = useSlotProps({ elementType: Root, getSlotProps: getRootProps, externalForwardedProps: other, @@ -67,12 +68,20 @@ const MenuButton = React.forwardRef(function MenuButton( additionalProps: { ref: forwardedRef, type: 'button', + children, }, ownerState, className: classes.root, }); - return {children}; + // eslint-disable-next-line @typescript-eslint/naming-convention + const { ownerState: _, ...otherRootProps } = rootProps; + + return renderRoot ? ( + renderRoot(otherRootProps, ownerState) + ) : ( + {children} + ); }); MenuButton.propTypes /* remove-proptypes */ = { diff --git a/packages/mui-base/src/MenuButton/MenuButton.types.ts b/packages/mui-base/src/MenuButton/MenuButton.types.ts index 5d1d951824cc39..509605099c2689 100644 --- a/packages/mui-base/src/MenuButton/MenuButton.types.ts +++ b/packages/mui-base/src/MenuButton/MenuButton.types.ts @@ -1,3 +1,4 @@ +import { UseMenuButtonRootSlotProps } from '../useMenuButton'; import { SlotComponentProps } from '../utils/types'; export interface MenuButtonRootSlotPropsOverrides {} @@ -35,6 +36,11 @@ export interface MenuButtonProps { slotProps?: { root?: SlotComponentProps<'button', MenuButtonRootSlotPropsOverrides, MenuButtonOwnerState>; }; + + renderRoot?: ( + props: Omit, + ownerState: MenuButtonOwnerState, + ) => React.JSX.Element; } export interface MenuButtonSlots { @@ -50,3 +56,8 @@ export type MenuButtonOwnerState = MenuButtonProps & { focusableWhenDisabled: boolean; open: boolean; }; + +export type MenuButtonRootSlotProps = UseMenuButtonRootSlotProps & { + ownerState: MenuButtonOwnerState; + children?: React.ReactNode; +}; diff --git a/packages/mui-base/src/useMenuButton/useMenuButton.types.ts b/packages/mui-base/src/useMenuButton/useMenuButton.types.ts index 3ae91422c41851..81ac3402b528f7 100644 --- a/packages/mui-base/src/useMenuButton/useMenuButton.types.ts +++ b/packages/mui-base/src/useMenuButton/useMenuButton.types.ts @@ -15,7 +15,8 @@ export interface UseMenuButtonParameters { rootRef?: React.Ref; } -type UseMenuButtonRootSlotProps = ExternalProps & UseMenuButtonRootSlotOwnProps; +export type UseMenuButtonRootSlotProps = ExternalProps & + UseMenuButtonRootSlotOwnProps; interface UseMenuButtonRootSlotOwnProps { 'aria-haspopup': 'menu';