simple css animation not working on dynamic reactjs element - reactjs

Check the snippet at codepen http://codepen.io/anon/pen/EZJjNO
Click on Add button, it will add another item but its appearing immediately without any fade effect.
JS:
class App extends React.Component {
constructor(props) {
super(props);
this.addItem = this.addItem.bind(this);
this.state = {
items: [1,2,3]
}
}
addItem() {
var items = this.state.items;
items.push(4);
this.setState({
items: items
})
}
render() {
return (
<div className="App">
{
this.state.items.map(function(i) {
return <div className="item fade">Testing</div>
})
}
<button onClick={this.addItem}>Add</button>
</div>
);
}
}
React.render(<App />, document.body);
CSS:
.App {
background-color: rgba(0,0,0, 0.5);
text-align: center;
height: 100vh;
}
div.item {
border: 1px solid #ccc;
padding: 10px;
background: #123456;
color: #fff;
opacity: 0;
transition: all 0.4s ease-out;
}
.fade {
opacity: 1 !important;
}

Since the fade class is added by default, you don't get the transition effect. If you open your browser's developer tools and remove the class, you'll see it fade away nicely.
There's a few ways to get what you want, but I'd just use a keyframe CSS animation like so:
.fade {
animation: 0.4s ease-out fadeIn 1;
}
#keyframes fadeIn {
0% {
opacity: 0;
visibility: hidden;
}
100% {
opacity: 1;
visibility: visible;
}
}
Here's a fork of your code pen showing how it works :)

Related

How do I use animation that spreads up and down when I make a drop-down menu?

I'm making a drop-down menu now. When I put my mouse on a specific part, the drop-down menu opens and when the mouse goes out of the browser, I want to make the drop-down menu disappear. I made a state value called isMouseOver to return true when the mouse goes up and to use jquery to return false when the mouse goes out of the browser. When the mouse goes up, I used animation to implement it as I wanted, but I want to implement animation that slowly disappears up when the mouse goes out of the browser, but this part doesn't work well. I put this part in an animation as well, but the animation overlapped and it was executed strangely. To sum up the question, how do I put the animation when isMouseOver becomes false and the display becomes none?
import { useState } from 'react';
import styled, {keyframes} from 'styled-components';
import $ from 'jquery';
// animation when mouseover
const dropdownAnimation = keyframes`
0% {
transform: translateY(-30%);
}
100% {
transform: translateY(0);
}
`
function HeaderRight () {
// Check mouseover
const [isMouseOver, setIsMouseOver] = useState(false)
// return true when mouse over
const ActMouseOver = () => {
setIsMouseOver(true)
}
// return false when mouse over
const ActMouseLeave = () => {
setIsMouseOver(false)
}
// return false when the mouse is out of the browser
$(document).mouseleave(function () {
ActMouseLeave();
});
return (
<HeaderRightWrap isMouseOver={isMouseOver} onMouseEnter={ActMouseOver}>
<ul className='HeaderRightWrapUl'>
<li className='HeaderRightWrapUlLi'>
<ul className='HeaderRightWrapUlLiUl'>
<li className='HeaderRightWrapUlLiUlLi'>
Hello
</li>
</ul>
</li>
</ul>
</HeaderRightWrap>
)
}
export default HeaderRight;
const HeaderRightWrap = styled.div`
position: relative;
box-sizing: border-box;
bottom: 40px;
.HeaderRightWrapUl {
height: 100%;
margin: 0 auto;
padding: 0;
list-style: none;
box-sizing: border-box;
display: block;
margin-inline-end: 0px;
margin-inline-start: 0px;
margin-block-start: 1em;
margin-block-end: 1em;
padding-inline-start: 40px;
}
.HeaderRightWrapUlLi {
z-index: 1000;
position: relative;
float: left;
width: auto;
height: 100%;
padding-right: 80px;
transition: padding .3s;
}
.HeaderRightWrapUlLiUl {
display: ${props=>props.isMouseOver===true?'auto':'none'};
position: absolute;
animation: ${dropdownAnimation} 0.3s ease;
}
.HeaderRightWrapUlLiUlLi {
margin-top: 0;
}
`

How do I change the background color of a toggle button when the state changes to true?

I'm still learning the fundamentals of web development and I am stuck. I've created a toggle button in react.js but I can't seem to change the background color when the state changes to true.
Can anyone help point me in the right direction?
.ToggleSwitch {
background: #e3e8eb;
border: 3px solid #e3e8eb;
height: 2em;
width: 4em;
border-radius: 2em;
cursor: pointer;
margin-bottom: 5px;
}
.ToggleSwitch .knob {
position: relative;
width: 1.9em;
height: 1.9em;
border-radius: 50%;
left: 0em;
transition: left 0.3s ease-out;
border: 1px solid #fff;
background-color: #fff;
}
.ToggleSwitch .knob.active {
left: 2em;
background-color: #f37c22;
border: 1px solid #f37c22;
}
import React from "react";
import "./toggleButton.css";
class ToggleButton extends React.Component {
constructor(props) {
super(props);
this.state = { isToggleOn: false };
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState((prevState) => ({
isToggleOn: !prevState.isToggleOn,
}));
}
render() {
return (
<div onClick={this.handleClick} className="ToggleSwitch active" >
<div className={this.state.isToggleOn ? "knob active" : "knob"} />
</div>
);
}
doSearch(props) {
const [searchInput, setSearchInput] = "";
const submitForm = (event) => {
event.preventDefault();
props.getRecipes(searchInput);
};
}
}

How to loop a Draggable slider in React

I have a draggable horizontal slider in my current project and I would like to setting up it also to loop continuously. By loop continuously I mean it should respond to the process of showing images one after another when dragging? Right now, I do have only 3 images in my slider and when I drag slider to the left, slider with its 3rd image and a blank white space starts showing just after. Here at this point I want images to get start again continuously from the very beginning i.e. from the 1st image with aim to cover the white blank space.
Apart, one error I'm getting with my existing code is that when I start to drag slider to right side, suddenly a scroll comes up on browser and keep going in never ending state. By never ending state, I mean it still remain on screen when I drag all my 3 images fully in right direction.
So these are the two things I want to apply and want to resolve in my current project. I'm sharing my code below.
src > Routes > Home > Components > Carousel > Components > SliderDataItems > index.js
import React, { useRef, useEffect } from "react";
import { gsap } from "gsap";
import { Draggable } from "gsap/Draggable";
import { ZoomInOutlined } from '#ant-design/icons'
import { Images } from '../../../../../../Shared/Assets';
import ImagesIcon from '../../../../../../Components/Cells/ImagesIcon'
gsap.registerPlugin(Draggable);
const pictures = [
{
img: Images.xgallery1,
icon: <ZoomInOutlined />
},
{
img: Images.xgallery2,
icon: <ZoomInOutlined />
},
{
img: Images.xgallery4,
icon: <ZoomInOutlined />
},
];
const Slide = ({ img, icon }) => {
return (
<div className="slide">
<div className="image">
<ImagesIcon src={img} />
<div className="icon">
{icon}
</div>
</div>
</div>
);
};
export const Slider = () => {
const sliderRef = useRef(null);
useEffect(() => {
Draggable.create(sliderRef.current, {
type: "x"
});
}, []);
return (
<div className="slider" ref={sliderRef}>
{pictures.map((item, index) => {
return (
<Slide key={index} img={item.img} icon={item.icon} />
);
})}
</div>
);
};
export default Slider;
src > Routes > Home > Components > Carousel > style.scss
.slider {
display: flex;
cursor: unset !important;
overflow: hidden !important;
.slide {
.image {
position: relative;
img {
width: 100% !important;
height: auto !important;
object-fit: cover;
}
.icon {
transition: 0.5s ease;
opacity: 0;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
text-align: center;
span {
svg {
font-size: 30px;
color: #fff;
}
}
}
}
}
.image:hover .icon {
opacity: 1;
}
}
.image:after {
content: "";
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: rgba(211, 208, 208, 0.6);
opacity: 0;
transition: all 0.5s;
-webkit-transition: all 0.5s;
}
.image:hover:after {
opacity: 1;
}
Here's the link of demo (kindly see just above the footer section) for your reference.
Thank you for any help.
For draggle Slider there is a very lightweight JS Carousel package - siema
It is a great, lightweight carousel that is made with JS. There are also other packages built on top of this purely made for React.
In your case, I would offer to try out react-siema.
With it, you can simply use the carousel like that and it will be draggable by default. Plus, no need to load any css.

react Semantic-UI - multi-select checkbox drop-down

i want to built an multi select checkbox dropdown in react with es6
my requirement is as below specified in image
I tried doing this click here but it is not working.
You can use one parent component that will keep values in its state and toggle list items. Then you can create component for each list item that will keep active property in state that you can toggle on click.
class ListItem extends React.Component {
constructor(props) {
super(props);
this.state = {active: false}
}
render() {
return (
<a
onClick={() => {
this.setState(prevState => {
let newState = !prevState.active;
this.props.handleClick(newState, this.props.value);
return {active: newState}
})
}}
className={!this.state.active ? '' : 'selected'}
href="#">
{this.props.value}</a>
)
}
}
class Select extends React.Component {
constructor(props) {
super(props);
this.state = {
showList: false,
value: []
}
this.handleItemClick = this.handleItemClick.bind(this)
}
componentDidMount() {
document.addEventListener('mousedown', (e) => {
if(!this.node.contains(e.target)) {
this.setState({showList: false})
}
})
}
componentWillUnmount() {
document.removeEventListener('mousedown');
}
renderValue() {
let {value} = this.state;
if(!value.length) return "Select..."
else return value.join(', ')
}
toggleList() {
this.setState(prevState => ({showList: !prevState.showList}))
}
handleItemClick(active, val) {
let {value} = this.state;
if(active) value = [...value, val]
else value = value.filter(e => e != val);
this.setState({value})
}
render() {
return (
<div
ref={node => this.node = node}
className="select">
<button onClick={this.toggleList.bind(this)}>
<span className="select_value">
{this.renderValue()}
</span>
</button>
<div
className={"select_list " + (!this.state.showList && 'hide')}>
<ListItem handleClick={this.handleItemClick} value="Lorem" />
<ListItem handleClick={this.handleItemClick} value="Ipsum" />
<ListItem handleClick={this.handleItemClick} value="Dolor" />
</div>
</div>
)
}
}
ReactDOM.render(
<Select />,
document.getElementById('container')
);
button {
background: white;
width: 100%;
padding: 10px 15px;
border: 1px solid rgba(0, 0, 0, .1);
border-radius: 5px;
cursor: pointer;
text-align: left;
}
.select_list {
width: 100%;
background: white;
border: 1px solid rgba(0, 0, 0, .1);
border-radius: 5px;
}
.select_list a {
padding: 10px 15px;
display: flex;
color: black;
text-decoration: none;
position: relative;
align-items: center;
}
.select_list a:before {
width: 15px;
height: 15px;
content: '';
border: 1px solid rgba(0, 0, 0, .1);
border-radius: 5px;
margin-right: 10px;
display: block;
}
.select_list a.selected:before {
background: #0493D1;
content: '✓';
color: white;
font-size: 11px;
text-align: center;
line-height: 15px;
}
.hide {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container"></div>
Semantic-UI React Approach
After much digging, I found an old conversation between eugenetumachov and Semantic-UI developers(?). One of the users provided incredibly helpful code that answers this question using Semantic-UI's Dropdown component.
This is done by making use of Dropdown's Dropdown.Menu and Dropdown.Item. Then looping through your options via map to create checkboxes. The only downside is that the workaround does not seem to allow scrolling and will require more CSS. Additionally, based on CSS the checkbox items' background color may turn transparent if you double-click on the dropdown, and the dropdown will collapse on mouse hover. You can bypass the transparency issue by using a class or style property for your Dropdown.Menu and Dropdown.Item.
Semantic-UI developer's response to this type of question appears to be a flat "no" or a
Active items are automatically removed from the Dropdown menu. So you cannot show a "checked" state for an item in the menu.
You could create a similar component out of an Input as a trigger for
a Popup containing a Menu or List of Checkboxes.
Are dropdowns with checkboxes possible? #2417
eugenetumachov's workaround

React styled-components fade in/fade out

I am trying to build a React component to handle fading in and fading out. In the following code, if I pass out as a prop to the component, it is disaplayed as hidden before animating out. I'm trying to have it fade in by default, then fade out when I pass in the out prop. Anyone see a solution to this problem?
import React from 'react';
import styled, { keyframes } from 'styled-components';
const fadeIn = keyframes`
from {
transform: scale(.25);
opacity: 0;
}
to {
transform: scale(1);
opacity: 1;
}
`;
const fadeOut = keyframes`
from {
transform: scale(1);
opacity: 0;
}
to {
transform: scale(.25);
opacity: 1;
}
`;
const Fade = styled.div`
${props => props.out ?
`display: none;`
: `display: inline-block;`
}
animation: ${props => props.out ? fadeOut : fadeIn} 1s linear infinite;
`;
function App() {
return (
<div>
<Fade><💅test></Fade>
</div>
);
}
export default App;
WebpackBin running example
The issue with your code is that you're setting the display property to none when props.out is true. That's why you're not seeing any animation, because before that can even start you've already hidden the component!
The way to do a fade out animation is to use the visibility property instead and transition that for the same amount of time as the animation takes. (see this old SO answer)
Something like this should solve your issues:
const Fade = styled.default.div`
display: inline-block;
visibility: ${props => props.out ? 'hidden' : 'visible'};
animation: ${props => props.out ? fadeOut : fadeIn} 1s linear;
transition: visibility 1s linear;
`;
const fadeIn = styled.keyframes`
from {
transform: scale(.25);
opacity: 0;
}
to {
transform: scale(1);
opacity: 1;
}
`;
const fadeOut = styled.keyframes`
from {
transform: scale(1);
opacity: 1;
}
to {
transform: scale(.25);
opacity: 0;
}
`;
const Fade = styled.default.div`
display: inline-block;
visibility: ${props => props.out ? 'hidden' : 'visible'};
animation: ${props => props.out ? fadeOut : fadeIn} 1s linear;
transition: visibility 1s linear;
`;
class App extends React.Component {
constructor() {
super()
this.state = {
visible: true,
}
}
componentDidMount() {
setTimeout(() => {
this.setState({
visible: false,
})
}, 1000)
}
render() {
return (
<div>
<Fade out={!this.state.visible}><💅test></Fade>
</div>
);
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://unpkg.com/styled-components/dist/styled-components.min.js"></script>
<div id="root" />
Note: Your fadeOut animation also went from 0 to 1 opacity, instead of the other way around. I've fixed that in the snippet too.

Resources