Perspective Flow Demo
unlumen-ui/demo-perspective-flowFreeComponent
Demo showing the Perspective Flow component.
Install it
npx shadcn@latest add https://ui.unlumen.com/r/demo-perspective-flow.jsonSource
1"use client";23import { useEffect, useMemo, useRef, useState } from "react";4import Lenis from "lenis";56import {7 PerspectiveFlow,8 type PerspectiveFlowProps,9} from "@/components/unlumen-ui/perspective-flow";1011type PerspectiveFlowDemoProps = Pick<12 PerspectiveFlowProps,13 "engine" | "perspective" | "gap" | "verticalGap" | "minItemWidth"14> & {15 imageCount?: number;16 smooth?: boolean;17};1819export default function PerspectiveFlowDemo({20 engine = "gsap",21 perspective = 2000,22 gap = 32,23 verticalGap = 92,24 minItemWidth = 170,25 imageCount = 24,26 smooth = true,27}: PerspectiveFlowDemoProps) {28 const scrollContainerRef = useRef<HTMLDivElement>(null);29 const contentRef = useRef<HTMLDivElement>(null);30 const [previewWidth, setPreviewWidth] = useState(900);3132 useEffect(() => {33 const node = scrollContainerRef.current;34 if (!node) return;3536 const update = () => setPreviewWidth(node.clientWidth || 900);37 update();3839 const observer = new ResizeObserver(update);40 observer.observe(node);4142 return () => observer.disconnect();43 }, []);4445 useEffect(() => {46 const wrapper = scrollContainerRef.current;47 const content = contentRef.current;48 if (!smooth || !wrapper || !content) return;4950 const lenis = new Lenis({51 wrapper,52 content,53 smoothWheel: true,54 wheelMultiplier: 0.95,55 lerp: 0.09,56 });5758 let rafId = 0;59 const raf = (time: number) => {60 lenis.raf(time);61 rafId = window.requestAnimationFrame(raf);62 };6364 rafId = window.requestAnimationFrame(raf);6566 return () => {67 window.cancelAnimationFrame(rafId);68 lenis.destroy();69 };70 }, [smooth]);7172 const images = useMemo(() => {73 const availableWidth = Math.max(320, previewWidth);74 const estimatedColumns = Math.max(75 1,76 Math.min(2, Math.round(availableWidth / (minItemWidth + 30))),77 );78 const targetWidth = Math.max(79 260,80 Math.round(81 (availableWidth - (estimatedColumns - 1) * 24) / estimatedColumns,82 ),83 );84 const targetHeight = Math.round(targetWidth * 1.2);8586 return Array.from({ length: imageCount }, (_, i) => ({87 src: `https://picsum.photos/seed/ps${i + 1}/${targetWidth}/${targetHeight}`,88 alt: `Demo image ${i + 1}`,89 }));90 }, [imageCount, minItemWidth, previewWidth]);9192 const reloadKey = useMemo(93 () =>94 [95 engine,96 perspective,97 gap,98 verticalGap ?? "",99 minItemWidth,100 imageCount,101// … truncated
What it pulls in
Other registry items
Files it writes
More from Unlumen Ui
All 233 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| AI Chatai-chat | Unlumen Ui | Components | Paid | 2 deps | |
| Vercel Animate Countanimate-count | Unlumen Ui | Components | Free | 1 dep | |
| Animate Digitsanimate-digits | Unlumen Ui | Components | Free | 1 dep | |
| Animated Inputanimate-text-input-typing | Unlumen Ui | Components | Paid | 1 dep | |
| Animated Listanimated-list | Unlumen Ui | Components | Free | 1 dep | |
| Apple Switchapple-switch | Unlumen Ui | Components | Free | 1 dep | |
| Aurora Barsaurora-bars | Unlumen Ui | Components | Free | 1 dep | |
| Aurora Bluraurora-blur | Unlumen Ui | Components | Free | 2 deps |
