Chess Grid Transition
vault-hyperiux/chess-grid-transitionFreeComponent
Staggered fullscreen grid wipe that sweeps blocks across the viewport during route changes
Install it
npx shadcn@latest add https://vault.hyperiux.com/r/chess-grid-transition.jsonSource
1// Built using Hyperiux Vault: https://vault.hyperiux.com23'use client'45import { TransitionRouter } from 'next-transition-router'6import React, { useEffect, useRef, useState, type ReactNode } from 'react'7import gsap from 'gsap'89function prefersReducedMotion() {10 if (typeof window === 'undefined') return false11 return window.matchMedia?.('(prefers-reduced-motion: reduce)')?.matches ?? false12}1314const DEFAULT_GRID_SIZE = 815const DEFAULT_COLOR = '#ff5f00'1617function clampNumber(value: number | undefined, min: number, max: number, fallback: number): number {18 const next = Number(value)19 if (!Number.isFinite(next)) return fallback20 return Math.min(max, Math.max(min, next))21}2223interface ChessGridTransitionProps {24 children?: ReactNode25 duration?: number26 gridSize?: number27 color?: string28}2930export default function ChessGridTransition({31 children,32 duration = 1,33 gridSize = DEFAULT_GRID_SIZE,34 color = DEFAULT_COLOR,35}: ChessGridTransitionProps) {36 const wrapperRef = useRef<HTMLDivElement | null>(null)37 const gridRef = useRef<HTMLDivElement | null>(null)3839 const [mounted, setMounted] = useState(false)40 const [isMobile, setIsMobile] = useState(false)41 const [isTablet, setIsTablet] = useState(false)4243 const safeDuration = clampNumber(duration, 0.25, 3, 1)44 const cols = Math.round(clampNumber(gridSize, 4, 16, DEFAULT_GRID_SIZE))45 const desktopRows = Math.max(2, Math.round(cols * 0.5))46 const mobileRows = Math.max(4, Math.round(cols * 1.125))47 const tabletRows = Math.max(4, Math.round(cols * 1.25))48 const overlap = 24950 useEffect(() => {51 const updateViewport = () => {52 const width = window.innerWidth53 setIsMobile(width <= 639)54 setIsTablet(width > 639 && width <= 1025)55 }5657 updateViewport()58 window.addEventListener('resize', updateViewport)59 return () => window.removeEventListener('resize', updateViewport)60 }, [])6162 const rows = isMobile ? mobileRows : isTablet ? tabletRows : desktopRows6364 const getRowCells = (cells: HTMLCollection, rowIndex: number) => {65 const rowCells = []66 for (let col = 0; col < cols; col++) {67 rowCells.push(cells[rowIndex * cols + col])68 }69 return rowCells70 }7172 const buildAnimation = (tl: gsap.core.Timeline, cells: HTMLCollection, direction = 1) => {73 const rowsArr = Array.from({ length: rows }, (_, i) => i)7475 rowsArr.forEach((rowIndex, rowOrderIndex) => {76 const rowCells = getRowCells(cells, rowIndex)7778 rowCells.forEach((cell, colIndex) => {79// … truncated
What it pulls in
npm packages
More from vault-hyperiux
All 120 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| 3D Portfolio Slider3d-portfolio-slider | vault-hyperiux | Components | Free | 3 deps | |
| Animated FAQanimated-faq | vault-hyperiux | Components | Free | 2 deps | |
| Animated Formanimated-form | vault-hyperiux | Components | Free | 1 dep | |
| Animated Modalanimated-modal | vault-hyperiux | Components | Free | 1 dep | |
| Tabsanimated-tabs | vault-hyperiux | Components | Free | 1 dep | |
| Animated Toggleanimated-toggle | vault-hyperiux | Components | Free | no deps | |
| Aperture Transitionaperture-transition | vault-hyperiux | Components | Free | 2 deps | |
| Arrow Fill Buttonarrow-fill-button | vault-hyperiux | Components | Free | 1 dep |
