I got a problem with framer-motion. I have modal with overlay and I want to overlay have a fading in animation but modal-container (his child element) to have and scale animation (from 1px width and height to 100vh and 100vw). I would like to prevent somehow overlay from scaling and just change his opacity by animation. Do you have any ideas on how to prevent child from parent's animation?
I'm framer-motion very beginner so sorry for probably shitty code :D
my code:
<motion.div
layout
data-isOpen={isOpen}
className="parent"
ref={modalRef}
>
<ModalContainer
initial={{opacity:0}}
animate={animate}
>
<div className="w-100 d-flex justify-content-end">
<Close
onClick={() => {
closeModal();
clearAllBodyScrollLocks(modalRef);
}}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20.39 20.39"
>
<title>close</title>
<line
x1="16.39"
y1="16.39"
x2="4"
y2="4"
fill="none"
stroke="#000000"
strokeLinecap="round"
strokeMiterlimit="10"
strokeWidth="1"
/>
<line
x1="4"
y1="16.39"
x2="16.39"
y2="4"
fill="none"
stroke="#000000"
strokeLinecap="round"
strokeMiterlimit="10"
strokeWidth="1"
/>
</Close>
</div>
{children}
</ModalContainer>
</motion.div>
parent class :
.parent{
width: 1px;
height: 1px;
position: absolute;
justify-content: center;
align-items: center;
overflow: auto;
border-radius: 2%;
}
.parent[data-isOpen="true"] {
display: block;
background-color: rgba(0,0,0,0.3);
margin: auto;
width: 100vw;
height: 100vh;
position: fixed;
top: 0;
left:0;
z-index:2;
border-radius: 2%;
padding: 4rem 0;
}
disclaimer: if you have any other idea how to make it better, please tell me (i have only just one requirement to make modal-container scaling from button, which opens modal. I mean it grows from his center to position fixed)
Thanks for help
If you're asking how to not have the overlay scale, then you just need to apply the scaling animation to the ModalContainer element, instead of the parent. But in that case, the modal will still fade in since its parent element is fading in. Is that what you want?
I think your solution will be to not have the modal be a child of the overlay. That way you can animate the opacity of the overlay, and the scale of the modal without either affecting the other.
If you want to keep them in the same component (you probably do), you could just have them both be siblings of the same parent element.
Structurally, something like this:
<div>
<Overlay animate={{opacity: isOpen ? 1 : 0}} />
<Modal animate={{scale: isOpen ? 1 : 0}} />
</div>
Related
I have created a Modal in which I add a Canvas from Recat Three Fiber.
The documentation says that Canvas should fill the parent's space.
To show it well, I added a yellow color to the Canvas parent as you can see in the picture.
However, Canvas doesn't want to fill that space.
The important thing is that when I change the size of the browser minimally, it works immediately.
Do I have something not defined in this way?
<Modal bodyStyle={{ height: "500px" }}>
<Content>
<Canvas
style={{
width: "100%",
height: "100%",
}}
>
<color attach="background" args={["skyblue"]} />
</Canvas>
</Content>
</Modal>;
const Content = styled.div`
width: 100%;
height: 100%;
background: yellow;
`;
IMAGE
I am using Accordion in next js. I am following this (react-accessible-accordion) package.
Currently it is getting collapse when main div is getting clicked. What i want to achieve is According should be collapse when click on arrow icon not on main div.
If there is an alternate way of doing this please let me know.
UPDATE
Here is the code sandbox
What i want to achieve is explained here
Thanks!
first I had to modify the styles so the icon is not taking the full width.
Accordion.css
.accordion__icon {
/* margin-left: auto; */
transition: transform 0.6s ease;
}
.accordion {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
display: flex;
align-items: center;
border: none;
outline: none;
transition: background-color 0.6s ease;
/* add flex display and justify content */
display: flex;
justify-content: space-between;
}
Add onClick to the main SVG and pass it through the props.
Chevron.js
// pass an onClick props to the main SVG
function Chevron(props) {
return (
<svg
className={props.className}
height={props.height}
width={props.width}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 320 512"
onClick={props.onClick}
>
<path
fill={props.fill}
d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"
/>
</svg>
);
}
export default Chevron;
Finally make the props.onClick of the Chevron component handle the onClick event not its Button parent component.
Accordion.js
...
// move the onClick from the button to the Chevron component
return (
<div className="accordion__section">
<button className={`accordion ${setActive}`}>
<p className="accordion__title">{props.title}</p>
<Chevron
onClick={toggleAccordion}
className={`${setRotate}`}
width={10}
fill={"#777"}
/>
</button>
...)
full sandbox link
I'm trying to add the Next Image component to my project.
And I have a problem, the image disappears when I add layout='responsive'.
code:
<Box>
<Link href='/' >
<Image src='/images/logoDark.svg'
alt='navbar-logo'
width={260}
height={56}
layout='responsive'
/>
</Link>
</Box>
Is there a solution? or any other way to optimize images?
Based on what is found here (https://github.com/vercel/next.js/issues/19314), it seems layout='responsive' has no intrinsic size. So you will have to add a width to the containing element.
You need to wrap the next/image into a container with display:block, so that the image will be displayed.
set height and width for the parent of the Image component :
<Box width={263} height={56}>
<Link href='/' >
<Image src='/images/logoDark.svg'
alt='navbar-logo'
width={260}
height={56}
layout='responsive'
/>
</Link>
</Box>
ensure the parent element uses display: block in their stylesheet like Box component or div
Component
<div className="photo">
<Image
width={300}
height={300}
src="https:/images.unsplash.com/photo-1501432377862-3d0432b87a14?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80"
alt="photo"
layout="raw"
/>
</div>
<style jsx>{`
#media (max-width: 768px) {
.photo {
margin: 0 auto;
justify-content: center;
display: flex;
width: 200px;
height: 200px;
}
}
`}</style>
next.config.js
experimental: {
images: {
layoutRaw: true,
},
},
This worked for me, the image doesn't disappear and is responsive,
I am building a React project. Within the projekt I am using React Popper 2 for dropdown menus. Great for auto positioning the dropdown menu when you are near the edges of the web browser, etc. I am also using React Transition Group / React CSStransition to make some animations. I am working with hooks in the project, no class components.
But I do not seem to be able to combine the both. Problem is that Popper enters and exits the dropdown menu. So CSStransition creates the classes as it should, but it does not work since they both enters and exits the element. And I have no clue how to resolve this.
References:
https://popper.js.org/
https://reactcommunity.org/react-transition-group/
This is the component atm:
<CSSTransition
classNames="popper-dd"
in={visible}
timeout={10000}
unmountOnExit
>
<div ref={popperElement}
onClick={() => autoclose!==false && setVisible(false)}
className={cn("Dropdown-tooltip", classes)}
style={{ ...styles.popper}}
{...attributes.popper}>
Test
<div className="cm-pos-dd-left bg-white absolute p-3 rounded-xl shadow z-20 text-black">
{children}
</div>
</div>
</CSSTransition>
I have also tried to place the CSStransition within the popperElement, but that does not do the trick.
Anyone have any clue how to get them both to work?
I did figure it out. It is maybe not the most beautiful solution, but it seems to work.
ReactJS:
<CSSTransition
in={visible}
classNames="popper-dd"
timeout={150}>
<div ref={popperElement}
onClick={() => autoclose!==false && setVisible(false)}
className={cn("popper-dd-init cm-pos-dd-left bg-white absolute p-3 rounded-xl shadow z-20 text-black Dropdown-tooltip", classes)}
style={{ ...styles.popper}}
{...attributes.popper}>
{children}
{/*<div ref={arrowElement} className="Dropdown-arrow" style={styles.arrow} />*/}
</div>
</CSSTransition>
CSS:
--popper-transition: margin-top .15s ease-in-out, opacity .15s ease-in-out;
--popper-top: -.5rem;
.popper-dd-init {
display: none;
}
.popper-dd-init.popper-dd-enter {
display: block;
pointer-events: none;
margin-top: var(--popper-top);
opacity: .5;
transition: var(--popper-transition);
}
.popper-dd-init.popper-dd-enter-active {
margin-top: 0;
opacity: 1;
pointer-events: auto;
}
.popper-dd-init.popper-dd-enter-done {
display: block;
}
.popper-dd-init.popper-dd-exit {
display: block;
margin-top: 0;
opacity: 1;
}
.popper-dd-exit-active {
pointer-events: none;
transition: var(--popper-transition);
margin-top: var(--popper-top) !important;
opacity: .5 !important;
}
.popper-dd-exit-done {
display: none;
}
I'm using react-modal
The documentation mentions that the modal should close when you click the overlay by default. Even if I set the shouldCloseOnOverlayClick prop to true, this still does not work.
I'm not aware of anything that might prevent that event from occurring.
In case this is relevant/indicative of anything (and I haven't figured out why this is showing), I noticed in Chrome Developer Tools that my modal's overlay and content nodes both have an undefined class. All the CSS classes I have used are defined and working as they should.
Here's the relevant JSX and CSS, please let me know if more context is required.
JSX:
return (
<div className="Modal">
<Modal
className={{
base: 'Modal-content' + ' Modal-InputError-videoURL'
}}
overlayClassName={{
base: 'Modal-overlay'
}}
isOpen={true}
contentLabel="Modal"
>
{props.message}
<br />
<br />
<br />
<button
className="Modal-button"
onClick={events.handleCloseModal}
>
Close
</button>
</Modal>
</div>
)
CSS classes:
.Modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.35);
z-index: 9998;
}
.Modal-content {
display: relative;
position: absolute;
top: 50%;
left: 50%;
border: 1px solid #ccc;
background: rgb(38,38,38);
border: 1.5px solid rgb(45,45,45);
overflow: auto;
border-radius: 1px;
outline: none;
z-index: 9999;
width: 400px;
margin-left: -150px;
margin-right: -150px;
padding: 24px;
line-height: 16px;
}
.Modal-InputError-videoURL {
height: 134px;
margin-bottom: -67px;
margin-top: -67px;
}
.Modal-button {
display: inline-block;
padding: 4px;
margin: 0;
}
I solved this problem by using onRequestClose (per the docs). It seems that react-modal doesn't store isOpen in its local state, so I provided a callback to onRequestClose that updates the state in the parent component, which is subsequently passed down to the modal as a prop.
http://reactcommunity.org/react-modal/examples/on_request_close.html
isOpen property is statically set to true. You should control its value by keeping isOpen value in your state.
isOpen = {this.state.isModelOpen}
And in handleCloseModal method you can set its value to false.
this.setState({isModelOpen: false})
I tried to use the modal in a certain component but the click overlay close was not working. Then, I moved the modal to the previous component parent, and it started work.
I guess it have to do with z-index, but I am not sure. Sorry for missing details.
Hope it helps you guys!