PurpleWelcome.tsx (6321B)
1 import { MeshGradient5 } from "@/components/effects/MeshGradient.5"; 2 import { MotionValue, circOut, easeInOut, easeOut, motion, useMotionValue, useTime, useTransform } from "framer-motion"; 3 import Image from "next/image"; 4 import { PurpleIcon } from "../icons/PurpleIcon"; 5 import { Button } from "../ui/Button"; 6 import { useIntl } from "react-intl"; 7 import { MeshGradient1 } from "../effects/MeshGradient.1"; 8 import Link from "next/link"; 9 10 11 export function PurpleWelcome() { 12 const intl = useIntl() 13 const time = useTime() 14 const headingGradient = useTransform( 15 time, 16 [0, 3000], 17 [ 18 "linear-gradient(to right, #000000 0%, #D34CD9 1000%, #F869B6 3000%)", 19 "linear-gradient(to right, #000000 -10%, #D34CD9 0%, #F869B6 100%)" 20 ], 21 { 22 clamp: true, 23 ease: circOut 24 } 25 ) 26 const headingOpacity = useTransform( 27 time, 28 [0, 3000], 29 [0, 1], 30 { 31 clamp: true, 32 ease: easeInOut 33 } 34 ) 35 const secondaryContentOpacity = useTransform( 36 time, 37 [3000, 5000], 38 [0, 1], 39 { 40 clamp: true, 41 ease: easeInOut 42 } 43 ) 44 const starsBgScale = useTransform( 45 time, 46 [0, 3000], 47 [1.2, 1.0], 48 { 49 clamp: true, 50 ease: circOut 51 } 52 ) 53 54 return ( 55 <motion.div 56 className="bg-black overflow-hidden relative" 57 > 58 <motion.div 59 className="absolute z-0 w-full h-full pointer-events-none" 60 style={{ scale: starsBgScale }} 61 > 62 <Image src="/stars-bg.webp" fill className="absolute top-0 left-0 object-cover lg:object-contain object-center w-full h-full" alt="" aria-hidden="true" /> 63 <MeshGradient1 className="translate-y-1/4 translate-x-32 z-0" /> 64 </motion.div> 65 <div className="container z-30 mx-auto px-6 pt-12 h-full min-h-screen flex flex-col gap-y-4 justify-center items-center"> 66 <motion.div 67 style={{ opacity: secondaryContentOpacity }} 68 > 69 <PurpleIcon className="w-16 h-16" /> 70 </motion.div> 71 <motion.h1 72 className="text-4xl md:text-6xl text-center text-transparent bg-clip-text font-semibold break-keep tracking-tight z-30" 73 style={{ 74 backgroundImage: headingGradient, 75 opacity: headingOpacity, 76 }} 77 > 78 Welcome to Purple 79 </motion.h1> 80 <PurpleStarIcon className="w-32 h-32 z-40" time={time} /> 81 <motion.div 82 className="text-center text-purple-200/80 text-lg max-w-lg p-6 space-y-4 z-30" 83 style={{ opacity: secondaryContentOpacity }} 84 > 85 <p> 86 Thank you very much for signing up for Damus Purple. Your contribution helps us continue our fight for a more Open and Free internet. 87 </p> 88 <p> 89 You will also get access to premium features, and a star badge on your profile. 90 </p> 91 <p> 92 Enjoy! 93 </p> 94 <div className="pt-8"> 95 <Link href="/purple/account" className="w-full justify-center"> 96 <Button variant="accent" className="w-48"> 97 { intl.formatMessage({ id: "purple.welcome.continue", defaultMessage: "Continue" }) } 98 </Button> 99 </Link> 100 </div> 101 </motion.div> 102 </div> 103 </motion.div> 104 ) 105 } 106 107 interface StarIconProps { 108 className?: string; 109 time: MotionValue<number>; 110 } 111 112 function PurpleStarIcon(props: StarIconProps) { 113 const { className, time } = props; 114 115 const purple1Color = "#D34CD9"; 116 const purple2Color = "#F869B6"; 117 118 const starScale = useTransform( 119 time, 120 [0, 3000], // For the first 3 seconds... 121 [3, 1.0], // ...scale from 3x to 1x 122 { 123 clamp: true, 124 ease: circOut 125 } 126 ) 127 128 const starOpacity = useTransform( 129 time, 130 [0, 3000], 131 [0, 1], 132 { 133 clamp: true, 134 ease: circOut 135 } 136 ) 137 138 const starShadowColor = useTransform( 139 time, 140 [0, 4000], 141 [ 142 "#FFFFFF00", 143 "#FFFFFFFF", 144 ], 145 { 146 clamp: true, 147 ease: circOut 148 } 149 ) 150 151 const gradientOffsetKeyframes = [0, 1000, 5000] 152 153 const whiteGradientStopOffset = useTransform( 154 time, 155 gradientOffsetKeyframes, 156 ["0%", "0%", "70%"], 157 { 158 clamp: true, 159 ease: circOut 160 } 161 ); 162 163 const purple2GradientStopOffset = useTransform( 164 time, 165 gradientOffsetKeyframes, 166 ["1%", "1%", "100%"], 167 { 168 clamp: true, 169 ease: circOut 170 } 171 ); 172 173 const purple1GradientStopOffset = useTransform( 174 time, 175 gradientOffsetKeyframes, 176 ["2%", "2%", "125%"], 177 { 178 clamp: true, 179 ease: circOut 180 } 181 ); 182 183 const blackGradientStopOffset = useTransform( 184 time, 185 gradientOffsetKeyframes, 186 ["3%", "3%", "250%"], 187 { 188 clamp: true, 189 ease: circOut 190 } 191 ); 192 193 return ( 194 // Generated by Pixelmator Pro 3.6.8 195 <motion.svg 196 className={className} 197 width="4267" height="4267" viewBox="0 0 4267 4267" xmlns="http://www.w3.org/2000/svg" 198 style={{ 199 scale: starScale, 200 opacity: starOpacity 201 }} 202 > 203 <defs> 204 <radialGradient id="purpleGradient" cx="150%" cy="-50%" r="250%"> 205 <motion.stop offset={whiteGradientStopOffset} style={{ stopColor: "#ffffff", stopOpacity: 1 }} /> 206 <motion.stop offset={purple2GradientStopOffset} style={{ stopColor: purple2Color, stopOpacity: 1 }} /> 207 <motion.stop offset={purple1GradientStopOffset} style={{ stopColor: purple1Color, stopOpacity: 1 }} /> 208 <motion.stop offset={blackGradientStopOffset} style={{ stopColor: "#000000", stopOpacity: 1 }} /> 209 </radialGradient> 210 <filter id="whiteShadow" x="-50%" y="-50%" width="200%" height="200%"> 211 <motion.feDropShadow dx="0" dy="0" stdDeviation="500" floodColor={starShadowColor} /> 212 </filter> 213 </defs> 214 <path 215 id="Star" 216 fill="url(#purpleGradient)" 217 stroke="url(#purpleGradient)" 218 fill-rule="evenodd" 219 stroke-width="400" 220 stroke-linejoin="round" 221 filter="url(#whiteShadow)" 222 d="M 2133.5 750 L 1812.484985 1691.660645 L 817.713318 1705.975098 L 1614.086914 2302.267578 L 1320.299072 3252.774902 L 2133.5 2679.643311 L 2946.700928 3252.774902 L 2652.913086 2302.267578 L 3449.286621 1705.975098 L 2454.515137 1691.660645 Z" 223 /> 224 </motion.svg> 225 ) 226 }