How refacto css class to material-ui class - css

Hi everyone 😌
I'm using material-UI for a project and i have try to use popover for display metadata of a document but the problem with MUI popover is that they put a z-index of 1500 and block all event like mouseEnter/mouseLeave but I have buttons and collapse on this div my user should be able to use for navigate or display an another infos so after hours to trying to tweak the comportement of the MUI popover I have think about to do it with a pure css component.
For this I have go grab old css from a another project and I'm stuck to pass it into the way MUI accept selector.
My problem is that I don't see how pass this:
.popover__wrapper {
position: relative;
}
.popover__content {
opacity: 0;
visibility: hidden;
position: absolute;
left: -100px;
transform: translate(0, 10px);
background-color: #bfbfbf;
padding: 1.5rem;
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
width: auto;
text-align: center;
}
.popover__content:before {
position: absolute;
z-index: -1;
content: "";
right: calc(50% - 10px);
top: -8px;
border-style: solid;
border-width: 0 10px 10px 10px;
border-color: transparent transparent #bfbfbf transparent;
transition-duration: 0.3s;
transition-property: transform;
}
.popover__wrapper:hover .popover__content {
z-index: 10;
opacity: 1;
visibility: visible;
transform: translate(0, -20px);
transition: all 0.5s cubic-bezier(0.75, -0.02, 0.2, 0.97);
}
into a MUI css if i can call this like that:
popover__content: {
opacity: 0,
visibility: "hidden",
position: "absolute",
left: "-150px",
transform: "translate(0, 10px)",
width: "100%",
"&:before": {
position: "absolute",
zIndex: "-1",
right: "calc(50% - 10px)",
transitionDuration: "0.3s",
transitionProperty: "transform",
},
"&:hover": {
zIndex: "10",
opacity: "1",
visibility: "visible",
transform: "translate(0, -20px)",
transition: " all 0.5s cubic-bezier(0.75, -0.02, 0.2, 0.97)",
},
},
I have check the MUI theming doc but my brain still stuck on this ..
Thanks by advance for your help have a great day all !

I fix the popover problem with this css and hooks this let me create the behaviors wanted to the DOM :
import React, { useState } from "react"
import { useSelector } from "react-redux"
import {
Grid, List, ListItem, Paper, Typography,
Divider, makeStyles, ListItemIcon,
ListItemText, Box,
} from "#material-ui/core"
import DescriptionIcon from "#material-ui/icons/Description"
const useStyles = makeStyles((theme) => ({
container: {
padding: theme.spacing(1),
borderRadius: theme.spacing(1.5),
background: "#FFFFFF",
boxShadow: "2px 2px 4px rgba(0, 0, 0, 0.0449219)",
},
title: {
color: "#4873c5",
},
paragraph: {
color: "#818181",
},
popover: {
zIndex: 2,
position: "absolute",
top: theme.spacing(-1),
left: theme.spacing(-24),
},
arrowRight: {
width: 0,
height: 0,
borderTop: "10px solid transparent",
borderBottom: "10px solid transparent",
borderLeft: "10px solid black",
position: "absolute",
right: theme.spacing(-1),
top: theme.spacing(2),
},
}))
const stages = [{ name: "Drafting", docs: 15 }, { name: "To Execute", docs: 5 }, { name: "Signature", docs: 10 }]
const tags = [{ name: "HR", docs: 10 }, { name: "Sales", docs: 4 }, { name: "Fundraising", docs: 1 }]
export default function ActiveDocuments() {
const classes = useStyles()
const documents = useSelector(state => state.documents)
const [popoverDetails, setPopoverDetails] = useState(null)
const onMouseLeaveDetails = (e) => {
if (e.relatedTarget.id === "activeDocumentsContainer")
return
setPopoverDetails(null)
}
// in case moving precisely on the diagonal of arrow
const hoverProtection = () => {
if (popoverDetails)
setPopoverDetails(null)
}
return (
<>
<Paper style={{ padding: 16 }} onMouseEnter={hoverProtection} id="activeDocumentsContainer">
<Box display="flex">
<Typography style={{ fontWeight: "bold", flexGrow: 1 }}>Active Documents</Typography>
<Typography>{documents.length}</Typography>
</Box>
<List id="testlist">
{stages.map((stage, idx) => (
<ListItem disableGutters key={idx}>
<div onMouseOver={() => setPopoverDetails(stage.name)}
onMouseLeave={onMouseLeaveDetails}>
<Typography className={classes.title}>
{stage.name}
</Typography>
{popoverDetails === stage.name && (
<Paper className={classes.popover} onMouseLeave={() => setPopoverDetails(null)}>
<div className={classes.arrowRight} />
<List>
{tags.map((tag, idx) => (
<ListItem key={idx}>
<Typography className={classes.title}>{tag.name}</Typography>
</ListItem>
))}
</List>
<Box>
<Typography style={{ fontWeight: "bold" }}>Latest Documents</Typography>
<List>
{documents.map((document, idx) => (
<ListItem key={idx}>
<ListItemIcon style={{ color: "#4873c5" }}>
<DescriptionIcon />
</ListItemIcon>
<ListItemText className={classes.title}>{document.filename}</ListItemText>
</ListItem>
))}
</List>
</Box>
</Paper>
)}
</div>
</ListItem>
))}
</List>
</Paper>
<List>
<ListItem>
<Grid container>
<Grid item xs={12} sm={12} md={12} lg={12} xl={12}>
<Typography className={classes.title}>Template</Typography>
</Grid>
<Grid item xs={12} sm={12} md={12} lg={12} xl={12}>
<Typography className={classes.paragraph} variant="body2">5 new this week</Typography>
</Grid>
</Grid>
</ListItem>
<Divider varient="fullWidth" style={{ backgroundColor: "#dcdee1" }} />
<ListItem>
<Grid container>
<Grid item xs={12} sm={12} md={12} lg={12} xl={12}>
<Typography className={classes.title}>Signed</Typography>
</Grid>
<Grid item xs={12} sm={12} md={12} lg={12} xl={12}>
<Typography className={classes.paragraph} variant="body2">8 new this week</Typography>
</Grid>
</Grid>
</ListItem>
</List>
</>
)
}
I gonna open an issue on MUI github repo for ask them to fix this annoying behavior in the popover component.

Related

Image 3D Hover Effect

I discovered this nice 3D Hover Image Effect - https://codepen.io/kw7oe/pen/mPeepv
With the help of tutorials and guides I know I can style a component with Materials UI and apply it this way the CSS what I do. In the example link the Image is declared as background in CSS. I did it not in CSS but with the MUI Image tag. However it does not throw errors but its not working at all and I am unsure as why.
For the information I build it in React TS.
import React from 'react';
import { Box, Typography } from '#mui/material';
import Image from 'mui-image';
const styles = {
body: {
background: '#ECECEC',
},
footer: {
width: '50%',
marginLeft: '25%',
textAlign: 'center',
fontFamily: 'Julius Sans One, sans-serif',
marginTop: '24px',
},
container: {
maxWidth: '720px',
margin: '24px auto 48px auto',
},
h1: {
fontFamily: 'Montserrat, sans-serif',
textTransform: 'uppercase',
},
h2: {
fontFamily: 'Julius Sans One, sans-serif',
fontSize: '2.5rem',
},
row: {
marginTop: '12px',
},
column: {
display: 'inlin-block',
textAlign: 'center',
},
figure: {
overflow: 'hidden',
},
'a:hover': {
textDecoration: 'none',
},
'column img': {
display: 'block',
width: '100%',
height: '300px',
},
tdimension: {
width: '300px',
height: '300px',
margin: '20px auto 40px auto',
perspective: '1000px',
},
'tdimension a ': {
display: 'block',
width: '100%',
height: '100%',
backgroundSize: 'cover',
transformStyle: 'preserve-3d',
transform: 'rotateX(70deg)',
transition: 'all 0.8s',
},
'tdimension:hover a': {
transform: 'rotateX(20deg)',
},
'tdimension a:after': {
content: '',
position: 'absolute',
left: 0,
bottom: 0,
width: '100%',
height: '40px',
background: 'linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.1))',
transform: 'rotateX(90deg)',
transformOrigin: 'bottom',
},
};
function Hover() {
return (
<Box style={styles.container}>
<Box style={styles.row}>
<Typography style={styles.h1}>Image Hover Effect</Typography> <Typography style={styles.h2}>3D Hover Effect</Typography>
</Box>
<Box style={styles.row}>
<Box style={styles.tdimension}>
<Image src="https://mir-s3-cdn-cf.behance.net/project_modules/disp/e8346826957515.56361c2106f3f.png" style={styles['tdimension a ']}/>
</Box>
</Box>
</Box>
);
}
export { Hover };
I would replace all style attributes with sx since MUI encourages the usage of sx prop and prefers it over style attribute:
https://mui.com/system/the-sx-prop/
I would also stick to the background url inside the <a/> since the 3D Hover Effect transformations are being applied to that tag.
return (
<Box sx={styles.container}>
<Box sx={styles.row}>
<Typography sx={styles.h1}>Image Hover Effect</Typography>
<Typography sx={styles.h2}>3D Hover Effect</Typography>
</Box>
<Box sx={styles.row}>
<Box sx={styles.tdimension}>
</Box>
<Divider sx={{ padding: "1px" }} />
</Box>
</Box>
);
Now inside your styles object wrap everything related to tdimension inside a nested styling object. Your <Box/> makes use of styles.tdimension and this way all your substyling won't get lost.
...
tdimension: {
width: "300px",
height: "300px",
margin: "20px auto 40px auto",
perspective: "1000px",
a: {
background:
'url("https://mir-s3-cdn-cf.behance.net/project_modules/disp/e8346826957515.56361c2106f3f.png")',
display: "block",
width: "100%",
height: "100%",
backgroundSize: "cover",
transformStyle: "preserve-3d",
transform: "rotateX(70deg)",
transition: "all 0.8s",
},
"&:hover a": {
transform: "rotateX(20deg)",
},
"a:after": {
content: '""',
position: "absolute",
left: 0,
bottom: 0,
width: "100%",
height: "40px",
background: "linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.1))",
transform: "rotateX(90deg)",
transformOrigin: "bottom",
},
},
The result should be pretty identical to the codepen now.

Material UI Advanced Button - Text Alignment for Small Screensizes

React / Material-UI Novice here. I am trying to configure a set of buttons inside my app Bar that have a background picture to make it look a little cleaner. I have used a lot of code from examples online (shock) and got it to a place where i am happy with how it has formatted on a full size view (md++). However, when i downsize it to a small breakpoint though, the button image then stack instead (which is what i want) but i lose my text to the left. I have tried shifting to the right in many different ways but i dont think thats the right way to do it, is there something i am missing in making the text flex, i want the text to be in the middle?
import React from 'react'
import { AppBar, Toolbar } from "#mui/material";
import { makeStyles } from '#mui/styles'
import Button from '#mui/material/Button'
import Stack from '#mui/material/Stack'
import ButtonBase from '#mui/material/ButtonBase';
import { styled } from '#mui/material/styles';
import Typography from '#mui/material/Typography';
import Box from '#mui/material/Box';
const useStyles = makeStyles(theme => ({
button: {
...theme.typography.mainmenu,
borderRadius: "40px",
marginLeft: "1px",
height: "45px",
"&:hover": {
backgroundColor: theme.palette.secondary
}
},
}))
const images = [
{
url: '/assets/breakfastMenu.jpg',
title: 'Breakfast',
width: '33.33%',
},
{
url: '/assets/steak.jpg',
title: 'Mains',
width: '33.33%',
},
{
url: '/assets/desserts.jpg',
title: 'Desserts',
width: '33.33%',
},
];
const Image = styled('span')(({ theme }) => ({
position: 'absolute',
left: 0,
right: 0,
top: 0,
bottom: 0,
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
color: theme.palette.common.primary,
}));
const ImageButton = styled(ButtonBase)(({ theme }) => ({
position: 'relative',
height: 150,
[theme.breakpoints.down('sm')]: {
width: '100% !important', // Overrides inline-style
height: 100,
},
'&:hover, &.Mui-focusVisible': {
zIndex: 1,
'& .MuiImageBackdrop-root': {
opacity: 0.15,
},
'& .MuiImageMarked-root': {
opacity: 0,
},
'& .MuiTypography-root': {
border: '4px solid currentColor',
},
},
}));
const ImageSrc = styled('span')({
position: 'absolute',
left: 0,
right: 0,
top: 0,
bottom: 0,
backgroundSize: 'cover',
backgroundPosition: 'center 40%',
});
const ImageBackdrop = styled('span')(({ theme }) => ({
position: 'absolute',
left: 0,
right: 0,
top: 0,
bottom: 0,
backgroundColor: theme.palette.common.black,
opacity: 0.4,
transition: theme.transitions.create('opacity'),
}));
const ImageMarked = styled('span')(({ theme }) => ({
height: 3,
width: 18,
backgroundColor: theme.palette.common.white,
position: 'absolute',
bottom: -2,
left: 'calc(50% - 9px)',
transition: theme.transitions.create('opacity'),
}));
const Header = () => {
const classes = useStyles();
return (<React.Fragment><AppBar position="sticky" className={classes.appBar}>
<Toolbar disableGutters className={classes.mainToolbar} sx={{ justifyContent: "center" }}>
<Stack direction="row" justifyContent="space-between" alignItems="center" spacing={10}>
{/* <Button variant="contained" color="secondary" className={classes.button}>Breakfast</Button>
<Button variant="contained" color="secondary" className={classes.button}>Mains</Button>
<Button variant="contained" color="secondary" className={classes.button}>Desserts</Button> */}
<Box sx={{ display: 'flex', flexWrap: 'wrap', minWidth: 900, width: '100%' }}>
{images.map((image) => (
<ImageButton
focusRipple
key={image.title}
style={{
width: image.width,
}}
>
<ImageSrc style={{
backgroundImage: `url(${image.url})`
}} />
<ImageBackdrop className="MuiImageBackdrop-root" />
<Image>
<Typography
component="span"
variant="subtitle1"
color="white"
fontWeight="bold"
sx={{
position: 'relative',
p: "7em",
pt: "2em",
pb: (theme) => `calc(${theme.spacing(1)} + 6px)`,
}}
>
{image.title}
<ImageMarked className="MuiImageMarked-root" />
</Typography>
</Image>
</ImageButton>
))}
</Box>
</Stack>
</Toolbar>
</AppBar>
</React.Fragment >
)
}
export default Header
I have moved on from this, but in case anybody finds it, using MUI i completely adapted my application by using:
import useMediaQuery from '#mui/material/useMediaQuery'
and some example like:
const matches = useMediaQuery(theme.breakpoints.down("md"))
to control when the application changes its styles

How can I scroll on my Page when my Dialog Component has been opened

I want to scroll on the background, when my dialog component opens up. By default, you cannot scroll when the dialog appears. How can I scroll in the background ?
Following is the Code:-
import React, { useState } from 'react';
import {
makeStyles,
Grid,
Button,
Dialog,
DialogActions,
DialogTitle,
} from '#material-ui/core';
import ShoppingCartIcon from '#material-ui/icons/ShoppingCart';
import CloseIcon from '#material-ui/icons/Close';
const styles = makeStyles((theme) => ({
root: {
position: 'fixed',
bottom: '0 ',
left: '0',
right: '0',
boxShadow: '0 0 6px rgb(0 0 0 / 70%)',
backgroundColor: 'white',
height: '63px',
},
textStyle: {
fontFamily: 'Comfortaa',
},
icon: {
color: theme.palette.primary.dark,
},
btn: {
backgroundColor: theme.palette.primary.dark,
color: 'white',
fontFamily: 'Comfortaa',
'&:hover': {
backgroundColor: theme.palette.primary.dark,
},
},
title: {
display: 'flex',
justifyContent: 'flex-end',
borderBottom: '1px solid #e5e5e5',
},
closeIcon: {
color: theme.palette.primary.light,
'&:hover': {
color: 'black',
},
},
dialogStyle: {
backgroundColor: 'white',
position: 'absolute',
top: 0,
},
dialogContainer: {
opacity: 0,
},
dialogTitle: {
display: 'flex',
justifyContent: 'flex-end',
borderBottom: '1px solid #e5e5e5',
},
}));
const CartAppBar: React.FC = () => {
const classes = styles();
const [open, setOpen] = useState(false);
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<>
<Grid
item
container
direction='row'
justify='space-around'
alignItems='center'
className={classes.root}
xs={12}
>
<div>
<ShoppingCartIcon
fontSize='large'
classes={{ root: classes.icon }}
onClick={handleClickOpen}
/>
</div>
<div>
<Button
className={classes.btn}
type='submit'
onClick={() => {
return (window.location.href = '/checkout');
}}
>
Checkout
</Button>
</div>
</Grid>
<Dialog
open={open}
onClose={handleClose}
aria-labelledby='alert-dialog-title'
aria-describedby='alert-dialog-description'
maxWidth='md'
fullWidth
classes={{
paper: classes.dialogStyle,
container: classes.dialogContainer,
}}
scroll='paper'
>
<DialogTitle className={classes.dialogTitle}>
<CloseIcon
onClick={handleClose}
classes={{ root: classes.closeIcon }}
/>
</DialogTitle>
{/* Footer */}
{/* <DialogActions className={classes.footer}>
<Button classes={{ root: classes.btn }}>Add To Cart</Button>
</DialogActions> */}
</Dialog>
</>
);
};
export default CartAppBar;
As you can see in the photo, there's opacity in the background and you cannot scroll. I want to override this and make the background scrollable
use disableScrollLock as prop will help

React material ui appbar made responsive

I am trying to use material ui's appbar and code in some custom responsiveness to it. I am creating a personal project that will be accessed from a Galaxy s8 smartphone. Ultimately I would like the nav-links and logout button on the navbar to consolidate into a hamburger button when the viewport is small. I am not quite sure how to achieve this however as I am using flexbox on the webpage when it is at full size and it keeps messing me up.
Here is the appbar at full size:
Here is the appbar at phone size with the hamburger button:
Here is the desired effect I would like with items, posts, groups, and the log out button being pushed to an accordion like menu on mobile:
Here is my navbar component code:
import { withStyles } from "#material-ui/core/styles";
import styles from "./styles/NavBarStyles";
import { LoggedInContext } from "./contexts/LoggedIn";
import { ThemeContext } from "./contexts/ThemeContext";
function Navbar(props) {
const { isDarkMode, toggleTheme } = useContext(ThemeContext);
const { loggedIn, changeLogIn, token, setToken } = useContext(
LoggedInContext
);
const { classes } = props;
const [mobileHamburgerOpen, setMobileHamburger] = useState(false);
const handleMobileClick = () => {
setMobileHamburger(!mobileHamburgerOpen);
console.log(mobileHamburgerOpen);
};
return (
<div className={classes.root}>
<AppBar
position="static"
style={{ background: isDarkMode ? "#2E3B55" : "#715AFF" }}
>
<Toolbar>
<Typography className={classes.title} variant="h6" color="inherit">
{isDarkMode ? "🌚" : "🌞"}
</Typography>
<Switch onChange={toggleTheme} />
<div className={classes.grow} />
{loggedIn && (
<div className={classes.loggedIn}>
<div className={classes.navlinks}>
<NavLink
to="/items"
activeStyle={{ background: "rgba(0, 0, 0, 0.5)" }}
>
Items
</NavLink>
<NavLink
to="/facebookitems"
activeStyle={{ background: "rgba(0, 0, 0, 0.5)" }}
>
<i className="fab fa-facebook-square"></i> Posts
</NavLink>
<NavLink
to="/groups"
activeStyle={{ background: "rgba(0, 0, 0, 0.5)" }}
>
<i className="fab fa-facebook-square"></i> Groups
</NavLink>
</div>
<Button
className={classes.logOutButton}
variant="contained"
color="secondary"
onClick={handleClick}
>
Log Out
</Button>
<Button
className={classes.hamburgerMenu}
variant="contained"
color="primary"
onClick={handleMobileClick}
>
<i className="fas fa-bars"></i>
</Button>
</div>
)}
</Toolbar>
</AppBar>
</div>
);
}
export default withStyles(styles)(Navbar);
Here is my style sheet code:
import { fade } from "#material-ui/core/styles/colorManipulator";
const styles = theme => ({
root: {
width: "100%",
marginBottom: 0
},
grow: {
flexGrow: 1
},
menuButton: {
marginLeft: -12,
marginRight: 20
},
title: {
display: 'block'
},
search: {
position: "relative",
borderRadius: theme.shape.borderRadius,
backgroundColor: fade(theme.palette.common.white, 0.15),
"&:hover": {
backgroundColor: fade(theme.palette.common.white, 0.25)
},
marginLeft: 0,
width: "100%",
[theme.breakpoints.up("sm")]: {
marginLeft: theme.spacing(1),
width: "auto"
}
},
searchIcon: {
width: theme.spacing(9),
height: "100%",
position: "absolute",
display: "flex",
alignItems: "center",
justifyContent: "center"
},
inputRoot: {
color: "inherit",
width: "100%"
},
inputInput: {
paddingTop: theme.spacing(1),
paddingRight: theme.spacing(1),
paddingBottom: theme.spacing(1),
paddingLeft: theme.spacing(10),
transition: theme.transitions.create("width"),
width: "100%",
[theme.breakpoints.up("sm")]: {
width: 120,
"&:focus": {
width: 200
}
}
},
loggedIn: {
width: "100%",
display: "flex",
justifyContent: "space-between",
alignItems: "center",
paddingLeft: "2rem"
},
navlinks: {
// [theme.breakpoints.down("sm")]: {
// position: 'absolute',
// backgroundColor: "rgba(0,0,0,.7)",
// top: '0%',
// right: '0%',
// width: '100vw',
// height: '100vh'
// },
"& a": {
color: "white",
fontWeight: "bold",
fontSize: "1.5rem",
textDecoration: "none",
marginRight: '1rem',
padding: ".5rem",
borderRadius: "15px"
},
"& a:active": {
backgroundColor: "rgba(0, 0, 0, 0.5)"
}
},
hamburgerMenu: {
display: 'none',
[theme.breakpoints.down("sm")]: {
display: 'block',
marginLeft: "auto",
backgroundColor: "white",
color: "#715AFF"
}
},
logOutButton: {
// [theme.breakpoints.down("sm")]: {
// display: 'none'
// }
}
});
export default styles;

Toggle button / decrease width grid and div Semantic React

I have a menu that will have a size and when you click the button it will decrease the width to 50px
ie I will have a menu with button and icons and when clicking the button will appear only the icon
but i'm having a hard time how do i decrease the width of my div and how would it work on the semantic grid
code:
function Menu() {
const [open, setOpen] = useState(true); // declare new state variable "open" with setter
const handleClick = e => {
e.preventDefault();
setOpen(!open);
};
return (
<Grid style={{background: '#eee'}}>
<Grid.Column computer={2} tablet={4} mobile={5} style={{background: '#000', padding:'0', height:'100vh'}}>
<div style={{background:'#000', width:'100%', height:'100%'}}>
</div>
</Grid.Column>
<Grid.Column width={14} style={{background: '#eee', padding:'0'}}>
<Button icon onClick={handleClick}>
<Icon name="align justify" />
</Button>
</Grid.Column>
</Grid>
);
}
css:
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
#root,
.App,
.ui.grid{
height: 100vh !important;
margin: 0 !important;
padding:0 !important;
}
code: https://codesandbox.io/s/cool-kepler-cxj4x
You can decrease the width of div when state of open being change on button click, please review demo link
App.js
import React, { useState } from "react";
import { Grid, Button, Icon } from "semantic-ui-react";
import "./style.css";
function Menu() {
const [open, setOpen] = useState(true); // declare new state variable "open" with setter
const handleClick = e => {
e.preventDefault();
setOpen(!open);
};
return (
<Grid style={{ background: "#eee" }}>
<Grid.Column
computer={2}
tablet={4}
mobile={5}
style={{
background: "#000",
padding: "0",
height: "100vh"
}}
>
<div
style={{
background: "red",
width: open ? "100%" : "calc(100% - 50px)",
height: "100vh"
}}
/>
</Grid.Column>
<Grid.Column
computer={14}
tablet={12}
mobile={11}
style={{ background: "#eee", padding: "0" }}
>
<Button icon onClick={handleClick}>
<Icon name="align justify" />
</Button>
</Grid.Column>
</Grid>
);
}
export default Menu;

Resources