Reputation: 213
When the user hovers over a Card
component, I'd like to show a button on that component that is otherwise invisible. In CSS, I'd do something like this:
.card:hover my-button {
display: block;
}
How do I replicate this in the "Material-UI" way?
All the Material-UI tips I found so far suggest something like this to add hover styling, but this applies the styles to the component that is being hovered over and not a different one.
'&:hover': {
background: 'blue'
}
Upvotes: 12
Views: 21818
Reputation: 76
I faced this problem today and after I discussed it with my mentor I made this result and it worked well for me. but first, let me tell you the disadvantage of using eventListener like onMouseEnter & on MouseLeave that it will cause so many renders.
I gave the (parent component) a movie-card class and the (child component) a movie-card-content class like the following
// movie-card.css
.movie-card-content {
opacity: 0;
}
.movie-card:hover .movie-card-content {
opacity: 1;
}
MUI allows you to add className prop so I gave the proper classNames
//MovieCard.jsx (component)
import "./movie-card.css";
function MovieCard () {
return (
<Card className="movie-card">
<CardContent className="movie-card-content">...<CardContent>
</Card>
);
}
and that's it 😉
Upvotes: 3
Reputation: 3467
If you want to define this purely inside of a styled component instead of using either of createMuiTheme
or makeStyles
, then try the following.
We will give an id to each child component and reference them when defining the behaviour to implement when we hover over the parent component:
const NameCellBox = styled(Box)(({ theme }) => ({
...other styles,
"&:hover #cellBoxLengthTypo": {
display: "none",
},
"&:hover #cellBoxContentTypo": {
display: "inline-block",
},
}));
const CellBoxLengthTypo = styled(Typography)(({ theme }) => ({
fontFamily: theme.typography.fontFamily,
fontSize: theme.typography.h5.fontSize,
}));
const CellBoxContentTypo = styled(Typography)(({ theme }) => ({
display: "none",
fontFamily: theme.typography.fontFamily,
fontSize: theme.typography.h5.fontSize,
}));
const items: string[] = ["andrew", "barry", "chris", "debbie"];
return (
<>
<NameCellBox>
<CellBoxLengthTypo id="cellBoxLengthTypo">+{items.length}</CellBoxLengthTypo>
<CellBoxContentTypo id="cellBoxContentTypo">{items.join(", ")}</CellBoxContentTypo>
</NameCellBox>
</>
);
Found it useful for updating a DataGrid cell in Material UI when hover or other event fired.
Upvotes: 1
Reputation: 11
This is a material UI example that displays the sub-element on hover of the parent. I also noticed that using some of the examples above, when using Material UI's makeStyles, the overlay item was flickering a lot when clicked. This solution below does not flicker when sub-element is clicked.
import React from "react"
import { Card, CardActionArea, CardContent, CardMedia } from "@material-
ui/core";
import { makeStyles } from "@material-ui/core/styles";
const useStyles = makeStyles(theme => ({
card: {
// some styles
},
cardAction: {
position: "relative"
},
media: {
// some styles
},
overlay: {
position: "absolute",
top: "85px"
}
}));
const App = () => {
const classes = useStyles();
const [show, setShow] = React.useState(false);
const handleMouseOver = () => {
setShow(true);
};
const handleMouseOut = () => {
setShow(false);
};
return (
<Card>
<CardActionArea
onMouseOver={handleMouseOver}
onMouseOut={handleMouseOut} className={classes.card} >
<CardMedia className={classes.media} component="img" >
// some content
</CardMedia>
<CardContent className={classes.overlay} style={{ display: show ?
'block' : 'none' }>
// some content
</CardContent>
</CardActionArea>
</Card>
);
}
Upvotes: 1
Reputation: 21
import {
makeStyles
} from '@material-ui/core'
const useStyles = makeStyles(() => ({
root: {
"& .appear-item": {
display: "none"
},
"&:hover .appear-item": {
display: "block"
}
}
}))
export default function MakeTextAppearOnHover() {
const classes = useStyles()
return (
<div className = { classes.root }>
Hello world
<span className = 'appear-item' >
Appearing text Go
</span>
</div>
)
}
Upvotes: 2
Reputation: 62676
You can do the exact same thing with CSS using the createMuiTheme:
export const theme = createMuiTheme({
overrides: {
// For label
MuiCard: {
root: {
"& .hidden-button": {
display: "none"
},
"&:hover .hidden-button": {
display: "flex"
}
}
}
}
});
Give the Button
inside your Card
the className hidden-button
and you will get the same thing that you want.
Check it here: https://codesandbox.io/s/mui-theme-css-hover-example-n8ou5
Upvotes: 13
Reputation: 22935
It is not specific to Material UI but a react specific thing. you need a state variable to show/hide your button.
const App = () => {
const [show, setShow] = useState(false);
return (
<Card
onMouseOver={() => setShow(true)}
onMouseOut={() => setShow(false)}>
<CardBody>
// some content
{show && <Button>Click</Button>}
</CardBody>
</Card>
);
}
Upvotes: 9