React Popper and React CSStransition - reactjs

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;
}

Related

Next Js Accrodion should be collapse when click arrow icon

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

How to change style of selected React-router link?

I have NavBar.jsx:
import React from "react";
import { Link } from "react-router-dom";
import "./navBar.sass";
function NavBar() {
return (
<div className="NavBar_container">
<nav className="NavBar">
<Link
to="/CreateReview"
className={(isActive) =>
"selected" + (!isActive ? " unselected" : "")
}
>
<div className="NavBar_img">
<img src="./create_review_icon.png" alt="create_review" />
</div>
<p className="NavBar_title">Create Review</p>
</Link>
<Link to="/Hotels" className="NavBar_item">
<div className="NavBar_img">
<img src="./main_page_icon.png" alt="main_page" />
</div>
<p className="NavBar_title">Reviews</p>
</Link>
<Link to="/MyAccount" className="NavBar_item">
<div className="NavBar_img">
<img src="./my_account_icon.png" alt="my_account" />
</div>
<p className="NavBar_title">My account</p>
</Link>
</nav>
;
</div>
);
}
export default NavBar;
And some styles:
.NavBar
position: fixed
z-index: 9999
display: flex
justify-content: space-between
width: 400px
height: 75px
padding: 15px 25px 0 25px
background-color: rgba(0, 0, 0, 0.81)
border-bottom-left-radius: 30px
border-bottom-right-radius: 30px
&_container
width: 450px
margin: 0 auto
&_item
text-decoration: none
&:hover , &:active
.NavBar_title
transition: 0.2s all
color: #DAAD86
border-bottom: 1px solid #DAAD86
.NavBar_img
transition: 0.2s all
transform: scale(1.1)
&_img
width: 35px
margin: 0 auto
&_title
text-align: center
color: white
padding-bottom: 5px
.selected
background-color: blue
.unselected
background-color: red
I'm trying to set up my NavBar so that the selected link changes style, nothing works right now, what's wrong? I would like the text under the image to change its color and become underlined (as it is done in the :hover classes). I did this according to the React-Router documentation, maybe I missed something?
In your app.jsx file, or wherever you have your navbar component rendering, use the useLocation hook provided by 'react-router-dom' to get the current page. You can then pass it to your navbar as props and give the links the 'selected' class if the current page === the page the link points to.

#media query display block not working in #emotion/react

I have a style like this
//inside page.jsx
export function Page() {
return (
<div css={container}>
<div css={header}>
<div css={horizontal}>
<Menu
mode="horizontal"
>
<Menu.Item>
<Link href="#>
<a>Menu A</a>
</Link>
</Menu.Item>
</Menu >
</div>
</div>
</div>
)
}
//inside styles.js
export const horizontal = css`
display: none;
#media (min-width: 720px) {
display:block;
}
`
export const header= css`
height: 10%;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 20px;
background-color: white;
position: sticky;
top: 0;
z-index: 1;
`
When testing the browser with a size less than 720px its works as intended the content is invisible because of display none, but when the browser size is back to more than 720px it's not working at all (not going back to visible).
if I replace the Menu component with another component the style is working properly (when less than 720px = invisible and when more than 720px = visible). Also, it can work with the Menu component if removing display flex in the header style.
I'm a bit confused about what going on here.

Radio Input As Cards - React + Antd

I wanted to create Radio Input Buttons styled Cards.
I am using react js and ant design.
Tried to create my own native component using good old input type="radio".
Connecting them to antd forms wasen't smooth sailing, then I had another idea.
Using antd react Radio component and just passing a card component. That's the working result!
Usage.tsx
// Other Code
<Radio.Group onChange={onChange} value={value} className="cards-container">
<Radio value={FOCUS_LEVEL.Regular} className="radio-input-card-container">
<InputCard
title="First Card"
checked={value === CONSTANT1}
imgPath="../../assets/icon1.svg"
points={["This is a point explain why this card is the best!", "Wow this is also a great point"]} />
</Radio>
<Radio value={FOCUS_LEVEL.DeepFocus} className="radio-input-card-container">
<InputCard
title="Second Card"
checked={value === CONSTANT2}
imgPath="../../assets/icon2.svg"
points={["This point explains why this card is way better", "The other card as shitty points!"]} />
</Radio>
</Radio.Group>
// Other Code
Usage.scss
.cards-container {
display: flex;
justify-content: space-between;
margin-left: 20px;
}
InputCard.tsx
import React from "react"
import Title from "antd/lib/typography/Title";
import "./InputCard.scss"
export function InputCard({ title, checked, imgPath, points }): JSX.Element {
return (
<div className={checked ? "card checked" : "card"}>
<div className="header-container">
<Title className="card-title">{title}</Title>
<img src={imgPath} alt="regular focus"></img>
</div>
<ul>
{points.map((point) =>
<li key={point.toString()}>{point}</li>
)}
</ul>
</div >
);
}
InputCard.scss
.card {
height: 420px !important;
width: 360px !important;
position: relative !important;
left: -45px; // A work around. Placing the card under the native radio button
-webkit-appearance: none;
appearance: none;
border: 2px solid rgba(2,28,53,0.08);
border-radius: 14px;
box-shadow: 7px 7px 15px rgba(2,28,53,0.08);
cursor: pointer;
outline: none;
.header-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
ul {
padding: 0em 1em 0em 2.5em !important;
}
img {
margin: 0.5em 0em 1em 0em;
}
}
.card-title {
font-size: 20px !important;
margin-top: 16px !important;
}
.checked {
transition: border 0.5s ease;
border: 2px solid rgba(255,0,0,0.6);
}
The antd component creates a radio input circle right before the card childe. Moving the card to the left (left: -45px) so the card will include the radio circle is a workaround. I don't want to change too much in the parent component for me to use this InputCard component, and this is my try to do it within the component.

How to stop the jumping jack of text change in React

How to smoothly transition from text to svg in react.
As soon as I click on next button shown in pic as ">" ,the text changes to svg.But there is some sort of jumping due to change in overall height.
How can I smoothly transition between two.
Note: Unfortunately, I can't share the code as this is not a personal
project.
You can set the height of the containing element to the heighest element. Therefore you need to place them in a row with a negative margin-right so that they overlay each other. Only the element that you make visible will be shown when you hide the other elements with visibility: hidden;
Here is an example:
var elements = document.querySelectorAll('.block__element');
document.querySelector('button').addEventListener('click', () => {
elements.forEach(element => {
if(element.classList.contains('block__element--visible')) {
element.classList.remove('block__element--visible');
} else {
element.classList.add('block__element--visible');
}
})
});
.block {
background: #aaa;
display: flex;
}
.block__element {
width: 100%;
margin-right: -100%;
visibility: hidden;
opacity: 0;
transition: visibility 1s, opacity 1s;
}
.block__element--visible {
visibility: visible;
opacity: 1;
}
<div class="block">
<div class="block__element block__element--visible">
<div style="background: #f00">Content 1</div>
</div>
<div class="block__element">
<div style="height: 200px; background: #0f0">Longer content 2</div>
</div>
</div>
<button>Toggle between elements</button>

Resources