mirror of
https://github.com/zen-browser/www.git
synced 2025-07-08 17:30:01 +02:00
refactor(components): improve layout and animation consistency in Features and Hero components
This commit is contained in:
parent
427dea3416
commit
1017d52859
2 changed files with 47 additions and 26 deletions
|
@ -46,10 +46,10 @@ const featureList = [
|
||||||
|
|
||||||
<section
|
<section
|
||||||
id="features"
|
id="features"
|
||||||
class="relative flex w-full flex-col items-center gap-8 py-8 text-center sm:gap-12 sm:py-12 xl:gap-16 xl:py-36"
|
class="relative flex w-full flex-col items-center gap-8 py-8 text-center sm:gap-12 sm:py-12 xl:gap-24 xl:py-36"
|
||||||
>
|
>
|
||||||
<!-- Section Header -->
|
<!-- Section Header -->
|
||||||
<div class="flex w-full flex-col items-center gap-4 sm:gap-6 xl:gap-12">
|
<div class="flex w-full flex-col items-center gap-4 sm:gap-6">
|
||||||
<h2 class="text-3xl sm:text-4xl md:text-6xl">
|
<h2 class="text-3xl sm:text-4xl md:text-6xl">
|
||||||
{
|
{
|
||||||
(titles || features.titles).map(title => {
|
(titles || features.titles).map(title => {
|
||||||
|
@ -70,7 +70,7 @@ const featureList = [
|
||||||
}
|
}
|
||||||
</h2>
|
</h2>
|
||||||
<p
|
<p
|
||||||
class="max-w-2xl text-base sm:text-lg"
|
class="max-w-4xl text-base sm:text-lg"
|
||||||
style="transform: translateY(20px); opacity: 0.001; filter: blur(4px)"
|
style="transform: translateY(20px); opacity: 0.001; filter: blur(4px)"
|
||||||
>
|
>
|
||||||
<span class="opacity-80">{features.description}</span>
|
<span class="opacity-80">{features.description}</span>
|
||||||
|
@ -78,25 +78,23 @@ const featureList = [
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Features Layout -->
|
<!-- Features Layout -->
|
||||||
<div class="space-between flex w-full flex-col gap-12 sm:gap-16 xl:gap-24">
|
<div id="showcase" class="flex w-full flex-col gap-12 sm:gap-16 xl:gap-36">
|
||||||
{
|
{
|
||||||
featureList.map((feature, index) => (
|
featureList.map((feature, index) => (
|
||||||
<div
|
<div class="flex w-full flex-col items-center gap-6 xl:gap-12">
|
||||||
class={`flex w-full flex-col items-center gap-6 xl:gap-12 ${index % 2 === 0 ? 'xl:flex-row-reverse' : 'xl:flex-row'}`}
|
|
||||||
>
|
|
||||||
<div class="flex flex-col items-center gap-4">
|
<div class="flex flex-col items-center gap-4">
|
||||||
<h3 class="text-2xl font-bold opacity-0 blur-sm sm:text-3xl xl:text-4xl">
|
<h3 class="text-3xl font-bold opacity-0 blur-sm sm:text-4xl xl:text-5xl">
|
||||||
{feature.title}
|
{feature.title}
|
||||||
</h3>
|
</h3>
|
||||||
<p
|
<p
|
||||||
class="text-base leading-relaxed sm:text-lg"
|
class="max-w-3xl text-center text-base leading-relaxed sm:text-lg"
|
||||||
style="transform: translateY(20px); opacity: 0.001; filter: blur(4px)"
|
style="transform: translateY(20px); opacity: 0.001; filter: blur(4px)"
|
||||||
>
|
>
|
||||||
<span class="opacity-80">{feature.description}</span>
|
<span class="opacity-80">{feature.description}</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<Video
|
<Video
|
||||||
class="max-h-[450px] w-[800px] rounded-xl border-2 border-dark object-cover shadow-lg"
|
class="w-full rounded-xl object-cover shadow-lg"
|
||||||
style="transform: translateY(20px); opacity: 0.001; filter: blur(4px)"
|
style="transform: translateY(20px); opacity: 0.001; filter: blur(4px)"
|
||||||
name={feature.video}
|
name={feature.video}
|
||||||
autoplay
|
autoplay
|
||||||
|
@ -117,22 +115,38 @@ const featureList = [
|
||||||
function initAnimations() {
|
function initAnimations() {
|
||||||
const debug = false
|
const debug = false
|
||||||
|
|
||||||
const elements = document.querySelectorAll(
|
const elements = document.querySelectorAll('#features h2 b, #features > div > p')
|
||||||
'#features h2 b, #features h3, #features p, #features video'
|
const showcase = document.getElementById('showcase') as HTMLElement
|
||||||
)
|
|
||||||
|
|
||||||
animate(elements, {
|
animate(elements, {
|
||||||
opacity: { from: 0.001, to: 1 },
|
opacity: { from: 0.001, to: 1 },
|
||||||
translateY: { from: 20, to: 0 },
|
translateY: { from: 20, to: 0 },
|
||||||
filter: { from: 'blur(4px)', to: 'blur(0px)' },
|
filter: { from: 'blur(4px)', to: 'blur(0px)' },
|
||||||
duration: 300,
|
duration: 300,
|
||||||
delay: stagger(150),
|
delay: stagger(200),
|
||||||
ease: 'cubicBezier(0.25, 0.1, 0.25, 1)',
|
ease: 'cubicBezier(0.25, 0.1, 0.25, 1)',
|
||||||
autoplay: onScroll({
|
autoplay: onScroll({
|
||||||
target: '#features',
|
target: '#features',
|
||||||
debug,
|
debug,
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
for (const element of showcase.children) {
|
||||||
|
const target = element.querySelectorAll('p, h3, video')
|
||||||
|
animate(target, {
|
||||||
|
opacity: { from: 0.001, to: 1 },
|
||||||
|
translateY: { from: 20, to: 0 },
|
||||||
|
filter: { from: 'blur(4px)', to: 'blur(0px)' },
|
||||||
|
duration: 300,
|
||||||
|
delay: stagger(150),
|
||||||
|
ease: 'cubicBezier(0.25, 0.1, 0.25, 1)',
|
||||||
|
autoplay: onScroll({
|
||||||
|
target,
|
||||||
|
enter: 'bottom-=200 top',
|
||||||
|
debug,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
initAnimations()
|
initAnimations()
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -17,7 +17,10 @@ const {
|
||||||
} = getUI(locale)
|
} = getUI(locale)
|
||||||
---
|
---
|
||||||
|
|
||||||
<header id="header" class="flex w-full flex-col items-center gap-12 py-32 text-center lg:gap-16">
|
<header
|
||||||
|
id="header"
|
||||||
|
class="flex w-full flex-col items-center gap-12 py-16 text-center lg:gap-16 lg:py-32"
|
||||||
|
>
|
||||||
<div class="flex h-full flex-col items-center justify-center gap-6 md:gap-12">
|
<div class="flex h-full flex-col items-center justify-center gap-6 md:gap-12">
|
||||||
<div class="flex flex-col items-center justify-center gap-4 md:gap-8">
|
<div class="flex flex-col items-center justify-center gap-4 md:gap-8">
|
||||||
<div>
|
<div>
|
||||||
|
@ -49,19 +52,13 @@ const {
|
||||||
<div
|
<div
|
||||||
class="flex w-2/3 flex-col items-center justify-center gap-3 sm:gap-6 md:w-fit md:flex-row"
|
class="flex w-2/3 flex-col items-center justify-center gap-3 sm:gap-6 md:w-fit md:flex-row"
|
||||||
>
|
>
|
||||||
<div
|
<div style="transform: translateY(20px); opacity: 0.001; filter: blur(4px)">
|
||||||
class="hero__link-group_button"
|
|
||||||
style="transform: translateY(20px); opacity: 0.001; filter: blur(4px)"
|
|
||||||
>
|
|
||||||
<Button class="w-fit" href={getLocalePath('/download')} isPrimary>
|
<Button class="w-fit" href={getLocalePath('/download')} isPrimary>
|
||||||
{hero.buttons.beta}
|
{hero.buttons.beta}
|
||||||
<ArrowRightIcon class="size-4" />
|
<ArrowRightIcon class="size-4" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div style="transform: translateY(20px); opacity: 0.001; filter: blur(4px)">
|
||||||
class="hero__link-group_button"
|
|
||||||
style="transform: translateY(20px); opacity: 0.001; filter: blur(4px)"
|
|
||||||
>
|
|
||||||
<Button class="w-fit" href={getLocalePath('/donate')}>
|
<Button class="w-fit" href={getLocalePath('/donate')}>
|
||||||
{hero.buttons.support}
|
{hero.buttons.support}
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -78,7 +75,7 @@ const {
|
||||||
playsinline
|
playsinline
|
||||||
preload="none"
|
preload="none"
|
||||||
class="rounded-xl"
|
class="rounded-xl"
|
||||||
style="transform: translateY(20px); opacity: 0.001; filter: blur(4px)"
|
style="transform: translateY(20px) scale(0.6); opacity: 0.001; filter: blur(4px); transform-origin: top;"
|
||||||
/>
|
/>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
@ -89,13 +86,12 @@ const {
|
||||||
const debug = false
|
const debug = false
|
||||||
|
|
||||||
const elements = document.querySelectorAll(
|
const elements = document.querySelectorAll(
|
||||||
'#header h1 b, #header p, #header .hero__link-group_button, #header video, #header ul'
|
'#header h1 b, #header p, #header div:has(a), #header video, #header ul'
|
||||||
)
|
)
|
||||||
|
|
||||||
animate(elements, {
|
animate(elements, {
|
||||||
// @ts-expect-error - element is HTMLElement
|
// @ts-expect-error - element is HTMLElement
|
||||||
opacity: element => {
|
opacity: element => {
|
||||||
// if ul is the element, return 0.8
|
|
||||||
if (element.tagName === 'UL') {
|
if (element.tagName === 'UL') {
|
||||||
return { from: 0.001, to: 0.8 }
|
return { from: 0.001, to: 0.8 }
|
||||||
}
|
}
|
||||||
|
@ -111,6 +107,17 @@ const {
|
||||||
debug,
|
debug,
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
animate('#header video', {
|
||||||
|
scale: { from: 0.6, to: 1 },
|
||||||
|
ease: 'cubicBezier(0.25, 0.1, 0.25, 1)',
|
||||||
|
autoplay: onScroll({
|
||||||
|
enter: 'bottom-=100 top',
|
||||||
|
leave: 'top+=100 bottom',
|
||||||
|
sync: true,
|
||||||
|
debug,
|
||||||
|
}),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
initAnimations()
|
initAnimations()
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue