Materials UI for React, additionally referred to as MUI, doesn’t include a local Dropdown part. Right here I wish to share the dropdown part that I’ve used for a number of of my freelance initiatives when utilizing Materials UI. Earlier than you need to use it, it’s a must to set up its Materials UI (MUI) dependencies:
npm set up @emotion/styled @mui/materials @mui/icons-material
Subsequent follows the implementation of a Materials UI Dropdown Part:
import * as React from 'react';
import styled from '@emotion/styled';
import Menu from '@mui/materials/Menu';
import MenuItem from '@mui/materials/MenuItem';
export const Dropdown = React.forwardRef(
(
{
set off,
menu,
keepOpen: keepOpenGlobal,
isOpen: controlledIsOpen,
onOpen: onControlledOpen,
minWidth,
},
ref
) => {
const [isInternalOpen, setInternalOpen] = React.useState(null);
const isOpen = controlledIsOpen || isInternalOpen;
let anchorRef = React.useRef(null);
if (ref) {
anchorRef = ref;
}
const handleOpen = (occasion) => {
occasion.stopPropagation();
if (menu.size) {
onControlledOpen
? onControlledOpen(occasion.currentTarget)
: setInternalOpen(occasion.currentTarget);
}
};
const handleClose = (occasion) => {
occasion.stopPropagation();
if (
anchorRef.present &&
anchorRef.present.comprises(occasion.goal)
) {
return;
}
handleForceClose();
};
const handleForceClose = () => {
onControlledOpen
? onControlledOpen(null)
: setInternalOpen(null);
};
const renderMenu = (menuItem, index) => {
const { keepOpen: keepOpenLocal, ...props } = menuItem.props;
let extraProps = {};
if (props.menu) {
extraProps = {
parentMenuOpen: isOpen,
};
}
return React.createElement(menuItem.kind, {
...props,
key: index,
...extraProps,
onClick: (occasion) => {
occasion.stopPropagation();
if (!keepOpenGlobal && !keepOpenLocal) {
handleClose(occasion);
}
if (menuItem.props.onClick) {
menuItem.props.onClick(occasion);
}
},
kids: props.menu
? React.Youngsters.map(props.menu, renderMenu)
: props.kids,
});
};
return (
<>
{React.cloneElement(set off, {
onClick: isOpen ? handleForceClose : handleOpen,
ref: anchorRef,
})}
<Menu
PaperProps={{ sx: { minWidth: minWidth ?? 0 } }}
anchorEl={isOpen}
open={!!isOpen}
onClose={handleClose}
>
{React.Youngsters.map(menu, renderMenu)}
</Menu>
</>
);
}
);
export const DropdownMenuItem = styled(MenuItem)`
show: flex;
justify-content: space-between !necessary;
& > svg {
margin-left: 32px;
}
`;
The utilization of the MUI Dropdown compopnent appears to be like as follows:
import * as React from 'react';
import Button from '@mui/materials/Button';
import AddCircleOutlinedIcon from '@mui/icons-material/AddCircleOutlined';
import EditIcon from '@mui/icons-material/Edit';
import DeleteForeverIcon from '@mui/icons-material/DeleteForever';
import { Dropdown, DropdownMenuItem } from './dropdown';
const App = () => {
const handleCreate = () => {
console.log('create one thing');
};
const handleEdit = () => {
console.log('edit one thing');
};
const handleDelete = () => {
console.log('delete one thing');
};
return (
<Dropdown
keepOpen
open={open}
set off={<Button>Dropdown</Button>}
menu={[
<DropdownMenuItem onClick={handleCreate}>
Create <AddCircleOutlinedIcon />
</DropdownMenuItem>,
<DropdownMenuItem onClick={handleEdit}>
Edit <EditIcon />
</DropdownMenuItem>,
<DropdownMenuItem onClick={handleDelete}>
Delete <DeleteForeverIcon />
</DropdownMenuItem>,
]}
/>
);
};
export default App;
If you wish to get to know a little bit of the underlying implementation particulars:
If you wish to get a nested dropdown menu for this dropdown part:
Optionally you need to use the
keepOpen
property to not shut the dropdown if one among its menu merchandise’s is clicked and theminWidth
property to outline a width for the dropdown’s menu. If you wish to flip the dropdown part right into a managed part, you possibly can cross itisOpen
andonOpen
props too.