alternative tangled frontend (extremely wip)

refactor: abstract component

serenity 98dbdf60 a9e25dac

+93 -68
+66
src/components/Animated/UnderlineIconRouterLink.tsx
··· 1 + import { Link } from "@tanstack/react-router"; 2 + import { motion, Transition, Variants } from "motion/react"; 3 + import { ReactNode } from "react"; 4 + 5 + export const UnderlineIconRouterLink = ({ 6 + to, 7 + icon, 8 + label, 9 + className, 10 + iconClassName = "text-[#cba6f7]", 11 + labelClassName = "text-[#cba6f7]", 12 + underlineClassName = "bg-[#cba6f7]", 13 + position = "left", 14 + iconVariants = { 15 + hover: { rotate: [0, -10, 10, -10, 10, 0] }, 16 + }, 17 + iconTransitions = { duration: 0.3, ease: "easeInOut" }, 18 + }: { 19 + to: string; 20 + icon: ReactNode; 21 + label: string; 22 + className?: string; 23 + iconClassName?: string; 24 + labelClassName?: string; 25 + underlineClassName?: string; 26 + position?: "right" | "left"; 27 + iconVariants?: Variants; 28 + iconTransitions?: Transition; 29 + }) => { 30 + const iconElement = ( 31 + <motion.div 32 + variants={iconVariants} 33 + transition={iconTransitions} 34 + className={iconClassName} 35 + > 36 + {icon} 37 + </motion.div> 38 + ); 39 + 40 + return ( 41 + <motion.div initial="initial" whileHover="hover"> 42 + <Link 43 + to={to} 44 + className={`flex cursor-pointer items-center gap-1 pl-2 ${className}`} 45 + > 46 + {position === "left" && iconElement} 47 + <motion.div className="relative inline-block"> 48 + <p className={labelClassName}>{label}</p> 49 + <motion.span 50 + className={`absolute bottom-1 left-0 h-0.25 w-full origin-center ${underlineClassName}`} 51 + variants={{ 52 + initial: { scaleX: 0 }, 53 + hover: { scaleX: 1 }, 54 + }} 55 + transition={{ 56 + type: "spring", 57 + duration: 0.2, 58 + bounce: 0.3, 59 + }} 60 + /> 61 + </motion.div> 62 + {position === "right" && iconElement} 63 + </Link> 64 + </motion.div> 65 + ); 66 + };
+27 -68
src/components/Nav/NavBarUnauthed.tsx
··· 1 - import { UnderlineRouterLink } from "@/components/Animated/UnderlineRouterLink"; 1 + import { UnderlineIconRouterLink } from "@/components/Animated/UnderlineIconRouterLink"; 2 2 import { StrandIcon } from "@/components/Icons/Branding/StrandIcon"; 3 3 import { LucideLogIn } from "@/components/Icons/LucideLogIn"; 4 - import { Link } from "@tanstack/react-router"; 5 - import { motion } from "motion/react"; 6 4 7 5 export const NavBarUnauthed = () => { 8 6 return ( 9 7 <div className="bg-surface0 flex w-full items-center justify-between p-4"> 10 8 <div className="flex items-center gap-1"> 11 - <motion.div initial="initial" whileHover="hover"> 12 - <Link 13 - to="/" 14 - className="flex cursor-pointer items-center gap-1 pl-2 text-lg font-semibold" 15 - > 16 - <motion.div 17 - variants={{ 18 - hover: { rotate: [0, -10, 10, -10, 10, 0] }, 19 - }} 20 - whileTap={{ scale: 0.8 }} 21 - transition={{ duration: 0.3, ease: "easeInOut" }} 22 - > 23 - <StrandIcon /> 24 - </motion.div> 25 - <motion.div className="text-text relative inline-block"> 26 - <h1>Strand</h1> 27 - <motion.span 28 - className="bg-text absolute bottom-1 left-0 h-0.25 w-full origin-center" 29 - variants={{ 30 - initial: { scaleX: 0 }, 31 - hover: { scaleX: 1 }, 32 - }} 33 - transition={{ 34 - type: "spring", 35 - duration: 0.2, 36 - bounce: 0.3, 37 - }} 38 - /> 39 - </motion.div> 40 - </Link> 41 - </motion.div> 9 + <UnderlineIconRouterLink 10 + to="/" 11 + label="Strand" 12 + icon={StrandIcon()} 13 + iconClassName="text-text" 14 + labelClassName="text-text" 15 + underlineClassName="bg-text" 16 + className="text-lg font-semibold" 17 + /> 42 18 </div> 43 19 <div className="flex items-center gap-1"> 44 - <motion.div initial="initial" whileHover="hover"> 45 - <Link 46 - to="/login" 47 - className="flex cursor-pointer items-center gap-1 pl-2" 48 - > 49 - <motion.div className="text-text relative inline-block"> 50 - <p>Sign In</p> 51 - <motion.span 52 - className="bg-text absolute bottom-1 left-0 h-0.25 w-full origin-center" 53 - variants={{ 54 - initial: { scaleX: 0 }, 55 - hover: { scaleX: 1 }, 56 - }} 57 - transition={{ 58 - type: "spring", 59 - duration: 0.2, 60 - bounce: 0.3, 61 - }} 62 - /> 63 - </motion.div> 64 - <motion.div 65 - variants={{ 66 - hover: { 67 - x: [0, 10, -10, 0], 68 - opacity: [1, 0, 0, 1], 69 - }, 70 - }} 71 - whileTap={{ scale: 0.8 }} 72 - transition={{ duration: 0.2, ease: "easeInOut" }} 73 - > 74 - <LucideLogIn /> 75 - </motion.div> 76 - </Link> 77 - </motion.div> 20 + <UnderlineIconRouterLink 21 + to="/login" 22 + label="Sign In" 23 + icon={LucideLogIn({})} 24 + iconClassName="text-crust" 25 + labelClassName="text-crust" 26 + underlineClassName="bg-crust" 27 + className="bg-accent rounded-sm p-1.5 pl-3 pr-3" 28 + position="right" 29 + iconTransitions={{ duration: 0.2, ease: "easeInOut" }} 30 + iconVariants={{ 31 + hover: { 32 + x: [0, 10, -10, 0], 33 + opacity: [1, 0, 0, 1], 34 + }, 35 + }} 36 + /> 78 37 </div> 79 38 </div> 80 39 );