Intersection Observer isVisible variable not changing - javascript

I have set up this Intersection Observer function because I want my divs to slide in from the side as the user scrolls down. However, after much tinkering and small changes, it still is not working. I've tried console-logging "entries", the "isVisible" variable, and "sliderRef". The first two are useless, as I get undefined for isVisible and an empty array for "entries", while I get the first div when I console-log sliderRef, but not the other two divs. I apologize for the vagueness and inability to present a specific reason as to why this isn't working. Any help would be appreciated, or any suggestion for a simpler way to achieve what I'm trying to do. Below is all the relevant code:
Edit: I changed the default value of isVisible to true, to see if the props were even being passed to my styled components, and the div appeared briefly on load but then slid out of view. However, still nothing happens when I have isVisible set to false. My options don't seem to be being taken into account, because the function was triggered regardless of the fact that I had not yet reached the threshold, which is 0.5
import { useRef, useState, useEffect} from 'react'
import styled, { css } from 'styled-components'
import PropTypes from 'prop-types';
import clsx from 'clsx';
import {
Container,
Grid,
Typography,
makeStyles
} from '#material-ui/core';
const useStyles = makeStyles((theme) => ({
root: {
backgroundColor: "white",
height: "200vh",
marginBottom: "200px"
},
contentGrid: {
display: "flex",
height: "33%",
padding: 0,
},
}));
const useElementOnScreen = (options) => {
const sliderRef = useRef(null);
const [isVisible, setIsVisible] = useState(false);
const callBackFunction = (entries) => {
const [entry] = entries;
setIsVisible(entry.IsIntersecting);
console.log(entries);
};
useEffect(() => {
const observer = new IntersectionObserver(callBackFunction, options);
if (sliderRef.current) observer.observe(sliderRef.current);
return () => {
if (sliderRef.current) observer.unobserve(sliderRef.current);
};
}, [sliderRef, options]);
return [sliderRef, isVisible];
}
function Features({ className, ...rest }) {
const classes = useStyles();
const [sliderRef, isVisible] = useElementOnScreen({
root: null,
threshold: 0.5,
rootMargin: "0px 0px -100px 0px"
})
return (
<div
className={clsx(classes.root, className)}
{...rest}
>
{/* <Container maxWidth="lg" style={{padding: 0, width: "100%"}}> */}
<Grid className={classes.contentGrid} style={{backgroundColor: "#025373"}}>
<SliderFromLeft visible={isVisible}
ref={sliderRef}
style={{backgroundColor: "#F2D680"}}
>
<Typography
variant="h4">
Increased complexity has enabled media agencies
to create opaque financial structures
and then inflate their fees and
media prices at will, while many
advertisers are stuck behind contracts
unfit for modern media buying that
provide little scope for transparency and accountability.
</Typography>
</SliderFromLeft>
<NonSlider style={{alignItems: "center", paddingRight:"75px"}}>
<Typography
variant="h1"
align="right"
style={{color:"#F2C230", fontSize:"4rem"}}
>
Are you getting the most out of your contract?
</Typography>
</NonSlider>
</Grid>
<Grid className={classes.contentGrid} style={{backgroundColor: "#D0E5F2"}}>
<NonSlider style={{backgroundColor: "#D0E5F2"}}>
<Typography
variant="h1"
style={{color: "#025373", fontSize:"4rem"}}
>
The <br/>Challenge
</Typography>
</NonSlider>
<SliderFromRight visible={isVisible}
style={{backgroundColor: "#75B8BF"}}
>
<Typography
variant="h4"
style={{color:"#025373"}}>
We want you to get the same benefits that the top global advertisers enjoy.
The core of a successful relationship between you and your media agency is a well thought-out contract.
<br/>
<br/>
You must ensure that your media agency contract provides clarity and accountability,
and contains competitive terms and conditions.
</Typography>
</SliderFromRight>
</Grid>
<Grid className={classes.contentGrid} style={{backgroundColor: "#F2D680"}}>
<SliderFromLeft visible={isVisible}
style={{backgroundColor:"#F2F2F2"}}
ref={sliderRef}
>
<Typography
variant="h4">
It is known that most media agencies design their own contract templates to benefit
themselves and not you. We believe this needs to change and you need to regain control.
<br/>
<br/>
To assess the quality of your contract, you must first benchmark it against the industry average.
Once you know the the strengths and weaknesses of the contract, it is easier to
know what needs to be improved upon.
</Typography>
</SliderFromLeft>
<NonSlider style={{alignItems: "center", justifyContent:"right", paddingRight: '75px'}}>
<Typography
variant="h1"
align="right"
style={{color:"#025373", fontSize:"4.2rem"}}
>
The <br/> Solution
</Typography>
</NonSlider>
</Grid>
{/* </Container> */}
</div>
);
}
const SliderFromLeft = styled.div`
height: 100%;
width: 50%;
display: flex;
align-items: center;
padding: 0 75px 0 75px;
border-top-right-radius: 30px;
border-bottom-right-radius: 30px;
opacity: 0%;
transform: translateX(-100%);
transition: transform 400ms ease-in, opacity 250ms ease-in;
${props => props.visible && `
transform: translateX(0%);
opacity: 100;`
}
`
const SliderFromRight = styled.div`
height: 100%;
width: 50%;
display: flex;
align-items: center;
padding: 0 75px 0 75px;
border-top-left-radius: 30px;
border-bottom-left-radius: 30px;
opacity: 0;
transform: translateX(100%);
transition: transform 400ms ease-in, opacity 250ms ease-in;
${props => props.visible && `
transform: translateX(0%)
opacity: 100;`
}
`
const NonSlider = styled.div`
height: 100%;
width: 50%;
display: flex;
align-items: center;
padding: 0 75px 0 75px
`
Features.propTypes = {
className: PropTypes.string
};
export default Features;```

For anyone having the same issue, despite reorganizing and improving my code based on updated documentation, I didn't exactly solve my problem, but I did somewhat achieve the effect I was looking for. I'm still not sure what was causing the issue, but I decided to ditch the slide-in effect for a simple fade-in effect by changing the opacity, and that works just fine.
Based on the newer documentation I found and some other answers here on SO, you can just import the useInView hook instead of writing it out yourself, and you must call useInView separately for each component, instead of giving all components the same ref and calling useInView once. I hope this helps.
import { useRef, useState, useEffect} from 'react';
import { useInView } from 'react-intersection-observer';
import styled, { css } from 'styled-components'
import PropTypes from 'prop-types';
import clsx from 'clsx';
import {
Container,
Grid,
Typography,
makeStyles
} from '#material-ui/core';
import Contract from './Media/contract.png'
import Challenge from './Media/challenge.png'
import Presenter from './Media/presenter.png'
const useStyles = makeStyles((theme) => ({
root: {
backgroundColor: "white",
height: "175vh",
},
contentGrid: {
display: "flex",
height: "33%",
padding: 0,
},
header: {
color: "#000000",
fontSize: "2.5rem",
marginBottom: "10px",
},
image: {
height: "355px",
width: "500px",
}
}));
function Features({ className, ...rest }) {
const classes = useStyles();
const { ref: ref1, inView: inView1 } = useInView({ threshold: 0.5 })
const { ref: ref2, inView: inView2 } = useInView({ threshold: 0.5 })
const { ref: ref3, inView: inView3 } = useInView({ threshold: 0.5 })
console.log(inView2);
return (
<div
className={clsx(classes.root, className)}
{...rest}
>
{/* <Container maxWidth="lg" style={{padding: 0, width: "100%"}}> */}
<Grid className={classes.contentGrid}>
<SliderFromLeft
visible={inView1}
ref={ref1}
>
<Typography
variant="h1"
align="left"
className={classes.header}
>
Are you getting the most out of your contract?
</Typography>
<Typography
variant="h4">
Increased complexity has enabled media agencies
to create opaque financial structures
and then inflate their fees and
media prices at will, while many
advertisers are stuck behind contracts
unfit for modern media buying that
provide little scope for transparency and accountability.
</Typography>
</SliderFromLeft>
<NonSlider style={{alignItems: "center", paddingRight:"75px"}}>
<img src={Contract} className={classes.image} />
</NonSlider>
</Grid>
<Grid className={classes.contentGrid}>
<NonSlider>
<img className={classes.image} src={Challenge} />
</NonSlider>
<SliderFromRight
visible={inView2}
ref={ref2}
>
<Typography
variant="h1"
align="right"
className={classes.header}
>
The Challenge
</Typography>
<Typography
variant="h4"
>
We want you to get the same benefits that the top global advertisers enjoy.
The core of a successful relationship between you and your media agency is a well thought-out contract.
<br/>
<br/>
You must ensure that your media agency contract provides clarity and accountability,
and contains competitive terms and conditions.
</Typography>
</SliderFromRight>
</Grid>
<Grid className={classes.contentGrid}>
<SliderFromLeft
visible={inView3}
ref={ref3}
>
<Typography
variant="h1"
align="left"
className={classes.header}
>
The Solution
</Typography>
<Typography
variant="h4">
It is known that most media agencies design their own contract templates to benefit
themselves and not you. We believe this needs to change and you need to regain control.
<br/>
<br/>
To assess the quality of your contract, you must first benchmark it against the industry average.
Once you know the the strengths and weaknesses of the contract, it is easier to
know what needs to be improved upon.
</Typography>
</SliderFromLeft>
<NonSlider style={{alignItems: "center", justifyContent:"right", paddingRight: '75px'}}>
<img src={Presenter} className={classes.image} />
</NonSlider>
</Grid>
{/* </Container> */}
</div>
);
}
const SliderFromLeft = styled.div`
height: 100%;
width: 50%;
// display: flex;
align-items: center;
padding: 75px 75px 0 75px;
border-top-right-radius: 30px;
border-bottom-right-radius: 30px;
opacity: 0;
// transform: translateX(-100%);
transition: transform 400ms ease-in, opacity 0.5s ease-in;
${props => props.visible && `
// transform: translateX(0%);
opacity: 100;`
}
`
const SliderFromRight = styled.div`
height: 100%;
width: 50%;
// display: flex;
align-items: center;
padding: 75px 75px 0 75px;
border-top-left-radius: 30px;
border-bottom-left-radius: 30px;
opacity: 0;
// transform: translateX(100%);
transition: transform 400ms ease-in, opacity 0.5s ease-in;
${props => props.visible && `
// transform: translateX(0%)
opacity: 100;`
}
`
const NonSlider = styled.div`
height: 100%;
width: 50%;
display: flex;
align-items: center;
padding: 0 75px 0 75px
`
Features.propTypes = {
className: PropTypes.string
};
export default Features;```

Related

How to place any button outside the dialog box

I want a close button that needs to work outside the dialog box.
I want this modal where the close button is outside div.
Expected:
Implementation:
const Component = styled(Box)`
display: flex;
height: 528px;
`;
const Image = styled(Box)`
width: 270px;
background: url(https://static-assets-web.flixcart.com/www/linchpin/fk-cp-zion/img/login_img_c4a81e.png)
no-repeat;
color: #fff;
background-color: #2874f0;
background-position: 50% 85%;
padding: 40px 33px;
& > p {
margin-top: 12px;
color: #dbdbdb;
font-size: 18px;
}
`;
const ReqBtn = styled(Button)`
background-color: #fb641b;
text-transform: none;
height: 48px;
width: 305px;
padding: 10px 20px 10px 20px;
`;
const Wrapper = styled(Box)`
padding: 56px 35px 16px 35px;
& > p {
color: #878787;
font-size: 12px;
}
`;
// <--------------------------------------- styled section ends-------------------------------->
const LoginDialog = ({ open, setOpen }) => {
const handleCloseDialog = () => {
setOpen(false);
};
return (
<Dialog
open={open}
onClose={handleCloseDialog}
sx={{
"& .MuiDialog-container": {
"& .MuiPaper-root": {
width: "100%",
maxWidth: "750px",
},
},
}}
>
<Component>
<Image>
{/* <Typography
style={{ fontWeight: "bold", fontSize: "28px", color: "#fff" }}
>
Login
</Typography>
<Typography>
Get access to your Orders, Wishlist and Recommendations
</Typography> */}
</Image>
<Wrapper>
{/* <TextField label="Enter Email/Mobile Number" variant="standard" />
<Typography>
By continuing, you agree to Flipkart's Terms of Use and Privacy
Policy.
</Typography>
<ReqBtn
variant="contained"
sx={{
"&.MuiButtonBase-root:hover": { backgroundColor: "#fb641b" },
}}
>
Request OTP
</ReqBtn>
<Typography>New to Flipkart?Create an Account</Typography> */}
</Wrapper>
//close button
<ClearIcon
onClick={handleCloseDialog}
style={{ cursor: "pointer", backgroundColor: "yellow" }}
/>
</Component>
</Dialog>
);
};
export default LoginDialog;
I tried pasting the <ClearICon> outside <Dialog> component but the issue is the close button came in my navbar position
<>
<ClearIcon
onClick={handleCloseDialog}
style={{ cursor: "pointer", backgroundColor: "yellow" }}
/>
</>
How can I place the CloseIcon outside the dialog box as per provided design?
something like this...
.box{
position:relative;
background:gray;
width:100px;
height:100px;
}
.box>.controls{
position:absolute;
right:-30px;
}
<div class="box">
<div class="controls">
<button>x</button>
</div>
</div>

CSS Slanding Div edges over an Image

I am trying to design a simple report with the format as shown in the following Figma file using React and Material UI. However, I am encountering a challenge when designing the slanting edges of the divs as shown on the report. Plus the purple border. This is what I have done so far, but it is far from being perfect:
const leftDiv = {
content: "",
position: "absolute",
top: "50%",
right: 0,
width: "100%",
height: "50%",
backgroundColor: 'rgb(255, 255, 255)',
clipPath: "polygon(0 0, 0% 0%, 100% 100%, 0% 100%)"
}
const rightDiv = {
position: "absolute",
bottom: 0,
right: 0,
display: 'inline-block',
width: 0,
height: 0,
borderStyle: 'solid',
borderWidth: '0 0 500px 100vw',
borderColor: 'transparent transparent #FFFFFF transparent',
}
const contentDiv = {
backgroundColor: 'rgb(255, 255, 255)',
width: "100%",
height: "100%",
clipPath: "polygon(100% 0, 100% 0%, 100% 100%, 0% 100%)"
}
const Coverpage = () => {
return (
<Container>
<Grid>
<Paper>
<Box sx={{ position: 'relative', width: '100%' }}>
<CardMedia
component='img'
alt="cover page image"
image='https://unsplash.com/photos/vbxyFxlgpjM'
/>
<Box style={leftDiv}></Box>
<Box style={rightDiv}>
<Box style={contentDiv}>
<Box sx={{ width: '100%', height: '100%', display: 'flex', flexDirection: 'column', justifyContent: 'flex-end', alignItems: 'flex-end', textAlign: 'right', pr: 8 }}>
<Typography sx={{ fontSize: '24px', mb: 2 }}>Lorem ipsum</Typography>
<Typography sx={{ fontSize: '48px', fontWeight: 'bold', textTransform: 'uppercase', color: '#000133' }}>Lorem ipsum</Typography>
<Typography sx={{ fontSize: '64px', fontWeight: 'bold', textTransform: 'uppercase', color: 'blue' }}>Lorem ipsum</Typography>
</Box>
</Box>
</Box>
</Box>
</Paper>
</Grid>
</Container>
);
}
export default Coverpage;
I found using clipPath as the easiest, even though I would prefer using triangles to design the slanting edges since later, I am planning to use react-pdf-renderer which I am not sure if it supports clipPath in its CSS styling.
I will appreciate a pointer to the right direction.
Dan touched on the purple border. About the slanted div you can use this trick:
.slanted{
height: 0;
width: 0;
border-top: solid 100px transparent;
border-right: solid 50vw blue;
border-left: solid 50vw blue;
border-bottom: solid 100px blue;
}
You're making a div with no height or width. The borders meet along a diagonal line and so you can have a triangle effect.
You can use an additional div for the text
Edit: making the borders responsive
To make the border trick dynamic you can use some JS:
function App() {
const footerRef = React.useRef()
useEffect(() => {
window.addEventListener('resize', setBorders)
return () => {
window.removeEventListener('resize', setBorders)
}
}, [])
useEffect(() => {
if (!footerRef.current) return
setBorders()
}, [footerRef])
const setBorders = () => {
let containerWidth = document.querySelector('.container').clientWidth
let footerStyle = footerRef.current.style
footerStyle.borderRightWidth = containerWidth/2+'px'
footerStyle.borderLeftWidth = containerWidth/2+'px'
}
return (
<div className='App'>
<div className='container'>
<div className='footer' ref={footerRef}>
</div>
</div>
</div>
);
}
export default App
We are adding a 'resize' eventListener to the window that will trigger the setBorders() function. In this function we select the container element and set the width of the footer borders to be half of it.
To make sure the function also fires on initial load I added a useEffect which will fire when the footer is created and its Ref is set. You can also use a callback ref instead.
The css, I assumed the footer will be static height:
.container{
height: 200px;
width: 100%;
background: red;
}
.footer{
position: relative;
height: 0;
width: 0;
top: calc(100% - 100px);
/*border-top width + border-bottom width = 100px*/
border-top: 50px solid transparent;
border-bottom: 50px solid green;
border-right: solid blue;
border-left: solid blue;
}
If you don't mind making the container position: relative; you can then just do:
.footer{
position: absolute;
bottom: 0;
}
You just need to use a simple CSS transform on the element.
transform: skew(-15deg, -15deg);

How to handle ScrollView inside a Pressable in React-Native? [duplicate]

This question already has answers here:
React-Native, Scroll View Not Scrolling
(13 answers)
Closed 1 year ago.
Right now, I am creating a modal with items inside the modal to scroll. However, I am noticing the touch function is being extremely obscured and not passing through appropriately. With this current implementation, scrolling on the ScrollView is not working. I am just trying to have this scrollview inside the modal, I have set it up so that the modal can be pressable inside and an outside press of the modal will cause it to close. So I need to pass the proper touchable properties down.
Some resources and previous stack overflow pages I was looking at was:
React-Native, Scroll View Not Scrolling
return (
<Container {...props}>
<BottomModal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
setModalVisible(!modalVisible);
}}>
<CenterView onPress={() => setModalVisible(!modalVisible)}>
<ModalContent>
<ModalHeader>
<CloseButtonContainer>
<Pressable onPress={() => setModalVisible(!modalVisible)}>
<CloseButton
name="times-circle"
type={vectorIconTypes.MEDIUM}
/>
</Pressable>
</CloseButtonContainer>
<TitleContainer>
<TitleText>{title}</TitleText>
</TitleContainer>
</ModalHeader>
<ModalList>
<ScrollContainer>
<LeftTextRightCheckBox>
<TitleText>Newest</TitleText>
<CheckBox />
</LeftTextRightCheckBox>
<LeftTextRightCheckBox>
<TitleText>Points High to Low</TitleText>
<CheckBox />
</LeftTextRightCheckBox>
<LeftTextRightCheckBox>
<TitleText>Brands A to Z</TitleText>
<CheckBox />
</LeftTextRightCheckBox>
<LeftTextRightCheckBox>
<TitleText>Brands A to Z</TitleText>
<CheckBox />
</LeftTextRightCheckBox>
<LeftTextRightCheckBox>
<TitleText>Brands A to Z</TitleText>
<CheckBox />
</LeftTextRightCheckBox>
<LeftTextRightCheckBox>
<TitleText>Brands A to Z</TitleText>
<CheckBox />
</LeftTextRightCheckBox>
<LeftTextRightCheckBox>
<TitleText>Brands A to Z</TitleText>
<CheckBox />
</LeftTextRightCheckBox>
<LeftTextRightCheckBox>
<TitleText>Brands A to Z</TitleText>
<CheckBox />
</LeftTextRightCheckBox>
</ScrollContainer>
</ModalList>
</ModalContent>
</CenterView>
</BottomModal>
</Container>
...
const Container = styled.View`
flex-direction: column;
background-color: white;
padding: 10px;
`;
const BottomModal = styled.Modal`
flex-direction: row;
height: 100%;
`;
const CenterView = styled.Pressable`
justify-content: flex-end;
align-items: center;
background-color: rgba(0, 0, 0, 0.3);
height: 100%;
`;
const ModalContent = styled.Pressable`
flex-direction: column;
background-color: white;
width: 100%;
border-top-left-radius: 50px;
border-top-right-radius: 50px;
padding-bottom: 30px;
height: 300px;
`;
const ModalHeader = styled.View`
flex-direction: row;
width: 100%;
padding: 20px;
height: 60px;
`;
const ModalList = styled(ScrollView).attrs(() => ({
contentContainerStyle: {
flexDirection: 'column',
justifyContent: 'center',
flexGrow: 1,
},
showsVerticalScrollIndicator: true,
persistentScrollbar: true,
}))`
border: solid pink 5px;
width: 100%;
height: 200px;
padding: 10px;
`;
My question was answered perfectly in the same link I had in my question. All credit goes to freddrivett.
If your ScrollView is within something that handles touch (Pressable,
TouchableWithoutFeedback etc) then you either need to stop the touch
event propagating up to that parent handler or else the ScrollView
won't handle the touch event and therefore won't scroll.
This can be done either with onStartShouldSetResponder={() => true} or
by wrapping the children in an element which itself handles the touch
event (e.g. Pressable):
<Pressable>
<Text>This is scrollable</Text>
<Pressable>
<Pressable>
<Text>As is this</Text>
<Pressable> </ScrollView> );

How to maintain the hover effect of the sibling in Material-UI

Card Component
import image from "../../Assets/pic.jpg";
import React, { useState } from "react";
import { makeStyles } from "#material-ui/core/styles";
import Card from "#material-ui/core/Card";
import CardActionArea from "#material-ui/core/CardActionArea";
import FavoriteBorderIcon from "#material-ui/icons/FavoriteBorder";
import CardContent from "#material-ui/core/CardContent";
import CardMedia from "#material-ui/core/CardMedia";
import Typography from "#material-ui/core/Typography";
import styles from "./Cards.module.css";
import Stars from "../Stars/Stars";
const useStyles = makeStyles({
root: {
maxWidth: 345,
},
});
const Cards = () => {
const [showComponent, setShowComponent] = useState(false);
const classes = useStyles();
const handleToggleHoverIn = (event) => {
event.preventDefault();
setShowComponent(true);
};
const handleToggleHoverOut = (event) => {
event.preventDefault();
setShowComponent(false);
};
console.log("The state showComponent value is ", showComponent);
return (
<div className={styles.container}>
<Card
onMouseEnter={handleToggleHoverIn}
onMouseLeave={handleToggleHoverOut}
className={classes.root}
>
<CardActionArea>
<div id={styles.imageCentre}>
<CardMedia
component="img"
alt=""
className={styles.image}
image={image}
title="Contemplative Reptile"
/>
{/*
here when I hover over my <Stars/> and <FavoriteBorderIcon/>, the hover effect of opacity that I have on
my Card's image, vanishes
*/}
{showComponent ? (
<>
<div id={styles.stars}>
<Stars />
</div>
<FavoriteBorderIcon fontSize="large" id={styles.heart} />
</>
) : null}
</div>
<CardContent>
<Typography
gutterBottom
variant="h5"
component="h2"
id={styles.textCentre}
>
Printed round Neck
</Typography>
<Typography variant="body2" color="textSecondary" component="p">
<div class="text">
<p id={styles.price}>
<b>Rs. 454</b>
<strike>Rs. 699</strike>
<span style={{ color: "#FF7F7F" }}> (35 % off) </span>
</p>
</div>
</Typography>
</CardContent>
</CardActionArea>
</Card>
</div>
);
};
export default Cards;
Card's CSS styling
.image {
width: 300px;
justify-content: center;
}
.image:hover {
opacity: 0.5;
}
#imageCentre {
align-items: center !important;
position: relative;
}
/* #imageCentre:hover {
opacity: 0.5;
} */
#textCentre {
text-align: center;
}
.container {
display: flex;
justify-content: center;
padding: 2em;
}
#price,
.text h3 {
text-align: center;
}
#price b {
padding-right: 0.5em;
font-size: 1.3em;
}
#heart {
position: absolute;
top: 0;
right: 0;
padding: 20px 20px 0 0;
color: aliceblue;
}
#stars {
position: absolute;
top: 50%;
left: 50%;
margin-right: -50%;
transform: translate(-50%, -50%);
margin-top: 50%;
}
when I hover over my card, the opacity hover-effect comes in but when I move to the heart or star component, the opacity-hover vanishes. I want the hover-effect to remain even when I hover over my star and heart component. Is there any way that I can make the opacity-hover-effect to remain there, when I hover over the stars and heart component
Live Link
Below is an example of one way to do this. The key aspect of the solution is to use the :hover pseudo-class on a common parent of the img, stars, and icon elements. In my example, this is done via the action class applied to the CardActionArea element. My example is using makeStyles, but you could achieve the same effect in your CSS with the following:
#imageCentre:hover .image {
opacity: 0.5;
}
It looks like you tried something similar (the commented out #imageCenter:hover styles), but since you weren't targeting the descendant .image class for the opacity, the opacity would have impacted the stars and favorite icon as well which you probably don't want.
Here's a full working example:
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import Card from "#material-ui/core/Card";
import CardActionArea from "#material-ui/core/CardActionArea";
import CardActions from "#material-ui/core/CardActions";
import CardContent from "#material-ui/core/CardContent";
import CardMedia from "#material-ui/core/CardMedia";
import Button from "#material-ui/core/Button";
import Typography from "#material-ui/core/Typography";
import FavoriteBorderIcon from "#material-ui/icons/FavoriteBorder";
import Rating from "#material-ui/lab/Rating";
const useStyles = makeStyles({
root: {
maxWidth: 345
},
media: {
height: 140
},
action: {
position: "relative",
"&:hover $media": {
opacity: 0.5
}
},
favorite: {
position: "absolute",
top: 10,
left: 10,
color: "white"
},
rating: {
position: "absolute",
top: 100,
left: 100
}
});
export default function MediaCard() {
const classes = useStyles();
return (
<Card className={classes.root}>
<CardActionArea className={classes.action}>
<CardMedia
component="img"
className={classes.media}
image="https://material-ui.com/static/images/cards/contemplative-reptile.jpg"
title="Contemplative Reptile"
/>
<CardContent>
<Typography gutterBottom variant="h5" component="h2">
Lizard
</Typography>
<Typography variant="body2" color="textSecondary" component="p">
Lizards are a widespread group of squamate reptiles, with over 6,000
species, ranging across all continents except Antarctica
</Typography>
</CardContent>
<FavoriteBorderIcon className={classes.favorite} />
<Rating className={classes.rating} name="rating" />
</CardActionArea>
<CardActions>
<Button size="small" color="primary">
Share
</Button>
<Button size="small" color="primary">
Learn More
</Button>
</CardActions>
</Card>
);
}

trying to render a button for a portal in react and get this error: × TypeError: Object(...) is not a function on the modalwrapper style

I created a portal to display a message. come compile time i get an error on the ModalWrapper and cannot figure it out. all technologies are installed and up to date. ive imported and exported differently just can seem to figure out.
import React, { Component, Fragment } from 'react';
import styled from 'styled-components';
import Portal from './Portal';
import absolute from './elevation';
import Card from './Card';
import { Transition, animated } from 'react-spring/renderprops';
export default class Modal extends Component {
render() {
const { children, toggle, on } = this.props;
return (
<Portal>
<Transition
native
config={{
tension: 100,
friction: 15
}}
items={on}
from={{ opacity: 0, bgOpacity: 0, y: -50 }}
enter={{ opacity: 1, bgOpacity: 0.6, y: 0 }}
leave={{ opacity: 0, bgOpacity: 0, y: 50 }}
>
{on => on && ((styles) => (
<ModalWrapper>
<ModalCard styles={{
transform:
styles.y.interpolate(y => `translate3d(0, ${y}, 0)`),
...styles }}>
<CloseButton onClick={toggle}>
<p>H</p>
</CloseButton>
<div>{children}</div>
</ModalCard>
<Background style={{ opacity: styles.bgOpacity.interpolate(bgOpacity => bgOpacity) }} onClick={toggle}
/>
</ModalWrapper>
))}
</Transition>
</Portal>
);
}
}
const ModalWrapper = styled.div`
${absolute({})};
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
`;
const ModalWrapper = styled.div`
position: absolute;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
`;

Categories