Creating interactive and visually appealing applications often involves integrating real-time data with dynamic animations. Today, we will walk through building an app that demonstrates battery animation using the useBattery hook from the scriptkavi/hooks library. This hook provides real-time battery status, which we will use to animate a battery component dynamically.
Prerequisites
Before diving into the code, make sure you have the following setup:
Node.js and npm: Ensure you have Node.js and npm installed on your machine. You can download them from Node.js official site.
React/NextJS App: If you don’t have a React app, we will go through the steps to create one
scriptkavi/hooks: We will use the
useBattery
hook from this library.
Setting Up the NextJS App
Start by creating a new Next.js project using create-next-app
:
npx create-next-app@latest battery-animation --typescript --eslint
Now enter battery-animation app by running
cd battery-animation
Install package dependencies by running
npm install
Configuring scriptkavi/hooks in your app
Run the scriptkavi-hooks
init command to setup your project:
npx scriptkavi-hooks@latest init
You will be asked a few questions to configure hooks.json
:
Would you like to use TypeScript (recommended)? no/yes
Which codestyle would you like to use? › React Hooks
Configure the import alias for hooks: › @/hooks
Configure the import alias for utils: › @/lib/utils
Add Battery hook to your project
Now add battery hook by running this code:
npx scriptkavi-hooks@latest add battery
The command above will add the Battery
hook to your project.
Create a battery.tsx component
Now create a battery component in your app and paste this code:
import "@/styles/battery.css"; | |
import { useBattery } from "@/hooks/hook/battery"; | |
const Battery = () => { | |
let { supported, loading, level, charging } = useBattery(); | |
const renderBubbles = () => { | |
const bubbles = []; | |
for (let i = 0; i < 10; i++) { | |
bubbles.push( | |
<div key={`bubble-${i + 1}`} className={`bubble x${i + 1}`}></div> | |
); | |
} | |
return bubbles; | |
}; | |
if (!supported) { | |
return <div className="font-semibold">Battery is not supported</div>; | |
} | |
return ( | |
<div className="flex flex-col items-center"> | |
<div className=" bg-black h-[1.2rem] rounded-t-[0.9rem] w-12"></div> | |
<div className=" w-44 h-72 border-[0.7rem] rounded-[3rem] border-black mt-1 flex items-end overflow-hidden"> | |
{loading ? ( | |
<div className="h-full w-full flex items-center justify-center"> | |
Loading... | |
</div> | |
) : ( | |
<div | |
className={`w-full bg-[#79C943] rounded-[2rem] relative overflow-hidden`} | |
style={{ | |
height: `${(level || 0) * 100}%` as string, | |
borderTopLeftRadius: level && level < 1 ? 0 : undefined, | |
borderTopRightRadius: level && level < 1 ? 0 : undefined, | |
backgroundColor: | |
level && level < 0.25 | |
? "#FF1D25" | |
: level && level < 0.85 | |
? "#FFC41F" | |
: "#79C943", | |
}} | |
> | |
{charging ? <>{renderBubbles()}</> : null} | |
</div> | |
)} | |
</div> | |
<div className="h-8 font-semibold text-sm flex items-center justify-center space-x-2"> | |
<span>{charging ? "Charging..." : "On Battery"}</span> | |
<span>{level ? `(${level * 100}%)` : null}</span> | |
</div> | |
</div> | |
); | |
}; | |
export default Battery; |
Create a battery.css file
Now create a battery.css file in your app to provide styling and paste this code:
.bubble { | |
width: 20px; | |
height: 20px; | |
background: #ffffff; | |
border-radius: 200px; | |
-moz-border-radius: 200px; | |
-webkit-border-radius: 200px; | |
position: absolute; | |
z-index: 9; | |
} | |
.x1 { | |
-webkit-transform: scale(0.9); | |
-moz-transform: scale(0.9); | |
transform: scale(0.9); | |
opacity: 0.2; | |
-webkit-animation: moveclouds 3s linear infinite, sideWays 4s ease-in-out infinite alternate; | |
-moz-animation: moveclouds 3s linear infinite, sideWays 4s ease-in-out infinite alternate; | |
-o-animation: moveclouds 3s linear infinite, sideWays 4s ease-in-out infinite alternate; | |
} | |
.x2 { | |
left: 10%; | |
-webkit-transform: scale(0.6); | |
-moz-transform: scale(0.6); | |
transform: scale(0.6); | |
opacity: 0.5; | |
-webkit-animation: moveclouds 2s linear infinite, sideWays 2s ease-in-out infinite alternate; | |
-moz-animation: moveclouds 2s linear infinite, sideWays 2s ease-in-out infinite alternate; | |
-o-animation: moveclouds 2s linear infinite, sideWays 2s ease-in-out infinite alternate; | |
} | |
.x3 { | |
left: 25%; | |
-webkit-transform: scale(0.8); | |
-moz-transform: scale(0.8); | |
transform: scale(0.8); | |
opacity: 0.3; | |
-webkit-animation: moveclouds 1s linear infinite, sideWays 1s ease-in-out infinite alternate; | |
-moz-animation: moveclouds 1s linear infinite, sideWays 1s ease-in-out infinite alternate; | |
-o-animation: moveclouds 1s linear infinite, sideWays 1s ease-in-out infinite alternate; | |
} | |
.x4 { | |
left: 70%; | |
-webkit-transform: scale(0.75); | |
-moz-transform: scale(0.75); | |
transform: scale(0.75); | |
opacity: 0.35; | |
-webkit-animation: moveclouds 1.5s linear infinite, sideWays 2s ease-in-out infinite alternate; | |
-moz-animation: moveclouds 1.5s linear infinite, sideWays 2s ease-in-out infinite alternate; | |
-o-animation: moveclouds 1.5s linear infinite, sideWays 2s ease-in-out infinite alternate; | |
} | |
.x5 { | |
left: 40%; | |
-webkit-transform: scale(0.8); | |
-moz-transform: scale(0.8); | |
transform: scale(0.8); | |
opacity: 0.3; | |
-webkit-animation: moveclouds 2s linear infinite, sideWays 1s ease-in-out infinite alternate; | |
-moz-animation: moveclouds 2s linear infinite, sideWays 1s ease-in-out infinite alternate; | |
-o-animation: moveclouds 2s linear infinite, sideWays 1s ease-in-out infinite alternate; | |
} | |
.x6 { | |
left: 65%; | |
-webkit-transform: scale(0.9); | |
-moz-transform: scale(0.9); | |
transform: scale(0.9); | |
opacity: 0.2; | |
-webkit-animation: moveclouds 1s linear infinite, sideWays 2s ease-in-out infinite alternate; | |
-moz-animation: moveclouds 1s linear infinite, sideWays 2s ease-in-out infinite alternate; | |
-o-animation: moveclouds 1s linear infinite, sideWays 2s ease-in-out infinite alternate; | |
} | |
.x7 { | |
left: 29%; | |
-webkit-transform: scale(0.6); | |
-moz-transform: scale(0.6); | |
transform: scale(0.6); | |
opacity: 0.5; | |
-webkit-animation: moveclouds 4s linear infinite, sideWays 4s ease-in-out infinite alternate; | |
-moz-animation: moveclouds 4s linear infinite, sideWays 4s ease-in-out infinite alternate; | |
-o-animation: moveclouds 4s linear infinite, sideWays 4s ease-in-out infinite alternate; | |
} | |
.x8 { | |
left: 39%; | |
-webkit-transform: scale(0.8); | |
-moz-transform: scale(0.8); | |
transform: scale(0.8); | |
opacity: 0.3; | |
-webkit-animation: moveclouds 2.5s linear infinite, sideWays 2.5s ease-in-out infinite alternate; | |
-moz-animation: moveclouds 2.5s linear infinite, sideWays 2.5s ease-in-out infinite alternate; | |
-o-animation: moveclouds 2.5s linear infinite, sideWays 2.5s ease-in-out infinite alternate; | |
} | |
.x9 { | |
left: 85%; | |
-webkit-transform: scale(0.75); | |
-moz-transform: scale(0.75); | |
transform: scale(0.75); | |
opacity: 0.35; | |
-webkit-animation: moveclouds 3.5s linear infinite, sideWays 1s ease-in-out infinite alternate; | |
-moz-animation: moveclouds 3.5s linear infinite, sideWays 1s ease-in-out infinite alternate; | |
-o-animation: moveclouds 3.5s linear infinite, sideWays 1s ease-in-out infinite alternate; | |
} | |
.x10 { | |
left: 55%; | |
-webkit-transform: scale(0.8); | |
-moz-transform: scale(0.8); | |
transform: scale(0.8); | |
opacity: 0.3; | |
-webkit-animation: moveclouds 3s linear infinite, sideWays 2s ease-in-out infinite alternate; | |
-moz-animation: moveclouds 3s linear infinite, sideWays 2s ease-in-out infinite alternate; | |
-o-animation: moveclouds 3s linear infinite, sideWays 2s ease-in-out infinite alternate; | |
} | |
@-webkit-keyframes moveclouds { | |
0% { | |
top: 100%; | |
} | |
100% { | |
top: -10%; | |
} | |
} | |
@-webkit-keyframes sideWays { | |
0% { | |
margin-left:0px; | |
} | |
100% { | |
margin-left:50px; | |
} | |
} | |
@-moz-keyframes moveclouds { | |
0% { | |
top: 100%; | |
} | |
100% { | |
top: -10%; | |
} | |
} | |
@-moz-keyframes sideWays { | |
0% { | |
margin-left:0px; | |
} | |
100% { | |
margin-left:50px; | |
} | |
} | |
@-o-keyframes moveclouds { | |
0% { | |
top: 100%; | |
} | |
100% { | |
top: -10%; | |
} | |
} | |
@-o-keyframes sideWays { | |
0% { | |
margin-left:0px; | |
} | |
100% { | |
margin-left:50px; | |
} | |
} |
Now import this battery component in your page.tsx file. Your page.tsx file should look like this.
import Battery from "@/components/battery"; | |
export default function Home() { | |
return ( | |
<main className="flex min-h-screen flex-col justify-center items-center"> | |
<div className="flex flex-col items-center justify-center"> | |
<Battery /> | |
</div> | |
</main> | |
); | |
} |
Now run the project by running
npm run dev
That’s it
Your app will show a battery like this. You can see the animation by connecting your device to the charger

Join the Revolution
scriptkavi/hooks library is open source so you can start contributing to the project by adding more hooks. You can find the github project here.
Our mission is to empower developers to build amazing applications with ease and efficiency. By providing a robust set of hooks, we aim to transform the way you develop with React. Explore our documentation, contribute to the project, and be part of the revolution in React development.
Conclusion
scriptkavi/hooks is an invaluable collection of reusable hooks designed to enhance React development by simplifying the integration of commonly used functionalities. With an easy installation process for Next.js applications, developers can quickly set up and incorporate these hooks to improve state management and handle side effects effectively. The library supports popular frameworks like NextJS and Vite, ensuring broad applicability.
By offering an open-source platform, scriptkavi/hooks invites developers to contribute and expand its capabilities, fostering a collaborative community aimed at advancing React development practices. Whether you’re adding hooks like debounce or exploring new ones, scriptkavi/hooks empowers developers to build robust applications with greater ease and efficiency. Embrace the revolution in React development by exploring the library, contributing to its growth, and leveraging the extensive documentation available.
Top comments (0)