ultisuite-client/components/landing/product/product-demos/ultidrive-browser-demo.tsx
R3D347HR4Y efaaf16f60
Some checks are pending
E2E / Playwright e2e (push) Waiting to run
feat: update metadata and layout for new product pages
- Refactored metadata for contacts, administration, and Ulticards pages to utilize dynamic app names and descriptions.
- Introduced new product pages for Ultiai, Ultical, Ulticards, Ultidrive, Ultimail, and Ultimeet with appropriate metadata.
- Enhanced layout components to ensure consistent styling and functionality across new product sections.
- Updated various components to replace hardcoded labels with dynamic references to improve maintainability and consistency.
2026-06-19 22:11:42 +02:00

67 lines
2.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client"
import { useLayoutEffect, useRef, useState } from "react"
import { ProductDemoFrame } from "@/components/landing/product/product-demo-frame"
import { ScaledPreviewIframe } from "@/components/landing/product/scaled-preview-iframe"
// Viewport logique réduit : l'explorateur est rendu plus petit puis agrandi
// dans le cadre — zoom ~25 % par rapport à la référence 1440×900.
export const ULTIDRIVE_BROWSER_DEMO_VIEWPORT_WIDTH = 1080
export const ULTIDRIVE_BROWSER_DEMO_VIEWPORT_HEIGHT = 675
export const ULTIDRIVE_BROWSER_DEMO_ASPECT_RATIO =
ULTIDRIVE_BROWSER_DEMO_VIEWPORT_WIDTH / ULTIDRIVE_BROWSER_DEMO_VIEWPORT_HEIGHT
function isInDemoViewport(node: HTMLElement, margin = 120): boolean {
const rect = node.getBoundingClientRect()
return rect.top < window.innerHeight + margin && rect.bottom > -margin
}
export function UltidriveBrowserDemo() {
const ref = useRef<HTMLDivElement>(null)
const [visible, setVisible] = useState(false)
useLayoutEffect(() => {
const node = ref.current
if (!node) return
if (isInDemoViewport(node)) {
setVisible(true)
return
}
const observer = new IntersectionObserver(
(entries) => {
if (entries.some((entry) => entry.isIntersecting)) {
setVisible(true)
observer.disconnect()
}
},
{ rootMargin: "120px 0px" }
)
observer.observe(node)
return () => observer.disconnect()
}, [])
return (
<div ref={ref}>
<ProductDemoFrame
fakeUrl="suite.votre-domaine.fr/drive"
fullscreenHref="/demo/drive"
hint="Démo interactive — parcourez, uploadez, prévisualisez. Zéro rétention."
aspectRatio={ULTIDRIVE_BROWSER_DEMO_ASPECT_RATIO}
>
<div className="absolute inset-0 bg-[var(--landing-bg)]">
<ScaledPreviewIframe
src="/demo/drive"
title="Démo explorateur UltiDrive"
viewportWidth={ULTIDRIVE_BROWSER_DEMO_VIEWPORT_WIDTH}
viewportHeight={ULTIDRIVE_BROWSER_DEMO_VIEWPORT_HEIGHT}
fit="cover"
ready={visible}
/>
</div>
</ProductDemoFrame>
</div>
)
}