mirror of
https://github.com/zen-browser/www.git
synced 2025-07-08 01:10:02 +02:00
Refactor homepage components: replace Features with HomepageFeatures and add HomepageFeature component for better structure and functionality
This commit is contained in:
parent
04b3db1a75
commit
864e559618
3 changed files with 126 additions and 2 deletions
45
src/components/HomepageFeature.astro
Normal file
45
src/components/HomepageFeature.astro
Normal file
|
@ -0,0 +1,45 @@
|
|||
|
||||
---
|
||||
import { motion } from 'motion/react'
|
||||
import { getTitleAnimation } from '~/animations'
|
||||
import Description from './Description.astro'
|
||||
import Video from './Video.astro'
|
||||
|
||||
const { title, video, description, alt, id } = Astro.props
|
||||
---
|
||||
|
||||
<section
|
||||
id={id}
|
||||
class="relative flex w-full flex-col items-center gap-12 py-12 text-start md:text-center lg:py-36"
|
||||
>
|
||||
<div class="flex w-full flex-col items-center">
|
||||
<Description class="text-6xl font-bold">
|
||||
<motion.span client:load {...getTitleAnimation(0.2)}>
|
||||
{title}
|
||||
</motion.span>
|
||||
</Description>
|
||||
<motion.p
|
||||
client:load
|
||||
{...getTitleAnimation(0.4)}
|
||||
className="lg:w-1/2 lg:px-0 text-center text-wrap"
|
||||
>
|
||||
{description}
|
||||
</motion.p>
|
||||
</div>
|
||||
<motion.span
|
||||
className="flex max-w-full lg:max-w-none lg:flex-none"
|
||||
client:load
|
||||
{...getTitleAnimation(0.8)}
|
||||
>
|
||||
<Video
|
||||
src={video}
|
||||
alt={alt}
|
||||
class="rounded-3xl shadow-md lg:mx-auto dark:opacity-80"
|
||||
loop
|
||||
muted
|
||||
playsinline
|
||||
preload="none"
|
||||
id=`video-${id}`
|
||||
/>
|
||||
</motion.span>
|
||||
</section>
|
79
src/components/HomepageFeatures.astro
Normal file
79
src/components/HomepageFeatures.astro
Normal file
|
@ -0,0 +1,79 @@
|
|||
---
|
||||
import { getLocale, getUI } from '~/utils/i18n'
|
||||
import HomepageFeature from './HomepageFeature.astro'
|
||||
const locale = getLocale(Astro)
|
||||
|
||||
import CompactModeVideo from '~/assets/CompactMode.webm'
|
||||
import GlanceVideo from '~/assets/Glance.webm'
|
||||
import SplitViewsVideo from '~/assets/SplitViews.webm'
|
||||
import WorkspacesVideo from '~/assets/Workspaces.webm'
|
||||
|
||||
const {
|
||||
routes: {
|
||||
index: { features },
|
||||
},
|
||||
} = getUI(locale)
|
||||
---
|
||||
|
||||
<HomepageFeature
|
||||
{...features.featureTabs.workspaces}
|
||||
video={WorkspacesVideo}
|
||||
id="workspaces"
|
||||
/>
|
||||
<HomepageFeature
|
||||
{...features.featureTabs.compactMode}
|
||||
video={CompactModeVideo}
|
||||
id="compactMode"
|
||||
/>
|
||||
<HomepageFeature
|
||||
{...features.featureTabs.splitView}
|
||||
video={SplitViewsVideo}
|
||||
id="splitView"
|
||||
/>
|
||||
<HomepageFeature
|
||||
{...features.featureTabs.glance}
|
||||
video={GlanceVideo}
|
||||
id="glance"
|
||||
/>
|
||||
|
||||
<script>
|
||||
const ids = ['workspaces', 'compactMode', 'splitView', 'glance'];
|
||||
const videos = ids.map(id => document.getElementById(`video-${id}`)).filter(Boolean) as HTMLVideoElement[];
|
||||
|
||||
function isElementVisible(el: HTMLElement) {
|
||||
var rect = el.getBoundingClientRect(),
|
||||
vWidth = window.innerWidth || document.documentElement.clientWidth,
|
||||
vHeight = window.innerHeight || document.documentElement.clientHeight,
|
||||
efp = function (x: number, y: number) { return document.elementFromPoint(x, y) };
|
||||
|
||||
// Return false if it's not in the viewport
|
||||
if (rect.right < 0 || rect.bottom < 0
|
||||
|| rect.left > vWidth || rect.top > vHeight)
|
||||
return false;
|
||||
|
||||
// Return true if any of its four corners are visible
|
||||
return (
|
||||
el.contains(efp(rect.left, rect.top))
|
||||
|| el.contains(efp(rect.right, rect.top))
|
||||
|| el.contains(efp(rect.right, rect.bottom))
|
||||
|| el.contains(efp(rect.left, rect.bottom))
|
||||
);
|
||||
}
|
||||
|
||||
function checkVideoSrolls() {
|
||||
videos.forEach(video => {
|
||||
// Check if the video is in the viewport. But it doesn't have to be fully in the viewport.
|
||||
// This is to prevent the video from playing when the user scrolls down and the video is not fully in the viewport.
|
||||
if (isElementVisible(video.parentNode?.parentNode as HTMLElement)) {
|
||||
video.play();
|
||||
} else {
|
||||
video.pause();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Play videos on scroll
|
||||
window.addEventListener('scroll', checkVideoSrolls);
|
||||
window.addEventListener('DOMContentLoaded', checkVideoSrolls);
|
||||
</script>
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
import Community from '~/components/Community.astro'
|
||||
import Features from '~/components/Features.astro'
|
||||
import Hero from '~/components/Hero.astro'
|
||||
import HomepageFeatures from '~/components/HomepageFeatures.astro'
|
||||
import Sponsors from '~/components/Sponsors.astro'
|
||||
import Layout from '~/layouts/Layout.astro'
|
||||
import { getLocale, getUI } from '~/utils/i18n'
|
||||
|
@ -19,7 +19,7 @@ const { layout } = getUI(locale)
|
|||
>
|
||||
<main class="container">
|
||||
<Hero />
|
||||
<Features />
|
||||
<HomepageFeatures />
|
||||
<Sponsors showSponsors />
|
||||
<Community />
|
||||
</main>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue