{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "hero-device-assemble", "title": "Hero Device Assemble", "description": "Floating device layers spring together into a laptop or phone mockup, then the screen wakes with a shimmer.", "dependencies": [ "remotion" ], "files": [ { "path": "registry/remocn/hero-device-assemble/index.tsx", "content": "\"use client\";\n\nimport { interpolate, spring, useCurrentFrame, useVideoConfig } from \"remotion\";\n\nexport interface HeroDeviceAssembleProps {\n assembleStart?: number;\n device?: \"laptop\" | \"phone\";\n accentColor?: string;\n speed?: number;\n className?: string;\n}\n\nconst FONT_FAMILY =\n \"var(--font-geist-sans), -apple-system, BlinkMacSystemFont, sans-serif\";\n\nfunction MockUI({ accentColor }: { accentColor: string }) {\n return (\n \n {/* Title bar */}\n \n \n \n \n \n
\n {/* Sidebar */}\n \n \n \n \n \n
\n {/* Content */}\n \n \n \n \n \n \n \n \n \n \n \n \n );\n}\n\nexport function HeroDeviceAssemble({\n assembleStart = 0,\n device = \"laptop\",\n accentColor = \"#22c55e\",\n speed = 1,\n className,\n}: HeroDeviceAssembleProps) {\n const frame = useCurrentFrame() * speed;\n const { fps } = useVideoConfig();\n\n const assemble = spring({\n frame: frame - assembleStart,\n fps,\n config: { mass: 1.4, damping: 12, stiffness: 90 },\n durationInFrames: 60,\n });\n\n // Layer translateZ values from far -> 0\n const lidZ = interpolate(assemble, [0, 1], [1000, 0]);\n const baseZ = interpolate(assemble, [0, 1], [-800, 0]);\n const bezelZ = interpolate(assemble, [0, 1], [600, 0]);\n const screenZ = interpolate(assemble, [0, 1], [300, 0]);\n\n // Parent rotation easing to 0\n const rotX = interpolate(assemble, [0, 1], [-22, 0]);\n const rotY = interpolate(assemble, [0, 1], [28, 0]);\n\n // Layer opacity fade in slightly during assembly\n const layerOpacity = interpolate(assemble, [0, 0.4], [0, 1], {\n extrapolateLeft: \"clamp\",\n extrapolateRight: \"clamp\",\n });\n\n // Settle frame: after assemble ~ 0.95\n const settleFrame = assembleStart + 45;\n const screenWake = interpolate(\n frame,\n [settleFrame, settleFrame + 18],\n [0, 1],\n { extrapolateLeft: \"clamp\", extrapolateRight: \"clamp\" },\n );\n\n // Shimmer sweep across screen (after wake)\n const shimmerProgress = interpolate(\n frame,\n [settleFrame + 6, settleFrame + 30],\n [-1, 2],\n { extrapolateLeft: \"clamp\", extrapolateRight: \"clamp\" },\n );\n\n const isPhone = device === \"phone\";\n\n // Device dimensions\n const deviceW = isPhone ? 320 : 760;\n const deviceH = isPhone ? 640 : 470;\n const screenInset = isPhone ? 12 : 18;\n const bezelRadius = isPhone ? 36 : 14;\n\n return (\n \n \n {/* Back lid (laptop only — for phone, acts as the back shell) */}\n \n\n {/* Keyboard / chassis base — laptop only */}\n {!isPhone && (\n \n )}\n\n {/* Bezel frame */}\n \n\n {/* UI screen */}\n \n {/* Black panel during flight */}\n \n {/* UI fades in */}\n
\n \n
\n {/* Shimmer sweep */}\n \n \n \n \n );\n}\n", "type": "registry:component", "target": "components/remocn/hero-device-assemble.tsx" } ], "type": "registry:component" }