How to align Material-UI Menu items? - javascript

I use the menu and menu item of material-ui to build a select dropdown menu, but I found one thing strange: the dropdown menu always expand to the left side of the box, as the image shown below:
I've tried to use the alignItems property inside my <MenuItem> but it didn't work.
My code is shown below. Can anybody help me to fix this problem? I really appreciate your help!
<Menu
id="order-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={() => setAnchorEl(null)}
>
{options.map((option, index) => (
<MenuItem
key={option}
selected={index === selectedIndex}
onClick={(event) => handleMenuItemClick(event, index)}
>
{option}
</MenuItem>
))}
</Menu>

The default styles controlling this are in ListItem where it specifies justifyContent: 'flex-start'.
You can change this to be right aligned with:
const MenuItem = withStyles({
root: {
justifyContent: "flex-end"
}
})(MuiMenuItem);
Here's a full working example:
import React from "react";
import Button from "#material-ui/core/Button";
import Menu from "#material-ui/core/Menu";
import MuiMenuItem from "#material-ui/core/MenuItem";
import { withStyles } from "#material-ui/core/styles";
const MenuItem = withStyles({
root: {
justifyContent: "flex-end"
}
})(MuiMenuItem);
export default function SimpleMenu() {
const [anchorEl, setAnchorEl] = React.useState(null);
const handleClick = event => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
return (
<div>
<Button
aria-controls="simple-menu"
aria-haspopup="true"
onClick={handleClick}
>
Open Menu
</Button>
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
<MenuItem onClick={handleClose}>1</MenuItem>
<MenuItem onClick={handleClose}>2</MenuItem>
<MenuItem onClick={handleClose}>3</MenuItem>
<MenuItem onClick={handleClose}>10</MenuItem>
<MenuItem onClick={handleClose}>20</MenuItem>
<MenuItem onClick={handleClose}>300</MenuItem>
</Menu>
</div>
);
}
Related documentation:
https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content
https://css-tricks.com/snippets/css/a-guide-to-flexbox/

A more flexible solution to your problem,
use <ListItemText> inside <MenuItem>
In this way you can style parts of the element.
<MenuItem onClick={handleClose}>
<ListItemText style={{ paddingRight: 50 }}>undo</ListItemText>
<ListItemText style={{ textAlign: "right" }}>ctrl+z</ListItemText>
</MenuItem>
example : shortcut hint on the right.

You can use this code to align the menu
anchorOrigin={{
vertical: 'bottom',
horizontal: 'center',
}}
transformOrigin={{
vertical: 'bottom',
horizontal: 'center',
}}
Example
<Menu
id="order-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={() => setAnchorEl(null)}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'center',
}}
transformOrigin={{
vertical: 'bottom',
horizontal: 'center',
}}
style={{top: 170}} // you can set top position so that it will show under the selection
>
{options.map((option, index) => (
<MenuItem
key={option}
selected={index === selectedIndex}
onClick={(event) => handleMenuItemClick(event, index)}
>
{option}
</MenuItem>
))}

mui 5 could use sx.
<MenuItem sx={{ justifyContent: 'flex-end' }}>

Related

Using the Material UI App Bar and React Router

I'm currently trying to build a website using react for my web development class, which is my first foray into JS and React. I'm using a Material UI appbar for my header. I've used react router in one of my class examples so I've set that up and my app bar is displaying as intended. My question is, how do I set the buttons on the appbar/header to link to my pages? The default code (minus imports) provided by Material UI is below with my placeholder page names added.
const pages = ['Utility List', 'Register', 'Login'];
const settings = ['Profile', 'Account', 'Logout'];
const Header = () => {
const [anchorElNav, setAnchorElNav] = React.useState(null);
const [anchorElUser, setAnchorElUser] = React.useState(null);
const handleOpenNavMenu = (event) => {
setAnchorElNav(event.currentTarget);
};
const handleOpenUserMenu = (event) => {
setAnchorElUser(event.currentTarget);
};
const handleCloseNavMenu = () => {
setAnchorElNav(null);
};
const handleCloseUserMenu = () => {
setAnchorElUser(null);
};
return (
<AppBar position="static">
<Container maxWidth="xl">
<Toolbar disableGutters>
<Typography
variant="h6"
noWrap
component="div"
sx={{ mr: 2, display: { xs: 'none', md: 'flex' } }}
>
LOGO
</Typography>
<Box sx={{ flexGrow: 1, display: { xs: 'flex', md: 'none' } }}>
<IconButton
size="large"
aria-label="account of current user"
aria-controls="menu-appbar"
aria-haspopup="true"
onClick={handleOpenNavMenu}
color="inherit"
>
<MenuIcon />
</IconButton>
<Menu
id="menu-appbar"
anchorEl={anchorElNav}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'left',
}}
keepMounted
transformOrigin={{
vertical: 'top',
horizontal: 'left',
}}
open={Boolean(anchorElNav)}
onClose={handleCloseNavMenu}
sx={{
display: { xs: 'block', md: 'none' },
}}
>
{pages.map((page) => (
<MenuItem key={page} onClick={handleCloseNavMenu}>
<Typography textAlign="center">{page}</Typography>
</MenuItem>
))}
</Menu>
</Box>
<Typography
variant="h6"
noWrap
component="div"
sx={{ flexGrow: 1, display: { xs: 'flex', md: 'none' } }}
>
LOGO
</Typography>
<Box sx={{ flexGrow: 1, display: { xs: 'none', md: 'flex' } }}>
{pages.map((page) => (
<Button
key={page}
onClick={handleCloseNavMenu}
sx={{ my: 2, color: 'white', display: 'block' }}
>
{page}
</Button>
))}
</Box>
<Box sx={{ flexGrow: 0 }}>
<Tooltip title="Open settings">
<IconButton onClick={handleOpenUserMenu} sx={{ p: 0 }}>
<Avatar alt="Remy Sharp" src="/static/images/avatar/2.jpg" />
</IconButton>
</Tooltip>
<Menu
sx={{ mt: '45px' }}
id="menu-appbar"
anchorEl={anchorElUser}
anchorOrigin={{
vertical: 'top',
horizontal: 'right',
}}
keepMounted
transformOrigin={{
vertical: 'top',
horizontal: 'right',
}}
open={Boolean(anchorElUser)}
onClose={handleCloseUserMenu}
>
{settings.map((setting) => (
<MenuItem key={setting} onClick={handleCloseUserMenu}>
<Typography textAlign="center">{setting}</Typography>
</MenuItem>
))}
</Menu>
</Box>
</Toolbar>
</Container>
</AppBar>
);
};
export default Header;
Find the place in your code where your navbar links are added to JSX. Wrap each link in Link component from react-router
const yourPages = [
{ text: 'Home', href: '/' },
{ text: 'About', href: '/about' }
]
// inside return statement
{yourPages.map((page) => (
<Link href={page.href}>{page.text}</Link
)}
...

Conditionally Rendering Material UI Elements in React

I want to render Material UI Elements like MenuItem of a AppBar Conditionally if some conditions are true. In my example menu items should only be rendered for specific users. But it doesnt work like the way it would work with normal html in react.
{context.token && context.userRole === "USER" && (
<MenuItem key="submission" onClick={handleCloseNavMenu}>
<Typography textAlign="center">Submission</Typography>
</MenuItem>
)}
{context.token && context.userRole === "JUDGE" && (
<MenuItem key="submissions" onClick={handleCloseNavMenu}>
<Typography textAlign="center">Submissions</Typography>
</MenuItem>
)}
Its rendering this Items all the time anyways and seems to ignoring the conditions.
The full code:
import React from "react";
import { NavLink } from "react-router-dom";
import AuthContext from "../context/auth-context.js";
import AppBar from "#mui/material/AppBar";
import Box from "#mui/material/Box";
import Toolbar from "#mui/material/Toolbar";
import IconButton from "#mui/material/IconButton";
import Typography from "#mui/material/Typography";
import Menu from "#mui/material/Menu";
import MenuIcon from "#mui/icons-material/Menu";
import Container from "#mui/material/Container";
import Avatar from "#mui/material/Avatar";
import Button from "#mui/material/Button";
import Tooltip from "#mui/material/Tooltip";
import MenuItem from "#mui/material/MenuItem";
import ComputerIcon from "#mui/icons-material/Computer";
const ResponsiveAppBar = (props) => {
const pages = ["Conditions", "Winner", "Submission", "Submissions", "Login"];
const settings = ["Profile", "Settings", "Logout"];
const [anchorElNav, setAnchorElNav] = React.useState(null);
const [anchorElUser, setAnchorElUser] = React.useState(null);
const handleOpenNavMenu = (event) => {
setAnchorElNav(event.currentTarget);
};
const handleOpenUserMenu = (event) => {
setAnchorElUser(event.currentTarget);
};
const handleCloseNavMenu = () => {
setAnchorElNav(null);
};
const handleCloseUserMenu = () => {
setAnchorElUser(null);
};
return (
<AuthContext.Consumer>
{(context) => (
<AppBar position="static">
<Container maxWidth="xl">
<Toolbar disableGutters>
<Typography
variant="h6"
noWrap
component="div"
sx={{ mr: 2, display: { xs: "none", md: "flex" } }}
>
<ComputerIcon />
</Typography>
<Box sx={{ flexGrow: 1, display: { xs: "flex", md: "none" } }}>
<IconButton
size="large"
aria-label="account of current user"
aria-controls="menu-appbar"
aria-haspopup="true"
onClick={handleOpenNavMenu}
color="inherit"
>
<MenuIcon />
</IconButton>
<Menu
id="menu-appbar"
anchorEl={anchorElNav}
anchorOrigin={{
vertical: "bottom",
horizontal: "left",
}}
keepMounted
transformOrigin={{
vertical: "top",
horizontal: "left",
}}
open={Boolean(anchorElNav)}
onClose={handleCloseNavMenu}
sx={{
display: { xs: "block", md: "none" },
}}
>
{context.token && context.userRole === "USER" && (
<MenuItem key="submission" onClick={handleCloseNavMenu}>
<Typography textAlign="center">Submission</Typography>
</MenuItem>
)}
{context.token && context.userRole === "JUDGE" && (
<MenuItem key="submissions" onClick={handleCloseNavMenu}>
<Typography textAlign="center">Submissions</Typography>
</MenuItem>
)}
<MenuItem key="conditions" onClick={handleCloseNavMenu}>
<Typography textAlign="center">Conditions</Typography>
</MenuItem>
<MenuItem key="winner" onClick={handleCloseNavMenu}>
<Typography textAlign="center">Winner</Typography>
</MenuItem>
</Menu>
</Box>
<Typography
variant="h6"
noWrap
component="div"
sx={{ flexGrow: 1, display: { xs: "flex", md: "none" } }}
>
LOGO
</Typography>
<Box sx={{ flexGrow: 1, display: { xs: "none", md: "flex" } }}>
{pages.map((page) => (
<Button
key={page}
onClick={handleCloseNavMenu}
sx={{ my: 2, color: "white", display: "block" }}
>
{page}
</Button>
))}
</Box>
<Box sx={{ flexGrow: 0 }}>
<Tooltip title="Open settings">
<IconButton onClick={handleOpenUserMenu} sx={{ p: 0 }}>
<Avatar
alt="Remy Sharp"
src="/static/images/avatar/2.jpg"
/>
</IconButton>
</Tooltip>
<Menu
sx={{ mt: "45px" }}
id="menu-appbar"
anchorEl={anchorElUser}
anchorOrigin={{
vertical: "top",
horizontal: "right",
}}
keepMounted
transformOrigin={{
vertical: "top",
horizontal: "right",
}}
open={Boolean(anchorElUser)}
onClose={handleCloseUserMenu}
>
{settings.map((setting) => (
<MenuItem key={setting} onClick={handleCloseNavMenu}>
<Typography textAlign="center">{setting}</Typography>
</MenuItem>
))}
</Menu>
</Box>
</Toolbar>
</Container>
</AppBar>
)}
</AuthContext.Consumer>
);
};
export default ResponsiveAppBar;

ReactJS: Close automatically the menu when change page

I have a create a nested menu, but I have a problem with it.
I have :
Parent_Menu
Parent1
> Child_Menu1
> Child_Menu2
Parent2
Now if I click for example in Child_Menu1, i'm redirect to the page correctly and also the Parent1 menu is closed, but the Parent_Menu reamins opened (So i can click another time or in parent1 or in parent2).
I would to close all the menu (the parent_menu) when I change page.
import React, { useState } from 'react';
import MenuItem from 'app/shared/layout/menus/menu-item';
import { Dropdown, DropdownToggle, DropdownMenu, UncontrolledDropdown, DropdownItem, NavLink } from 'reactstrap';
import { NavDropdown } from './menu-components';
export const EntitiesMenu = props => {
const [dropDownOpen, setDropDownOpen] = useState(false);
const toggle = () => setDropDownOpen(prevState => !prevState);
return (
<NavDropdown
icon="th-list"
name="Parent_Menu"
id="parent-menu"
data-cy="parent_menu"
style={{ maxHeight: '80vh', minWidth: '150px', minHeight: '250px' }}
>
<Dropdown isOpen={dropDownOpen} toggle={toggle} direction="right">
<DropdownToggle nav caret style={{ color: '#000000', marginLeft: 25 }}>
Parent1
</DropdownToggle>
<DropdownMenu right style={{ border: '0px', outline: 'none', marginTop: 20 }}>
<DropdownItem>
<MenuItem icon="asterisk" to="/child_menu1">
Child_Menu1
</MenuItem>
</DropdownItem>
<DropdownItem>
<MenuItem icon="asterisk" to="/child_menu2">
Child_Menu2
</MenuItem>
</DropdownItem>
</DropdownMenu>
<NavLink href="/parent2" style={{ color: '#000000', marginLeft: 25 }}>
Parent2
</NavLink>
</Dropdown>
</NavDropdown>
);
};
How can I do to close automatically all the menu?
have you try the onBlur?
or you can even use the onClick
import React, { useState } from 'react';
import MenuItem from 'app/shared/layout/menus/menu-item';
import { Dropdown, DropdownToggle, DropdownMenu, UncontrolledDropdown, DropdownItem, NavLink } from 'reactstrap';
import { NavDropdown } from './menu-components';
export const EntitiesMenu = props => {
const [dropDownOpen, setDropDownOpen] = useState(false);
const toggle = () => setDropDownOpen(prevState => !prevState);
return (
<NavDropdown
icon="th-list"
name="Parent_Menu"
id="parent-menu"
data-cy="parent_menu"
style={{ maxHeight: '80vh', minWidth: '150px', minHeight: '250px' }}
>
<Dropdown isOpen={dropDownOpen} toggle={toggle} direction="right">
<DropdownToggle nav caret style={{ color: '#000000', marginLeft: 25 }}>
Parent1
</DropdownToggle>
<DropdownMenu onBlur={e=>{
toggle()
}} right style={{ border: '0px', outline: 'none', marginTop: 20 }}>
<DropdownItem>
<MenuItem onClick={()=>{
toggle()
}} icon="asterisk" to="/child_menu1">
Child_Menu1
</MenuItem>
</DropdownItem>
<DropdownItem>
<MenuItem onClick={()=>{
toggle()
}} icon="asterisk" to="/child_menu2">
Child_Menu2
</MenuItem>
</DropdownItem>
</DropdownMenu>
<NavLink onClick={()=>{
toggle()
}} href="/parent2" style={{ color: '#000000', marginLeft: 25 }}>
Parent2
</NavLink>
</Dropdown>
</NavDropdown>
);
};
import React, { useState } from 'react';
import MenuItem from 'app/shared/layout/menus/menu-item';
import { Dropdown, DropdownToggle, DropdownMenu, UncontrolledDropdown, DropdownItem, NavLink } from 'reactstrap';
import { NavDropdown } from './menu-components';
export const EntitiesMenu = props => {
const [dropDownOpen, setDropDownOpen] = useState(false);
const [dropDownStyle, setStyle] = useState('80px');
const toggle = () => setDropDownOpen(prevState => !prevState);
useEffect(()=>{
dropDownOpen ? setStyle('0'); : setStyle('80px');
},[dropDownOpen]);
return (
<NavDropdown
icon="th-list"
name="Parent_Menu"
id="parent-menu"
data-cy="parent_menu"
style={{ maxHeight: customHeight, minWidth: '150px', minHeight: '250px' }}
>
<Dropdown isOpen={dropDownOpen} toggle={toggle} direction="right">
<DropdownToggle nav caret style={{ color: '#000000', marginLeft: 25 }}>
Parent1
</DropdownToggle>
<DropdownMenu right style={{ border: '0px', outline: 'none', marginTop: 20 }}>
<DropdownItem>
<MenuItem icon="asterisk" to="/child_menu1">
Child_Menu1
</MenuItem>
</DropdownItem>
<DropdownItem>
<MenuItem icon="asterisk" to="/child_menu2">
Child_Menu2
</MenuItem>
</DropdownItem>
</DropdownMenu>
<NavLink href="/parent2" style={{ color: '#000000', marginLeft: 25 }}>
Parent2
</NavLink>
</Dropdown>
</NavDropdown>
);
};

How to make a drop-down menu appear exactly below the bar in Material-UI?

I created a drop-down menu by using Material-UI, and I found one thing annoying: I want to let my drop-down menu appear under the bar when I click it, but every time it just covers the bar (as the image below)
Is there any way I can do to let the drop-down menu appear below the bar? (not covering the Your order label and the number)
My codes are as below: I try to modify the anchorOrigin property and transformOrigin property but it didn't work.
<Menu
id="order-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={() => setAnchorEl(null)}
elevation={20}
getContentAnchorEl={null}
anchorOrigin={{ vertical: "bottom", horizontal: "center", }}
transformOrigin={{ vertical: -100, horizontal: 150, }} >
I will really appreciate your help!
Here's an example that aligns the top-center (transformOrigin) of the menu with the bottom-center (anchorOrigin) of the button:
import React from "react";
import Button from "#material-ui/core/Button";
import Menu from "#material-ui/core/Menu";
import MuiMenuItem from "#material-ui/core/MenuItem";
import styled from "styled-components";
const MenuItem = styled(MuiMenuItem)`
justify-content: flex-end;
`;
export default function SimpleMenu() {
const [anchorEl, setAnchorEl] = React.useState(null);
const handleClick = event => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
return (
<div>
<Button
aria-controls="simple-menu"
aria-haspopup="true"
onClick={handleClick}
>
Open Menu
</Button>
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
getContentAnchorEl={null}
anchorOrigin={{ vertical: "bottom", horizontal: "center" }}
transformOrigin={{ horizontal: "center" }}
>
<MenuItem onClick={handleClose}>1</MenuItem>
<MenuItem onClick={handleClose}>2</MenuItem>
<MenuItem onClick={handleClose}>3</MenuItem>
<MenuItem onClick={handleClose}>10</MenuItem>
<MenuItem onClick={handleClose}>20</MenuItem>
<MenuItem onClick={handleClose}>300</MenuItem>
</Menu>
</div>
);
}
Related documentation: https://material-ui.com/api/popover/#props

Material-ui Popover, Select, Menus componets positions come wrong, when i give zoom index

i give zoom index to my html, and after that Material-ui Popover, Select and Menus components which is use Material-ui Modal components, positions come wrong
Here is my İndex.css
#media only screen and (max-width: 1500px) {
html{
zoom:0.8
}}
My Js.
<Popover
anchorReference="anchorEl"
open={Boolean(userMenu)}
anchorEl={userMenu}
onClose={userMenuClose}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'center'
}}
transformOrigin={{
vertical: 'top',
horizontal: 'center'
}}
action={refa}
classes={{
paper: 'py-8'
}}
>
<>
<MenuItem onClick={() => changeLanguage('tr')}>
<img src="/assets/images/flags/tr.png" alt="tr"
className="flag mr-8" />
<ListItemText className="pl-0 " primary="TR" />
</MenuItem>
<MenuItem onClick={() => changeLanguage('en')}>
<img src="/assets/images/flags/en.png" alt="en"
className="flag mr-8" />
<ListItemText className="pl-0" primary="EN" />
</MenuItem>
</>
</Popover>
Thats what should be enter image description here
But thats happen enter image description here

Categories

Resources