feat: implement motion animations for Community and Hero components

This commit is contained in:
mr. M 2024-12-11 21:16:07 +01:00
parent 54346338d1
commit 20f3d76579
No known key found for this signature in database
GPG key ID: CBD57A2AEDBDA1FB
3 changed files with 42 additions and 27 deletions

7
src/animations.ts Normal file
View file

@ -0,0 +1,7 @@
export function getTitleAnimation(delay = 0) {
return {
initial: { opacity: 0, translateY: 20, filter: 'blur(4px)' },
whileInView: { opacity: 1, translateY: 0, filter: 'blur(0px)', transition: { duration: 0.3, delay } },
};
}

View file

@ -2,36 +2,46 @@
import Title from '../components/Title.astro' import Title from '../components/Title.astro'
import Description from '../components/Description.astro' import Description from '../components/Description.astro'
import Button from '../components/Button.astro' import Button from '../components/Button.astro'
import Circles from '../components/Circles.astro' import { motion } from 'motion/react';
import { Image } from 'astro:assets'
import myImage from '../assets/browser.png'
import { import {
Github, Github,
Check, Check,
} from 'lucide-astro' } from 'lucide-astro'
import { getTitleAnimation } from '../animations'
--- ---
<section <section
id="Community" id="Community"
class="flex w-full flex-col items-center text-center relative" class="flex w-full flex-col items-center text-center relative"
> >
<Title>Community Driven</Title> <Title>
<Description class="px-4 lg:px-0 lg:w-1/2"> <motion.span client:load viewport={{ once: true }} {...getTitleAnimation(0.2)}>
Community
</motion.span>
<motion.span client:load viewport={{ once: true }} {...getTitleAnimation(0.4)}>
Driven
</motion.span>
</Title>
<motion.p client:load viewport={{ once: true }} {...getTitleAnimation(0.6)} className="px-4 lg:px-0 lg:w-1/2">
We are a community-driven project. We listen to our users and build the We are a community-driven project. We listen to our users and build the
features they want. Zen focuses on privacy and customization, not on data collection. features they want. Zen focuses on privacy and customization, not on data collection.
</Description> </motion.p>
<div class="mt-6 gap-3 px-4 sm:px-0 w-full sm:gap-10 flex flex-wrap justify-center"> <div class="mt-6 gap-3 px-4 sm:px-0 w-full sm:gap-10 flex flex-wrap justify-center">
<motion.span client:load viewport={{ once: true }} {...getTitleAnimation(0.8)}>
<Button class:list={['px-4']} href="https://github.com/zen-browser"> <Button class:list={['px-4']} href="https://github.com/zen-browser">
<Github class="size-4" /> <Github class="size-4" />
<span>View on Github</span> <span>View on Github</span>
</Button> </Button>
<div class="flex items-center gap-4"> </motion.span>
<motion.div client:load viewport={{ once: true }} {...getTitleAnimation(1)} className="flex items-center gap-4">
<Check class="size-4" /> <Check class="size-4" />
<span>Fully Customizable</span> <span>Fully Customizable</span>
</div> </motion.div>
<div class="flex items-center gap-4"> <motion.div client:load viewport={{ once: true }} {...getTitleAnimation(1.2)} className="flex items-center gap-4">
<Check class="size-4" /> <Check class="size-4" />
<span>Privacy Focused</span> <span>Privacy Focused</span>
</div> </motion.div>
</div> </div>
</section> </section>

View file

@ -7,6 +7,7 @@ import myImage from '../assets/browser.png'
import { ArrowRight } from 'lucide-astro'; import { ArrowRight } from 'lucide-astro';
import { motion } from 'motion/react'; import { motion } from 'motion/react';
import { AnimatedText } from './AnimatedText'; import { AnimatedText } from './AnimatedText';
import { getTitleAnimation } from '../animations'
let titleAnimationCounter = 0; let titleAnimationCounter = 0;
function getNewAnimationDelay() { function getNewAnimationDelay() {
@ -14,11 +15,8 @@ function getNewAnimationDelay() {
return titleAnimationCounter * 0.15; return titleAnimationCounter * 0.15;
} }
function getTitleAnimation() { function getHeroTitleAnimation() {
return { return getTitleAnimation(getNewAnimationDelay());
initial: { opacity: 0, translateY: 20, filter: 'blur(4px)' },
animate: { opacity: 1, translateY: 0, filter: 'blur(0px)', transition: { duration: 0.3, delay: getNewAnimationDelay() } },
};
} }
--- ---
@ -29,37 +27,37 @@ function getTitleAnimation() {
> >
<div class="flex flex-col items-center h-full justify-center"> <div class="flex flex-col items-center h-full justify-center">
<Title class='text-left px-12 lg:px-0 md:text-center leading-[108px] md:!text-7xl lg:!text-9xl !font-normal'> <Title class='text-left px-12 lg:px-0 md:text-center leading-[108px] md:!text-7xl lg:!text-9xl !font-normal'>
<motion.span client:load {...getTitleAnimation()}> <motion.span client:load {...getHeroTitleAnimation()}>
Welcome Welcome
</motion.span> </motion.span>
<motion.span client:load {...getTitleAnimation()}> <motion.span client:load {...getHeroTitleAnimation()}>
to to
</motion.span> </motion.span>
<br class="hidden md:block" /> <br class="hidden md:block" />
<motion.span client:load {...getTitleAnimation()}> <motion.span client:load {...getHeroTitleAnimation()}>
a a
</motion.span> </motion.span>
<motion.span client:load {...getTitleAnimation()} className='italic'> <motion.span client:load {...getHeroTitleAnimation()} className='italic'>
calmer calmer
</motion.span> </motion.span>
<motion.span client:load {...getTitleAnimation()}> <motion.span client:load {...getHeroTitleAnimation()}>
internet internet
</motion.span> </motion.span>
</Title> </Title>
<motion.span client:load {...getTitleAnimation()}> <motion.span client:load {...getHeroTitleAnimation()}>
<Description class='text-left px-12 lg:px-0 md:text-center' <Description class='text-left px-12 lg:px-0 md:text-center'
>Beautifully designed, privacy-focused, and packed with features.<br >Beautifully designed, privacy-focused, and packed with features.<br
/>We care about your experience, not your data.</Description />We care about your experience, not your data.</Description
> >
</motion.span> </motion.span>
<div class="w-2/3 md:w-fit mt-6 gap-3 sm:gap-6 flex flex-col md:flex-row"> <div class="w-2/3 md:w-fit mt-6 gap-3 sm:gap-6 flex flex-col md:flex-row">
<motion.span client:load {...getTitleAnimation()}> <motion.span client:load {...getHeroTitleAnimation()}>
<Button class="w-full" href="/download" isPrimary> <Button class="w-full" href="/download" isPrimary>
Download Download
<ArrowRight class="size-4" /> <ArrowRight class="size-4" />
</Button> </Button>
</motion.span> </motion.span>
<motion.span client:load {...getTitleAnimation()}> <motion.span client:load {...getHeroTitleAnimation()}>
<Button href="#features">Start Exploring</Button> <Button href="#features">Start Exploring</Button>
</motion.span> </motion.span>
</div> </div>