Add Lottie animations to onboarding steps and integrate LottieAnimation component

- Introduced a new LottieAnimation component to handle Lottie animations in the onboarding flow.
- Updated the Onboarding component to include Lottie animations for each step, enhancing visual engagement.
- Added multiple Lottie animation files to the public/lottie directory for use in onboarding steps.
- Adjusted the ConnectStep and GetStartedStep components to improve messaging and user experience.

These changes aim to create a more dynamic and engaging onboarding experience for users, utilizing animations to illustrate key steps in the process.
This commit is contained in:
Steven Enamakel
2026-01-28 02:24:06 +05:30
parent 1500ca7a28
commit 334673e59a
14 changed files with 465 additions and 393 deletions
+20
View File
@@ -12,6 +12,7 @@
"@tauri-apps/plugin-deep-link": "^2",
"@tauri-apps/plugin-opener": "^2",
"@types/react-router-dom": "^5.3.3",
"lottie-react": "^2.4.1",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-router-dom": "^7.13.0"
@@ -2220,6 +2221,25 @@
"dev": true,
"license": "MIT"
},
"node_modules/lottie-react": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/lottie-react/-/lottie-react-2.4.1.tgz",
"integrity": "sha512-LQrH7jlkigIIv++wIyrOYFLHSKQpEY4zehPicL9bQsrt1rnoKRYCYgpCUe5maqylNtacy58/sQDZTkwMcTRxZw==",
"license": "MIT",
"dependencies": {
"lottie-web": "^5.10.2"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/lottie-web": {
"version": "5.13.0",
"resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.13.0.tgz",
"integrity": "sha512-+gfBXl6sxXMPe8tKQm7qzLnUy5DUPJPKIyRHwtpCpyUEYjHYRJC/5gjUvdkuO2c3JllrPtHXH5UJJK8LRYl5yQ==",
"license": "MIT"
},
"node_modules/lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+2 -1
View File
@@ -11,9 +11,10 @@
},
"dependencies": {
"@tauri-apps/api": "^2",
"@tauri-apps/plugin-opener": "^2",
"@tauri-apps/plugin-deep-link": "^2",
"@tauri-apps/plugin-opener": "^2",
"@types/react-router-dom": "^5.3.3",
"lottie-react": "^2.4.1",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-router-dom": "^7.13.0"
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
{"v":"4.8.0","meta":{"g":"LottieFiles AE 3.0.2","a":"","k":"","d":"","tc":""},"fr":60,"ip":0,"op":77,"w":500,"h":500,"nm":"security tick","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"tick","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250,250,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.094,0.094,0.094],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0.067,0.067,-0.067]},"t":32,"s":[62,62,100]},{"t":56,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-52.947,0],[-17.649,35.298],[52.947,-35.298]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":25.537,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.178],"y":[1]},"o":{"x":[0.21],"y":[0]},"t":32,"s":[0]},{"t":62,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"shield","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":4,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.97],"y":[1]},"o":{"x":[0.03],"y":[0]},"t":0,"s":[250]},{"i":{"x":[0.97],"y":[1]},"o":{"x":[0.03],"y":[0]},"t":20,"s":[250]},{"t":40,"s":[250]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.174],"y":[0.822]},"t":0,"s":[319]},{"i":{"x":[0.334],"y":[1]},"o":{"x":[0.308],"y":[0]},"t":20,"s":[197]},{"t":40,"s":[250]}],"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.174,0.174,0.174],"y":[0.822,0.822,-0.822]},"t":0,"s":[46,46,100]},{"t":20,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.094,"y":1},"o":{"x":0.252,"y":0},"t":25,"s":[{"i":[[-29.271,0],[0,-29.271],[29.271,0],[0,29.271]],"o":[[29.271,0],[0,29.271],[-29.271,0],[0,-29.271]],"v":[[0,-53],[53,0],[0,53],[-53,0]],"c":true}]},{"t":56,"s":[{"i":[[-2.504,1.787],[-85.122,-7.093],[120.419,-40.532],[0,158.319]],"o":[[2.504,1.787],[0,158.319],[-120.419,-40.532],[85.122,-7.093]],"v":[[0,-169.229],[141.87,-126.668],[0,169.229],[-141.87,-126.668]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.360784322023,0.800000011921,0.474509805441,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":300,"st":0,"bm":0}],"markers":[]}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+39
View File
@@ -0,0 +1,39 @@
import { useEffect, useState } from 'react';
import { useLottie } from 'lottie-react';
interface LottieAnimationProps {
src: string;
className?: string;
height?: number;
width?: number;
}
const LottieAnimation = ({ src, className = '', height = 200, width = 200 }: LottieAnimationProps) => {
const [animationData, setAnimationData] = useState<unknown>(null);
useEffect(() => {
fetch(src)
.then((response) => response.json())
.then((data) => setAnimationData(data))
.catch((error) => console.error('Failed to load Lottie animation:', error));
}, [src]);
const options = {
animationData,
loop: true,
autoplay: true,
};
const { View } = useLottie(options, {
height,
width,
});
if (!animationData) {
return <div className={className} style={{ height, width }} />;
}
return <div className={className}>{View}</div>;
};
export default LottieAnimation;
+15 -2
View File
@@ -1,6 +1,7 @@
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import ProgressIndicator from '../../components/ProgressIndicator';
import LottieAnimation from '../../components/LottieAnimation';
import FeaturesStep from './steps/FeaturesStep';
import PrivacyStep from './steps/PrivacyStep';
import AnalyticsStep from './steps/AnalyticsStep';
@@ -12,6 +13,15 @@ const Onboarding = () => {
const [currentStep, setCurrentStep] = useState(1);
const totalSteps = 5;
// Lottie animation files for each step
const stepAnimations = [
'/lottie/wave.json', // Step 1 - Features
'/lottie/safe3.json', // Step 2 - Privacy
'/lottie/analytics.json', // Step 3 - Analytics
'/lottie/connect2.json', // Step 4 - Connect
'/lottie/trophy.json', // Step 5 - Get Started
];
const handleNext = () => {
if (currentStep < totalSteps) {
setCurrentStep(currentStep + 1);
@@ -50,16 +60,19 @@ const Onboarding = () => {
return (
<div className="min-h-screen relative flex items-center justify-center">
<div className="relative z-10 max-w-lg w-full mx-4">
<div className="flex justify-center mb-6">
<LottieAnimation src={stepAnimations[currentStep - 1]} height={120} width={120} />
</div>
<ProgressIndicator currentStep={currentStep} totalSteps={totalSteps} />
{renderStep()}
{currentStep > 1 && (
{/* {currentStep > 1 && (
<button
onClick={handleBack}
className="mt-6 outline-none border-none w-full opacity-60 hover:opacity-100 text-sm font-medium transition-opacity"
>
← Back
</button>
)}
)} */}
</div>
</div>
);
+9 -10
View File
@@ -26,12 +26,12 @@ const ConnectStep = ({ onNext }: ConnectStepProps) => {
const handleConnect = (provider: string) => {
// In a real app, this would handle OAuth
console.log(`Connecting to ${provider}`);
if (provider === 'telegram') {
setIsTelegramModalOpen(true);
return;
}
// Don't auto-advance for coming soon items
if (!connectOptions.find(opt => opt.id === provider)?.comingSoon) {
onNext();
@@ -47,32 +47,32 @@ const ConnectStep = ({ onNext }: ConnectStepProps) => {
{
id: 'google',
name: 'Google',
description: 'Get insights from your emails, contacts and calendar events',
description: 'Manage emails, contacts and calendar events',
icon: <GoogleIcon />,
},
{
id: 'notion',
name: 'Notion',
description: 'Read through tasks, documents and everything else in your Notion workspace',
description: 'Manage tasks, documents and everything else in your Notion',
icon: <img src={NotionIcon} alt="Notion" className="w-5 h-5" />,
},
{
id: 'telegram',
name: 'Telegram',
description: 'Go through chats, automate messages and get insights from your conversations.',
description: 'Organize chats, automate messages and get insights.',
icon: <img src={TelegramIcon} alt="Telegram" className="w-5 h-5" />,
},
{
id: 'wallet',
name: 'Web3 Wallet',
description: 'Trade the trenches while also managing your portfolio with deep insights.',
description: 'Trade the trenches in a safe and secure way.',
icon: <img src={MetamaskIcon} alt="Metamask" className="w-5 h-5" />,
comingSoon: true,
},
{
id: 'exchange',
name: 'Crypto Trading Exchanges',
description: 'Connect to your trading accounts to make trades and manage your portfolio with deep insights.',
description: 'Connect tand make trades with deep insights.',
icon: <img src={BinanceIcon} alt="Binance" className="w-5 h-5" />,
comingSoon: true,
},
@@ -83,8 +83,7 @@ const ConnectStep = ({ onNext }: ConnectStepProps) => {
<div className="text-center mb-4">
<h1 className="text-xl font-bold mb-2">Connect Accounts</h1>
<p className="opacity-70 text-sm">
To get the most out of AlphaHuman, you need to connect at least one account. The more
accounts you connect, the more powerful the intelligence will be.
The more accounts you connect, the more powerful the intelligence will be.
</p>
</div>
@@ -114,7 +113,7 @@ const ConnectStep = ({ onNext }: ConnectStepProps) => {
<div className="mt-4 p-4 bg-sage-500/10 rounded-xl border border-sage-500/30">
<div className="flex items-start space-x-2">
<div>
<p className="font-medium text-sm">🔒 Remember everything stays private &amp; encrypted!</p>
<p className="font-medium text-sm">🔒 Remember everything is private &amp; encrypted!</p>
<p className="opacity-70 text-xs mt-1">All data and credentials are stored
locally and follows a strict zero-data retention policy so you won't have to worry about anything
getting leaked.</p>
+2 -46
View File
@@ -18,58 +18,14 @@ const GetStartedStep = ({ onComplete }: GetStartedStepProps) => {
<div className="text-center mb-4">
<h1 className="text-xl font-bold mb-2">You Are Ready, Soldier!</h1>
<p className="opacity-70 text-sm">
Alright you're all set up, just message your assistant and you're ready to cook!
Alright you're all set up, just message your assistant and you're ready to cook! Remember to keep this tab open to keep the connection alive.
</p>
</div>
<ConnectionIndicator
description="Your browser is now connected to the AlphaHuman AI Models. Keep this tab open to keep the connection alive."
description="Your browser is now connected to the AlphaHuman AI Models. Please keep this tab open."
/>
<div className="space-y-3 mb-4">
<div className="bg-stone-800/50 rounded-xl p-4 border border-stone-700">
<div className="flex items-start space-x-3">
<div className="w-8 h-8 bg-primary-500 rounded-lg flex items-center justify-center flex-shrink-0">
<span className="text-white font-bold text-xs">1</span>
</div>
<div>
<h3 className="font-semibold mb-1 text-sm">Open Telegram</h3>
<p className="opacity-70 text-xs">
Click the button below to open the AlphaHuman bot in Telegram
</p>
</div>
</div>
</div>
<div className="bg-stone-800/50 rounded-xl p-4 border border-stone-700">
<div className="flex items-start space-x-3">
<div className="w-8 h-8 bg-primary-500 rounded-lg flex items-center justify-center flex-shrink-0">
<span className="text-white font-bold text-xs">2</span>
</div>
<div>
<h3 className="font-semibold mb-1 text-sm">Keep this tab open</h3>
<p className="opacity-70 text-xs">
Keep this tab open to keep the connection alive. You can message the assistant with the button below.
</p>
</div>
</div>
</div>
<div className="bg-stone-800/50 rounded-xl p-4 border border-stone-700">
<div className="flex items-start space-x-3">
<div className="w-8 h-8 bg-primary-500 rounded-lg flex items-center justify-center flex-shrink-0">
<span className="text-white font-bold text-xs">3</span>
</div>
<div>
<h3 className="font-semibold mb-1 text-sm">Start Messaging</h3>
<p className="opacity-70 text-xs">
Send a message to the bot to get started. Try asking about crypto prices, market trends, or anything about your chats!
</p>
</div>
</div>
</div>
</div>
<button
onClick={handleOpenTelegram}
className="w-full flex items-center justify-center space-x-3 bg-blue-500 hover:bg-blue-600 active:bg-blue-700 text-white font-semibold py-2.5 text-sm rounded-xl transition-all duration-300 hover:shadow-medium mb-3"
+371 -334
View File
File diff suppressed because it is too large Load Diff