score:2
I've modified your sandbox to make it work:
https://codesandbox.io/s/animable-timeline-reactjs-tiofz
For animation I used following CSS:
div { height: 200px; width: 10px; } .green-progress { background: linear-gradient(0, #00a36c, #00a36c) no-repeat, #ccc; background-size: 100% 0; animation: progressAnim 3s linear infinite forwards; } @keyframes progressAnim { 0% { background-size: 100% 0; } 100% { background-size: 100% 100%; } }
<div class="green-progress"></div>
To animate actual time line we'll remove vertical bar from first entry and there will be only checked circle. From second entry onwards we'll have a vertical bar and checked circle. To make them consistent they've been shifted upwards. To show progress, the bar will fill and then circle will be checked.Converted
App
to stateful component so that we can maintain animation states. In constructor, for each entry addedid
,startAnim
, andchecked
state. Here, we'll setstartAnim
flag to start animation on corresponding TimelineConnector. andchecked
is used to control checkmarking the circle.In
TimelineConnector
set class to green-progress ifthis.props.startAnim
is true. Also addedonAnimationEnd
handler as{() => this.props.onAnimDone(this.props.id)}
. This tells App component that animation is done on this component withid
.In
TimelineDot
usedprops.event.checked
to set the checked status.In App added a lifecycle hook
componentDidMount
which will get called when all components gets added to actual DOM. In the hook you checkmark the first circle and start animation on first TimelineConnector.When TimelineConnector is done with the animation, it calls
startNextAnim
in the App. In the method you first complete the checkmark on last entry. And start next animation if the entry hasstatus:true
.
We could've added delays to each animation and ran them at once. But parent controlling each component and each component notifying when animation is done makes it more flexible to update the code. You can have different animations for each entry, based on their state.
We can use react-spring animation library but things will get complicated. CSS animation is the simplest solution.
score:0
It's possible to animate a background. Please check the example below
.bg {
min-height: 300px;
width: 10px;
background: linear-gradient(0, red, red) no-repeat;
background-size: 100% 0;
animation: gradient 15s ease infinite;
}
@keyframes gradient {
0% {
background-size: 100% 0;
}
100% {
background-size: 100% 100%;
}
}
<div class="bg"></div>
Your TimelineConnector could be updated with include of that CSS class.
score:1
You can try this
/* timeline css */
@keyframes fill-color {
0% {
height: 0;
}
100% {
height: 100%;
}
}
@keyframes fill-color1 {
0% {
height: 0;
}
100% {
height: 50%;
}
}
@keyframes scaleup {
0% {
transform: scale(0);
}
100% {
transform: scale(1);
}
}
@keyframes fade {
0% {
color: rgba(black, 0.4);
}
100% {
color: rgba(black, 1);
}
}
body {
margin: 0;
padding: 0;
}
.timeline {
padding: 0;
list-style: none;
margin: 32px;
overflow: hidden;
position: relative;
}
.details {
margin-left: 48px;
border-bottom: 1px solid #f2f2f2;
min-height: 85px;
display: flex;
justify-content: center;
flex-direction: column;
}
.list,
.list-content {
position: relative;
width: 100%;
}
.list-content::before,
.list-content::after {
content: "";
display: block;
position: absolute;
left: 0;
transition: 0.2s all linear;
width: 0.714rem;
height: 0.714rem;
border-radius: 50%;
background-color: gray;
top: 50%;
z-index: 3;
margin-left: 0.35rem;
margin-top: rem(-8px);
}
.list-content::after {
z-index: 2;
}
.list {
position: relative;
width: 100%;
}
.list.active .list-content:before {
transform: scale(0);
width: 17px;
height: 17px;
border: 2px solid white;
background-color: red;
background-image: url("https://upload.wikimedia.org/wikipedia/commons/thumb/2/27/White_check.svg/2048px-White_check.svg.png");
background-position: center;
background-repeat: no-repeat;
background-size: 9px 7px;
margin-left: 0;
margin-top: -8px;
animation: scaleup 0.4s forwards;
}
.list:before,
.list:after {
content: "";
display: block;
position: absolute;
left: 0;
transition: 0.2s all linear;
width: 0.214rem;
margin-left: 0.6rem;
}
.list:before {
background: #f2f2f2;
height: 100%;
}
.list:after {
background: red;
height: 0;
z-index: 1;
}
.list:before {
top: -50%;
}
.list.active:after {
top: 0;
animation: fill-color 0.4s forwards;
}
.list:last-child:after {
display: none;
}
.list:last-child.active:after {
display: block;
bottom: 50%;
animation: fill-color1 0.4s forwards;
}
.list:last-child .details {
border-bottom: none;
}
.list:first-child:before {
display: none;
}
.list:first-child.active:after {
animation: fill-color1 0.4s forwards;
top: 50%;
}
.list:first-child.active:after {
animation-delay: 1s;
}
.list:first-child.active .list-content:before {
animation-delay: 0.5s;
}
.list:nth-child(2).active:after {
animation-delay: 2s;
}
.list:nth-child(2).active .list-content:before {
animation-delay: 2s;
}
.list:nth-child(3).active:after {
animation-delay: 3s;
}
.list:nth-child(3).active .list-content:before {
animation-delay: 3s;
}
.list:nth-child(4).active:after {
animation-delay: 4s;
}
.list:nth-child(4).active .list-content:before {
animation-delay: 4.15s;
}
<body>
<ul class="timeline">
<li class="list active">
<div class="list-content">
<div class="details">
<h4 class="status-title">Step 1</h4>
</div>
</div>
</li>
<li class="list active">
<div class="list-content">
<div class="details">
<h4 class="status-title">Step 2</h4>
</div>
</div>
</li>
<li class="list active">
<div class="list-content">
<div class="details">
<h4 class="status-title">Step 3</h4>
</div>
</div>
</li>
<li class="list active">
<div class="list-content">
<div class="details">
<h4 class="status-title">Step 4</h4>
</div>
</div>
</li>
</ul>
</body>
you can also check on Sandbox
here I have added active
class in all li
elements but if you want to two steps active so apply only first two li (i.e that class is conditional)
Source: stackoverflow.com
Related Query
- Event timeline with animation
- React onClick - pass event with parameter
- How to register event with useEffect hooks?
- Specifying onClick event type with Typescript and React.Konva
- Wrong React hooks behaviour with event listener
- Passing an additional parameter with an onChange event
- Warning: This synthetic event is reused for performance reasons happening with <input type="checkbox" />
- ReactJS can't set state from an event with event.persist()
- How to fix 'Static HTML elements with event handlers require a role.'?
- Updating a React Input text field with the value on onBlur event
- React - ul with onBlur event is preventing onClick from firing on li
- Add onClick event to a group element (svg) with react
- React event handlers with Typescript and JSX
- How do I trigger the change event on a react-select component with react-testing-library?
- Framer Motion exit animation not firing on accordion with react-router-dom
- Avoiding event chains with asynchronous data dependencies
- Using transitionend event listener with react to create a transition
- Cancel wheel event with e.preventDefault in react event bubbling
- Problem with keyboard event in ag-grid with react-select as a popup custom cell editor
- How to redirect to a gatsby-react page with an onclick event of a component?
- How to dynamically update the value for any input field with one event handler function, using hooks
- How to replace a component with another one upon event (button click) in react js
- How to achieve re-useable components with React and mouse event propagation?
- Using debouncer with React event
- How to add click event with React createElement
- How does event handlers with arrow functions achieve context binding
- Do I need to bind event handlers to `this` with TypeScript + React?
- What is the best way to test Window Scroll Event Handlers with Enzyme?
- how to remove an item from a list with a click event in ReactJS?
- How select part of text in a Textfield on onFocus event with material-UI in React?
More Query from same tag
- How do I add the ability to edit text within a react component?
- React - Prevent scrolling to top after changing query params
- How to make the part of search suggestion bold based on the user input?
- Adding a loading animation when loading in ReactJS
- Changing object in an array does not trigger change in html React
- Turn a CSS Linear Gradient Into An HTML Bootstrap Button
- Local storage is not keeping the data after page reload
- SetState in React ES6
- React functional components with methods
- In NextJS how to pass data from server.js to _app.js?
- Unhandled Rejection with FieldValue.arrayUnion()
- How to get reference to store in react/redux?
- Firebase deploy routes not working as they did with npm run (React)
- Zeit builds failing - Error: No output directory named "build" found
- String is incompatible with number (Flow typing optional property with default)
- React - Uncaught Error: Element type is invalid
- React: function passed in props is undefined
- JavaScript function syntax in Next.js / JSX?
- Strapi isn't showing both Content Types on GraphQL
- Creating dynamic table, Object.keys not allowing to return rows of table react
- What is the canonical React-Redux method to pass elements/references between atomic components?
- After $npm install, Getting Error: Cannot find module '../lib/utils/unsupported.js'
- React Native localeCompare not working on Android
- React Promise stuck on {Pending} Promise Status Fulfilled
- How do I return an array from a reducer?
- Add input value to Semantic UI Dropdown in React
- A way to trigger onFetchData in ReactTable
- react-router changes URL but does not render component
- How to pass an objects array to a component prop in ReactJS excluding objects whose key-value pairs have empty strings
- Redux: Handling State between Multiple Routes