import React from "react"; import { AbsoluteFill, interpolate, spring, useCurrentFrame, useVideoConfig, Easing, } from "remotion"; import { zColor } from "@remotion/zod-types"; import { z } from "zod"; import { hexToRgba, mixHex, rand } from "../lib/anim"; export const verticalStorySchema = z.object({ kicker: z.string(), line1: z.string(), line2: z.string(), line3: z.string(), ctaText: z.string(), accentColor: zColor(), secondaryColor: zColor(), backgroundColor: zColor(), }); type Props = z.infer; // ── Diagonal animated gradient + floating dust ─────────────────────────────── const StoryBackground: React.FC<{ bg: string; accent: string; secondary: string; }> = ({ bg, accent, secondary }) => { const frame = useCurrentFrame(); const { width, height } = useVideoConfig(); const shift = interpolate(frame, [0, 180], [0, 60]); return ( {Array.from({ length: 22 }).map((_, i) => { const x = rand(i) * width; const baseY = rand(i + 9) * height; const y = (baseY - frame * (0.6 + rand(i) * 1.2)) % height; const size = 2 + rand(i + 3) * 5; const tw = 0.2 + 0.6 * Math.abs(Math.sin((frame + i * 20) / 16)); return (
); })} ); }; const StoryLine: React.FC<{ text: string; delay: number; highlight?: string; }> = ({ text, delay, highlight }) => { const frame = useCurrentFrame(); const { fps } = useVideoConfig(); const s = spring({ frame: frame - delay, fps, config: { damping: 16, mass: 0.8, stiffness: 100 }, }); const y = interpolate(s, [0, 1], [70, 0]); const op = interpolate(s, [0, 1], [0, 1]); return (
{text}
); }; export const VerticalStory: React.FC = ({ kicker, line1, line2, line3, ctaText, accentColor, secondaryColor, backgroundColor, }) => { const frame = useCurrentFrame(); const { fps } = useVideoConfig(); const kickerOp = interpolate(frame, [4, 20], [0, 1], { extrapolateRight: "clamp", }); const ctaSpring = spring({ frame: frame - 64, fps, config: { damping: 12, stiffness: 120 }, }); const ctaScale = interpolate(ctaSpring, [0, 1], [0.6, 1]); const ctaOp = interpolate(ctaSpring, [0, 1], [0, 1]); const arrowBounce = Math.sin(frame / 8) * 8; return (
{kicker}
{/* Swipe-up CTA pinned near the bottom */}
{ctaText}
); };