Refactor homepage components: replace Features with HomepageFeatures and add HomepageFeature component for better structure and functionality

This commit is contained in:
Mr. M 2025-05-31 00:47:26 +02:00
parent 04b3db1a75
commit 864e559618
No known key found for this signature in database
GPG key ID: 6292C4C8F8652B18
3 changed files with 126 additions and 2 deletions

View 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>

View 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>

View file

@ -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>