I'm building a personal site w/ React and trying to get some h2's to fade in after a couple of seconds after load. I'm using ReactCssTransitionGroup on the following Component:
import React, { Component } from 'react';
import ReactCSSTransitionGroup from 'react-addons-css-transition-group';
class TitleArea extends Component {
constructor(props) {
super(props);
this.state = {
ids: ['h2-one', 'h2-two', 'h2-three'],
h2Texts: ['Text1', 'Text2', 'Text3']
};
}
render() {
const descriptionDivs = this.state.ids.map( (id, index)=> {
return(<h2 key={id} id={id}>
{this.state.h2Texts[index]}
</h2>)
})
return (
<div className='row odd'>
<h1> MYNAMEHERE </h1>
<div className='description-container'>
<ReactCSSTransitionGroup
transitionName="descriptions"
transitionEnterTimeout={500}
transitionLeaveTimeout={300}>
{descriptionDivs}
</ReactCSSTransitionGroup>
</div>
</div>
);
}
}
export default TitleArea;
CSS/SASS:
.site-container {
text-align: center;
font-family: 'Source Code Pro', monospace;
h1 {
font-size: 50px;
font-family: 'Arvo', serif;
h2 {
font-size: 25px;
}
}
.descriptions-enter {
opacity: 0.01;
}
.descriptions-enter.descriptions-enter-active {
opacity: 1;
transition: opacity 500ms ease-in;
}
I'd ideally want each h2 to transition in one after another, but I'm trying to get a handle on the react-addons first before I jump to staggering the fade-ins. Does anyone have any experience with css transitions in React. Tried following the docs but got a bit lost. Any insight greatly appreciated! Thanks
Related
Update - solved, Thanks Konrad! I had text that was blocking the search bar, adding pointer-events: none; to the text fixed my issue.
I am learning react and trying to create a search bar. Right now, I just want to have the user's input to the search bar be logged to the console or pop up in a message when they submit text.
However, I cannot even enter text into my search bar right now.
I have tried looking at the react documentation (https://reactjs.org/docs/forms.html) and (https://reactjs.org/docs/state-and-lifecycle.html) and I think the issue has something to do with setting state but I am not sure where I am going wrong. I saw other people on stack overflow had this issue, but it was fixed for them when they added 'value=' to their <in bar which did not work for me.
Thank you for reading!
import React from 'react'
import './SearchBar.css'
class SearchBar extends React.Component { //
constructor(props){
super(props);
this.state = {value: ''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('A value was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<div className='Container'>
<form className='SearchBar' onSubmit={this.handleSubmit}>
<input type="text" placeholder='Enter the link to your IMDB profile' value={this.state.value} onChange={this.handleChange} />
</form>
<p className='Warning'>Make sure your imdb profile is set to public!</p>
</div>
);
}
}
export default SearchBar
As pointed out by Konrad below, the isolated component works fine, so there must be some issue in my integration. When I comment out my App.css file, it also works fine, so it is some issue in those that is causing me an issue, does anyone know what I need to add?
Here is my app.css:
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
#media (prefers-reduced-motion: no-preference) {
.App-logo {
height: 20vmin;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(20px + 2vmin);
color: white;
}
.Wrapped{
position:absolute;
left: 40%;
height: 75%;
font-size: 75px;
transform: rotate(45deg);
font-family: "Apple Chancery", cursive;
color:deeppink
}
.App-link {
color: #61dafb;
}
#keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
and my app.js:
import logo from './Logo_2016.png';
import './App.css';
import SearchBar from './components/SearchBar';
function App() {
return (
<div className="App">
<header className="App-header">
<h1 className='Wrapped'> Wrapped </h1>
<img src={logo} className="App-logo" alt="logo" />
<p> Welcome! </p>
<SearchBar/>
</header>
</div>
);
}
export default App;
Trying to do a drop-shadow hover effect in react. I thought I'd use inline style attribute so each icon can have a different color when it's hovered over. I'm stuck on how to achieve this. In my IconGrid component I've created an array of objects, each has an image and the image color respectively. Then I map through it and return the individual GridItem component, but I'm stuck as to how I can use the unique color property for the css drop-shadow effect. I'm getting the red lines in my GridItem component because it's clearly not the written correctly. How can I achieve this?
IconGrid Component
import React from "react";
import "./index.scss";
import GridItem from "./GridItem";
import XD from "../../../assets/images/adobe-xd.png";
import PS from "../../../assets/images/adobe-photoshop.png";
import AI from "../../../assets/images/adobe-illustrator.png";
import CSS from "../../../assets/images/css.png";
import GSAP from "../../../assets/images/gsap.png";
import GULP from "../../../assets/images/gulp.png";
import HTML from "../../../assets/images/html.png";
import JS from "../../../assets/images/javascript.png";
import NODE from "../../../assets/images/nodejs.png";
import REACT from "../../../assets/images/react.png";
import WP from "../../../assets/images/wordpress.png";
import PHP from "../../../assets/images/php.png";
const IconGrid = () => {
const icons = [
{ img: XD, color: "#2E001E" },
{ img: PS, color: "#31C5F0" },
{ img: AI, color: "#FF7F18" },
{ img: HTML, color: "#E44D26" },
{ img: CSS, color: "#264DE4" },
{ img: WP, color: "#01579B" },
{ img: PHP, color: "#6181B6" },
{ img: JS, color: "#F7DF1E" },
{ img: GSAP, color: "#8AC640" },
{ img: GULP, color: "#D34A47" },
{ img: NODE, color: "#83CD29" },
{ img: REACT, color: "#61DBFB" },
];
return (
<>
<div className="flex-grid">
{icons.map((icon, idX) => (
<GridItem key={idX} icon={icon} />
))}
</div>
</>
);
};
GridItem Component
import React from "react";
import "./index.scss"
const GridItem = ({ icon }) => {
return (
<div style={{`--color: ${icon.color}`}} className="flex-item">
<img src={icon.img} alt="" />
</div>
);
};
export default GridItem;
And the CSS
.flex-item {
flex-basis: 22.5%;
padding: 2.5rem 0;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.4s ease-in-out;
position: relative;
&:hover {
transition: all 0.4s ease-in-out;
filter: drop-shadow(0 0 20px var(--color)) drop-shadow(0 0 40px var(--color))
drop-shadow(0 0 60px var(--color));
}
img {
max-width: 80px;
height: auto;
}
}
I think you should set your inline style as below, keeping the key: value form.
import React from "react";
import "./index.scss"
const GridItem = ({ icon }) => {
return (
<div style={{'--color': `${icon.color}`}} className="flex-item">
<img src={icon.img} alt="" />
</div>
);
};
export default GridItem;
i started a simple project with react.in my project i have a paragraph and when mouse hover on paragraph (mouse enter event) a square appears under the paragraph and when hover out from paragraph(mouse leave event) that square disapear.but this occure so fast so i want changing this smoothly and i want use opacity and change that from 0 to 1 and reverse when my events occure.but I do not know what to do to change the opacity with animation in react.
this is my appjs
import './index.css';
import React, {useState} from "react";
function App() {
const [isShowSquare, setIsShowSquare] = useState(false);
const showSquare = () => {
setIsShowSquare(true);
}
const hideSquare = () => {
setIsShowSquare(false);
}
return (
<div>
<p onMouseEnter={showSquare} onMouseLeave={hideSquare} style={{display:'inline-block'}}>Hover Me</p>
{isShowSquare ?
<div className='square'>
</div>
: null
}
</div>
);
}
export default App;
and this is my index.css
*{
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.square{
width: 50px;
height: 50px;
background-color: #61dafb;
}
I would be very grateful if anyone could help me
Here is a method without using useState though.
I don't know if this part is important, but have a look at my
sandbox
First of all you need a css class to define the opacity the method and how much time it will take. Also, your first square class should have opacity: 0, meaning non visible.
When mouse is over text, then you add the extra class to the element.
const showSquare = () => {
div.current.classList.add("square-full");
};
const hideSquare = () => {
div.current.classList.remove("square-full");
};
.square.square-full {
opacity: 0.5;
transition: opacity 1s ease-out;
}
.square {
width: 50px;
height: 50px;
background-color: #61dafb;
opacity: 0;
}
Updated answer: No need for ref
Just use the following code
export default function App() {
const [ isShown, setShown ] = useState(false)
return (
<div>
<p
onMouseEnter={() => setShown(true)}
onMouseLeave={() => setShown(false)}
style={{ display: "inline-block" }}
class="paragraph"
>
Hover Me
</p>
<div className={`square ${isShown ? 'square-full' : ''}`}></div>
</div>
);
}
along with the extra class i mentioned before
Appearing is easy, and for disappearing I found a solution like this;
import { useState } from "react";
import "./styles.css";
export default function App() {
const [visible, setVisible] = useState(false)
const [disappear, setDisappear] = useState(false)
return (
<div className="App">
<p onMouseLeave={()=> {
setDisappear(true)
setTimeout(()=>{setVisible(false)
setDisappear(false)}
, 1000)
}} onMouseEnter={()=> setVisible(true)}>Hide/Show square </p>
{visible && <div className="square"
style={{
width: 100,
height: 100,
animation: disappear ? "disappear 1s ease" : "appear 1s ease"
}}> </div> }
</div>
);
}
For the animations in css ;
//style.css
.square {
background-color: red;
animation: appear 1s ease;
}
#keyframes appear {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
#keyframes disappear {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
So what happens here is that we have a keyframe on our css for the opacity initially. So this works fine, tricky part is disappearing. When we set the visible state to false React immideately removes our element, so we have setTimeOut to stop React for 1 second. In that 1 second we apply our animations, it runs smoothly on me. Go ahead and try.
I have a component that is already built out like so:
const Banner = ({ image, heading, text }) => (
<Container>
<Background src={image}>
<BannerContent>
<h1>{heading}</h1>
<h2>{text}</h2>
</BannerContent>
</Background>
</Container>
);
const BannerContent = styled.div`
h1 {
font-size: 24px;
}
h2 {
font-size: 16px;
}
`;
and I'm trying to override the styles of the h1 and h2 and add new styles like so in another component:
const PageBanner = styled(Banner)`
h1 {
font-size: 20px;
width: ...
}
h2 {
font-size: 13px;
width: ...
}
`;
However, none of that is happening. I'm assuming it's because it's nested in there? Am I able to override the styles? Or should I just build a similar component to it?
If you are styling one of your own custom components, you must make sure you use the className prop that styled components gives to the component.
const Banner = ({ image, heading, text, className }) => (
<Container className={className}>
<Background src={image}>
<BannerContent>
<h1>{heading}</h1>
<h2>{text}</h2>
</BannerContent>
</Background>
</Container>
);
const PageBanner = styled(Banner)`
h1 {
font-size: 20px;
width: ...
}
h2 {
font-size: 13px;
width: ...
}
`;
I am Using GatsbyJs and am trying to accomplish a active class toggle. I have a simple Component composed of a anchor tag with a span inside. I want to change some css by toggling a active class on the anchor when it is clicked. Here is my code so far, I am also using styled-components. I tried some vanilla js in the broken code section below, that obviously didn't work hence broken code.
Thanks in advance
styles
const Menu = styled.a`
position: absolute;
cursor: pointer; padding: 10px 35px 16px 0px;
span, span:before, span:after{
cursor: pointer;
border-radius: 1px;
height: 5px;
width: 35px;
background: #000000;
position: absolute;
display: block;
content: '';
transition: all 200ms ease-in-out;
}
span:before{
top: -10px;
}
span:after{
bottom: -10px;
}
.active span{
background-color: transparent;
}
.active span:before, .active span:after{
top:0;
}
.active span:before{
transform: rotate(45deg);
}
.active span:after{
transform: rotate(-45deg);
}
`
component
const TemplateWrapper = ({ children }) => (
<div>
<Wrapper>
<Menu id="nav-toggle" className="menu"><span></span></Menu>
{children()}
</Wrapper>
</div>
)
TemplateWrapper.propTypes = {
children: PropTypes.func,
}
export default TemplateWrapper
broken code
document.querySelector( "#nav-toggle" )
.addEventListener( "click", function() {
this.classList.toggle( "active" );
});
This is the html that is rendered
<a class="menu sc-bwzfXH SqHLW" id="nav-toggle"><span></span></a>
Okay, you can take a look here REACT - toggle class onclick
. There are several answers that show the way how you can achieve that, but things get messier when you want to use more than one class.
I like this package to handle the cases where you deal with styling with multiple classes based on the props or state: https://github.com/JedWatson/classnames.
I simplified the styles for the sake of clarity of this answer and assumed that the menu is a global class, you want to apply as well.
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import styled from 'styled-components';
const Wrapper = styled.div``;
const Menu = styled.a`
span {
color: green;
}
&.active span {
color: blue;
}
`;
class TemplateWrapper extends Component {
state = {
isActive: false
};
handleClick = () => {
this.setState(state => ({ isActive: !state.isActive }));
};
render() {
const menuClass = classNames({
menu: true,
active: this.state.isActive
});
return (
<Wrapper>
<Menu id="nav-toggle" className={menuClass} onClick={this.handleClick}>
<span>Test</span>
</Menu>
{this.props.children}
</Wrapper>
);
}
}
TemplateWrapper.propTypes = {
children: PropTypes.node
};
TemplateWrapper.defaultProps = {
children: null
};
export default TemplateWrapper;
Notice the ampersand (&) before .active. As stated in the docs, styled components supports all of CSS plus nesting.
Ampersands (&) get replaced by our generated, unique classname for that styled component, making it easy to have complex logic.
However, you can achieve the same effect without classnames by fully utilizing styled components functionality. Take a look at this section of the documentation.
A few changes needed:
const Menu = styled.a`
span {
color: ${props => (props.active ? 'blue' : 'green')};
}
`;
The render method would look like that:
render() {
return (
<Wrapper>
<Menu id="nav-toggle" className="menu" active={this.state.isActive} onClick={this.handleClick}>
<span>Test</span>
</Menu>
{this.props.children}
</Wrapper>
);
}
You can use component state to mange this.
Code will look like:
Updated: Moved logic to Menu component as it makes more sense to place it there. Below working example
class Menu extends React.Component {
constructor(props) {
super(props);
this.menuClick = this.menuClick.bind(this);
this.state = {
menuClass: '',
}
}
menuClick(e) {
const menuClass = this.state.menuClass === '' ? 'active' : '';
this.setState({ menuClass });
}
render() {
const {children, id} = this.props;
const menuClassName = `menu sc-bwzfXH SqHLW nav-toggle ${this.state.menuClass}`;
return (<a className={menuClassName} id={id} onClick={this.menuClick}>{children}</a>);
}
}
ReactDOM.render(<Menu><span>Test link</span></Menu>, document.getElementById('menu'))
.menu {
font-weight: bolder;
color: blue;
}
.active{
color:red;
}
<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="menu" />