Making Material-UI Appbar/Grid responsive - ReactJS - reactjs

I built out a footer using Material-UI#next AppBar and I would like to center align the icons within the Grid and on being responsive, each grid-item should be in a new line center-aligned. Please advice. In desktop mode, they all should be in a straight line.
This is my code:
import {
AppBar,
Grid,
Link,
Stack,
Toolbar,
Typography
} from "#material-ui/core";
import React from "react";
import { Facebook, LinkedIn, Twitter } from "#material-ui/icons";
import { styled } from "#material-ui/core/styles";
const StyledLink = styled(Link)`
color: #ffffff;
& .MuiSvgIcon-root:hover {
color: #ffffff;
}
`;
const Footer = () => {
return (
<footer>
<AppBar sx={{ top: "auto", bottom: 0, backgroundColor: "#304659" }}>
<Toolbar variant="dense">
<Grid container spacing={{ xs: 1, sm: 2, md: 4 }}>
<Grid item xs={12} sm={4} justifyContent="center">
<Typography sx={{ color: "white" }}>
{new Date().getFullYear()}© All rights reserved.
</Typography>
</Grid>
<Grid item sm={4} xs={12} textAlign="center">
<Stack direction={"row"} spacing={{ sm: 2 }}>
<StyledLink
href="https://www.twitter.com"
underline="always"
sx={{ color: "white" }}
>
<Twitter />
</StyledLink>
<StyledLink href="https://www.linkedin.com" underline="always">
<LinkedIn />
</StyledLink>
<StyledLink href="https://www.facebook.com" underline="always">
<Facebook />
</StyledLink>
</Stack>
</Grid>
<Grid item xs={12} sm={4} textAlign="right">
<Link
href="https://privacy-policy/"
underline="always"
sx={{ color: "white" }}
>
Privacy Policy
</Link>
</Grid>
</Grid>
</Toolbar>
</AppBar>
<Toolbar />
</footer>
);
};
export default Footer;
CodeSandboxLink: Link

import {
AppBar,
Grid,
Link,
Stack,
Toolbar,
Typography
} from "#material-ui/core";
import React from "react";
import { Facebook, LinkedIn, Twitter } from "#material-ui/icons";
import { styled } from "#material-ui/core/styles";
const StyledLink = styled(Link)`
color: #ffffff;
& .MuiSvgIcon-root:hover {
color: #ffffff;
}
`;
const Footer = () => {
return (
<footer>
<AppBar sx={{ top: "auto", bottom: 0, backgroundColor: "#304659" }}>
<Toolbar variant="dense">
<Grid container spacing={{ xs: 1, sm: 2, md: 4 }}>
<Grid
item
xs={12}
sm={4}
sx={{ textAlign: "center" }}
>
<Typography sx={{ color: "white" }}>
{new Date().getFullYear()}© All rights reserved.
</Typography>
</Grid>
<Grid item sm={4} xs={12} style={{ textAlign: "center" }}>
<StyledLink
href="https://www.twitter.com"
underline="always"
sx={{ color: "white" }}
>
<Twitter />
</StyledLink>
<StyledLink href="https://www.linkedin.com" underline="always">
<LinkedIn />
</StyledLink>
<StyledLink href="https://www.facebook.com" underline="always">
<Facebook />
</StyledLink>
</Grid>
<Grid item xs={12} sm={4} style={{ textAlign: "center" }}>
<Link
href="https://privacy-policy/"
underline="always"
sx={{ color: "white" }}
>
Privacy Policy
</Link>
</Grid>
</Grid>
</Toolbar>
</AppBar>
<Toolbar />
</footer>
);
};
export default Footer;
I just changed some css styles. Try this.

Related

How to make only the clicked icon true using useState, react and typescript?

After clicking on the FavoriteIcon inside the ExamplesCard all the icons turn red instead of just one icon. I'm using useState to change icon state value between true and false and style to change icon color.
Componenet ExamplesCard.tsx
import * as React from "react";
import {
Box,
Card,
CardActionArea,
CardActions,
CardContent,
CardMedia,
Grid,
Typography
} from "#mui/material";
import FavoriteIcon from "#mui/icons-material/Favorite";
import { ButtonProps } from "./ButtonProps";
import data from "./data/data.json";
import { useState } from "react";
export default function ExemplesCard() {
const [iconFavorite, setIconFavorite] = useState(false);
const ChangeColorFavorite = () => {
setIconFavorite(!iconFavorite);
};
return (
<Box sx={{ flexGrow: 1, margin: "0 2rem" }}>
<Grid
container
justifyContent="center"
spacing={{ xs: 8, sm: 8, md: 8, lg: 8, xl: 8 }}
className="GRID1"
>
{data.map((item) => {
return (
<Grid
item
xs={12}
sm={6}
md={4}
lg={3}
xl={2}
sx={{
display: "flex",
justifyContent: "center",
marginTop: "1rem"
}}
>
<Card
key={item.id}
sx={{
p: "1rem",
boxShadow: 4,
maxWidth: {
xs: "250px",
sm: "250px",
md: "280px",
lg: "300px",
xl: "300px"
}
}}
>
<CardActionArea>
<CardMedia component="img" height="140" image={item.img} />
<CardContent>
<Typography gutterBottom variant="h5" component="div">
{item.title}
</Typography>
<Typography variant="body2" color="text.secondary">
Lizards are a widespread group of squamate reptiles, with
over 6,000 species, ranging across all continents except
Antarctica
</Typography>
</CardContent>
</CardActionArea>
<CardActions>
<ButtonProps
size="small"
endIcon={
<FavoriteIcon
onClick={ChangeColorFavorite}
style={{ color: iconFavorite ? "red" : "white" }}
/>
}
>
Favorite
</ButtonProps>
</CardActions>
</Card>
</Grid>
);
})}
</Grid>
</Box>
);
}
I used the useState to store the current value of the icon (true or false), however, it was not enough to leave only the icon clicked in red. When clicking on the FavoriteIcon I expected that only the icon clicked would turn red.
Code link in codesanbox
your are using one state iconFavorite of type boolean where you actually want to use amount of the data array entries of type boolean[]. Every icon needs its own color state. This code works.
import * as React from "react";
import {
Box,
Card,
CardActionArea,
CardActions,
CardContent,
CardMedia,
Grid,
Typography
} from "#mui/material";
import FavoriteIcon from "#mui/icons-material/Favorite";
import { ButtonProps } from "./ButtonProps";
import data from "./data/data.json";
import { useState } from "react";
export default function ExemplesCard() {
const [iconFavorite, setIconFavorite] = useState([ ...Array(data.length).keys() ].map( i => false));
const ChangeColorFavorite = (idx: number) => {
const newIconFavorite = iconFavorite.slice();
newIconFavorite[idx] = !iconFavorite[idx];
setIconFavorite(newIconFavorite);
};
return (
<Box sx={{ flexGrow: 1, margin: "0 2rem" }}>
<Grid
container
justifyContent="center"
spacing={{ xs: 8, sm: 8, md: 8, lg: 8, xl: 8 }}
className="GRID1"
>
{data.map((item,idx) => {
return (
<Grid
item
xs={12}
sm={6}
md={4}
lg={3}
xl={2}
sx={{
display: "flex",
justifyContent: "center",
marginTop: "1rem"
}}
>
<Card
key={item.id}
sx={{
p: "1rem",
boxShadow: 4,
maxWidth: {
xs: "250px",
sm: "250px",
md: "280px",
lg: "300px",
xl: "300px"
}
}}
>
<CardActionArea>
<CardMedia component="img" height="140" image={item.img} />
<CardContent>
<Typography gutterBottom variant="h5" component="div">
{item.title}
</Typography>
<Typography variant="body2" color="text.secondary">
Lizards are a widespread group of squamate reptiles, with
over 6,000 species, ranging across all continents except
Antarctica
</Typography>
</CardContent>
</CardActionArea>
<CardActions>
<ButtonProps
size="small"
endIcon={
<FavoriteIcon
onClick={() => ChangeColorFavorite(idx)}
style={{ color: iconFavorite[idx] ? "red" : "white" }}
/>
}
>
Favorite
</ButtonProps>
</CardActions>
</Card>
</Grid>
);
})}
</Grid>
</Box>
);
}
Try doing this instead. It might work.
import * as React from "react";
import {
Box,
Card,
CardActionArea,
CardActions,
CardContent,
CardMedia,
Grid,
Typography
} from "#mui/material";
import FavoriteIcon from "#mui/icons-material/Favorite";
import { ButtonProps } from "./ButtonProps";
import data from "./data/data.json";
import { useState } from "react";
export default function ExemplesCard() {
const [iconFavorite, setIconFavorite] = useState(false);
return (
<Box sx={{ flexGrow: 1, margin: "0 2rem" }}>
<Grid
container
justifyContent="center"
spacing={{ xs: 8, sm: 8, md: 8, lg: 8, xl: 8 }}
className="GRID1"
>
{data.map((item) => {
return (
<Grid
item
xs={12}
sm={6}
md={4}
lg={3}
xl={2}
sx={{
display: "flex",
justifyContent: "center",
marginTop: "1rem"
}}
>
<Card
key={item.id}
sx={{
p: "1rem",
boxShadow: 4,
maxWidth: {
xs: "250px",
sm: "250px",
md: "280px",
lg: "300px",
xl: "300px"
}
}}
>
<CardActionArea>
<CardMedia component="img" height="140" image={item.img} />
<CardContent>
<Typography gutterBottom variant="h5" component="div">
{item.title}
</Typography>
<Typography variant="body2" color="text.secondary">
Lizards are a widespread group of squamate reptiles, with
over 6,000 species, ranging across all continents except
Antarctica
</Typography>
</CardContent>
</CardActionArea>
<CardActions>
<ButtonProps
size="small"
endIcon={
<FavoriteIcon
onClick={() => setIconFavorite(true)}
style={iconFavorite ? {color: "red"} : {color: "black"}}
/>
}
>
Favorite
</ButtonProps>
</CardActions>
</Card>
</Grid>
);
})}
</Grid>
</Box>
);
}

MUI React menu never get closed

On this MUI AppBar/Drawer sample, I have added a MUI Menu to edit profile, with an anchor on a div. It's located on the top right corner. I like to be able to click on the username or the profile icon to pop the menu out. For some reason the menu never disappear. I have try to add console.log in the callbacks. It shows the open callback is called right after the close one. Can someone explain why and how to close the menu ?
Here is my code, and the full project on Codesandbox :
import React from "react";
import Box from "#mui/material/Box";
import Grid from "#mui/material/Grid";
import IconButton from "#mui/material/IconButton";
import Menu from "#mui/material/Menu";
import MenuIcon from "#mui/icons-material/Menu";
import MenuItem from "#mui/material/MenuItem";
import Toolbar from "#mui/material/Toolbar";
import AccountCircle from "#mui/icons-material/AccountCircle";
import { styled } from "#mui/material/styles";
import { useNavigate } from "react-router-dom";
export default function TopBar(props) {
const navigate = useNavigate();
const [anchorEl, setAnchorEl] = React.useState(null);
const handleMenuOpen = (event) => {
console.log("set menu open");
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
console.log("set menu close");
setAnchorEl(null);
};
const UserName = styled("div")(({ theme }) => ({
fontSize: "1em",
marginRight: "0.7em",
display: "inline",
height: "100%",
textAlign: "center",
cursor: "pointer"
}));
const Logo = styled("img")(({ theme }) => ({
height: "42px",
width: "42px",
backgroundColor: "#FFF",
marginRight: "0.7em"
}));
return (
<Toolbar>
<Grid
style={{ justifyContent: "space-between", alignItems: "center" }}
container
>
<Grid item style={{ display: "inline-flex", alignItems: "center" }}>
<IconButton
color="inherit"
aria-label="open drawer"
onClick={props.handleDrawerOpen}
edge="start"
sx={{
...(props.drawerOpen && {
display: {
xs: "block",
sm: "none"
}
})
}}
>
<MenuIcon />
</IconButton>
</Grid>
<Grid item style={{ display: "inline-flex", alignItems: "center" }}>
<Logo
src=""
alt="logo"
onClick={() => {
props.handleDrawerClose();
navigate("/");
}}
/>
<Box
sx={{
whiteSpace: "nowrap",
fontSize: { xs: "1em", sm: "1.25em" },
fontWeight: { xs: 400, sm: 500 }
}}
>
Toolbar test
</Box>
</Grid>
<Grid item style={{ display: "flex", alignItems: "center" }}>
<div
style={{ display: "inline-flex", alignItems: "center" }}
onClick={handleMenuOpen}
>
<UserName sx={{ display: { xs: "none", sm: "block" } }}>
{props.userName}
</UserName>
<IconButton
color="inherit"
aria-label="user"
edge="start"
size="large"
>
<AccountCircle />
</IconButton>
<Menu
anchorEl={anchorEl}
open={Boolean(anchorEl)}
onClose={handleClose}
>
<MenuItem
onClick={() => {
props.handleDrawerClose();
navigate("/test");
}}
>
My Profile
</MenuItem>
<MenuItem
onClick={() => {
props.handleDrawerClose();
navigate("/logout");
}}
>
Logout
</MenuItem>
</Menu>
</div>
</Grid>
</Grid>
</Toolbar>
);
}
You somehow managed that when you trigger the onClose event, you are simultaneously triggering handleMenuOpen function. I would suggest you use a button base to handle opening the menu.
Something like this:
<ButtonBase onClick={handleMenuOpen}>
<UserName sx={{ display: { xs: "none", sm: "block" } }}>
{props.userName}
</UserName>
<AccountCircle />
</ButtonBase>
And dont forget to remove the onClick event from your div.
You can also take a look of the fork that i made.

Open page and scroll to section React Router dom

Goal: I want to make it so that when I click a button in my navbar, it takes the user to a page and a section of the page.
This is how I would do it with regular html.
<a href="secondpage#section"/>
But how can this be accomplished with React-router-dom?
Here is what I have tried so far but it wont scroll to the correct section on click:
https://codesandbox.io/s/hopeful-night-q06msw
import { AppBar, Button, Toolbar } from "#mui/material";
import React from "react";
import { Link } from "react-router-dom";
export default function Navbar() {
return (
<AppBar position="fixed">
<Toolbar>
<Button component={Link} to="/" sx={{ color: "#fff" }}>
Hello
</Button>
<Button component={Link} to="/second" sx={{ color: "#fff" }}>
SecondpageTop
</Button>
<Button
component={Link}
to={{ pathname: "/second", hash: "#sectiontwo" }}
sx={{ color: "#fff" }}
>
SecondpageSectionwo
</Button>
</Toolbar>
</AppBar>
);
}
import { Box, Typography } from "#mui/material";
import React from "react";
import Navbar from "./Navbar";
export default function () {
return (
<>
<Navbar></Navbar>
<Typography sx={{ mt: "50px", color: "red" }}>Sup</Typography>
<Box
sx={{
width: "150px",
height: "150px",
mb: "1000px",
backgroundColor: "red"
}}
>
<Typography sx={{ color: "#fff" }}>This is the top box</Typography>
</Box>
<div
id="sectiontwo"
style={{ width: "150px", height: "150px", backgroundColor: "blue" }}
>
<Typography sx={{ color: "#fff" }}>
This is where to scroll to
</Typography>
</div>
</>
);
}

How can I center Logo and text in material-ui Appbar?

I use Material-Ui Appbar and want to simply center my logo and title in the middle (See the picture).
But I tried different methods, still nothing works. Following is my code, do you know what's wrong with my code?
You can also try the code in codesandbox:
https://codesandbox.io/s/material-ui-appbar-logo-7q80d?file=/src/MyAppBar.tsx:797-1455
Here is my clasess:
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
flexGrow: 1
},
menuButton: {
marginRight: theme.spacing(2)
},
title: {
flexGrow: 1,
textAlign: "center"
},
logo: {
maxWidth: 40,
marginRight: '10px'
}
})
);
Here is my component code:
export function ButtonAppBar() {
const classes = useStyles();
return (
<div className={classes.root}>
<AppBar position="static">
<Toolbar>
<IconButton
edge="start"
className={classes.menuButton}
color="inherit"
aria-label="menu"
>
<MenuIcon />
</IconButton>
<img src={logo} alt="Kitty Katty!" className={classes.logo} />
<Typography variant="h6" className={classes.title}>
Kitty Katty!
</Typography>
<Button color="inherit">Login</Button>
</Toolbar>
</AppBar>
</div>
);
}
Thanks very much for the help!
Try this:
<Typography variant="h6" className={classes.title}>
<img src={logo} alt="Kitty Katty!" className={classes.logo} />
Kitty Katty!
</Typography>
import React from "react";
import { createStyles, makeStyles, Theme } from "#material-ui/core/styles";
import AppBar from "#material-ui/core/AppBar";
import Toolbar from "#material-ui/core/Toolbar";
import Typography from "#material-ui/core/Typography";
import Button from "#material-ui/core/Button";
import IconButton from "#material-ui/core/IconButton";
import MenuIcon from "#material-ui/icons/Menu";
import logo from "./images/logo.png";
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
flexGrow: 1
},
menuButton: {
marginRight: theme.spacing(2)
},
toolbar:{
justifyContent:'space-between'
},
container:{
display:'flex',
alignItems:'center',
},
title: {
flexGrow: 1,
textAlign: "center"
},
logo: {
maxWidth: 40,
marginRight: '10px'
}
})
);
export function ButtonAppBar() {
const classes = useStyles();
return (
<div className={classes.root}>
<AppBar position="static">
<Toolbar classes={{root:classes.toolbar}}>
<IconButton
edge="start"
className={classes.menuButton}
color="inherit"
aria-label="menu"
>
<MenuIcon />
</IconButton>
<div className={classes.container}>
<img src={logo} alt="Kitty Katty!" className={classes.logo} />
<Typography variant="h6" className={classes.title}>
Kitty Katty!
</Typography>
</div>
<Button color="inherit">Login</Button>
</Toolbar>
</AppBar>
</div>
);
}
<div className={classes.root}>
<AppBar position="static">
<Toolbar>
<IconButton
edge="start"
className={classes.menuButton}
color="inherit"
aria-label="menu"
>
<MenuIcon />
</IconButton>
<Typography variant="h6" className={classes.title} id="appBar">
<img src={logo} alt="Kitty Katty!" className={classes.logo} />
Kitty Katty!
</Typography>
<Button color="inherit">Login</Button>
</Toolbar>
</AppBar>
</div>
Then in your style.css add this
#appBar {
display: flex;
justify-content: center;
align-items: center;
}

Not able to reduce the size of image in Material UI CardMedia in a React component

I´m just not able to an image's heigh and width changed in Material-UI's CardMedia image: Below is my code.
<Grid
container
spacing={36}
direction="column"
alignItems="center"
justify="center"
style={{
minHeight: "100vh",
backgroundImage: `url(${Image})`,
height: "100%",
backgroundPosition: "center",
backgroundRepeat: "norepeat",
backgroundSize: "cover"
}}
>
<Paper style={{ height: "740px", width: "500px" }}>
<Card className={classes.card}>
<CardActionArea>
<CardMedia
style={{
height: "40px",
marginLeft: "113px",
paddingLeft: "56.25%",
paddingTop: "56.25%", // 16:9,
marginTop: "20px",
width: "30px"
}}
image={require("../../../Images/ApLogo/111.jpg")}
title="Login"
/>
<CardTitle
title="Log In"
style={{
marginLeft: "220px",
marginTop: "10px",
fontWeight: "bold"
}}
/>
<CardContent>
......
</CardContent>
</CardActionArea>
</Card>
</Paper>
</Grid>
I have looked throuh this and this. But none of which resolved my problem.
You can skip CardMedia and write div with background or use image tag yourself inside CardActionArea.
Or correct your CardMedia props as here
Because CardMedia do not accept style prop
`<CardMedia
component="img"
alt="Contemplative Reptile"
className={classes.media}
height="140"
image="/static/images/cards/contemplative-reptile.jpg"
title="Contemplative Reptile"
/>`
You can apply your styles with className props. Here is an example:
const { withStyles, Card, CardHeader, CardMedia, CardContent, Typography} = window['material-ui'];
const styles = theme => ({
card: {
maxWidth: 400,
},
media: { // this is the`className` passed to `CardMedia` later
height: 100, // as an example I am modifying width and height
width: '33%',
marginLeft: '33%'
},
});
class Demo extends React.Component {
render() {
const { classes } = this.props;
return (
<Card className={classes.card}>
<CardHeader
title="Shrimp and Chorizo Paella"
subheader="September 14, 2016"
/>
<CardMedia
className={classes.media}
image="https://picsum.photos/800/450"
title="Paella dish"
/>
<CardContent>
<Typography component="p">
This impressive paella is a perfect party dish and a fun meal to cook together with your
guests. Add 1 cup of frozen peas along with the mussels, if you like.
</Typography>
</CardContent>
</Card>
);
}
}
const App = withStyles(styles)(Demo);
ReactDOM.render(<App />, document.querySelector('#root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/#material-ui/core#3.9.2/umd/material-ui.production.min.js"></script>
<div id="root"></div>

Resources