Hey is a decentralized and permissionless social media app built with Lens Protocol 馃尶
at main 112 lines 3.2 kB view raw
1import { cva, type VariantProps } from "class-variance-authority"; 2import { AnimatePresence, motion } from "motion/react"; 3import type { ButtonHTMLAttributes, ReactNode } from "react"; 4import { forwardRef, memo } from "react"; 5import { Spinner } from "@/components/Shared/UI"; 6import cn from "@/helpers/cn"; 7 8const buttonVariants = cva( 9 "rounded-full font-bold inline-flex items-center justify-center relative overflow-hidden", 10 { 11 compoundVariants: [ 12 // Non-outline Primary 13 { 14 class: cn( 15 "text-white hover:text-white active:text-gray-100", 16 "bg-gray-950 hover:bg-gray-800 active:bg-gray-700", 17 "border border-gray-950 hover:border-gray-800 active:border-gray-700", 18 "dark:text-gray-950 dark:hover:text-gray-900 dark:active:text-gray-600", 19 "dark:bg-white dark:hover:bg-gray-200 dark:active:bg-gray-200", 20 "dark:border-white dark:hover:border-gray-100 dark:active:border-gray-200" 21 ), 22 outline: false, 23 variant: "primary" 24 }, 25 // Outline Primary 26 { 27 class: cn( 28 "text-gray-950 active:text-gray-500", 29 "border border-gray-300 hover:border-gray-400", 30 "dark:text-white dark:active:text-gray-700", 31 "dark:border-gray-700 dark:hover:border-gray-600" 32 ), 33 outline: true, 34 variant: "primary" 35 } 36 ], 37 defaultVariants: { 38 outline: false, 39 size: "md", 40 variant: "primary" 41 }, 42 variants: { 43 outline: { false: "", true: "" }, 44 size: { lg: "px-5 py-1.5", md: "px-4 py-1", sm: "px-3 py-0.5 text-sm" }, 45 variant: { primary: "" } 46 } 47 } 48); 49 50interface ButtonProps 51 extends ButtonHTMLAttributes<HTMLButtonElement>, 52 VariantProps<typeof buttonVariants> { 53 children?: ReactNode; 54 icon?: ReactNode; 55 loading?: boolean; 56} 57 58const Button = forwardRef<HTMLButtonElement, ButtonProps>( 59 ( 60 { 61 children, 62 className, 63 disabled, 64 icon, 65 outline, 66 size, 67 variant, 68 loading, 69 ...rest 70 }, 71 ref 72 ) => { 73 return ( 74 <button 75 className={buttonVariants({ className, outline, size, variant })} 76 disabled={disabled} 77 ref={ref} 78 type={rest.type} 79 {...rest} 80 > 81 <AnimatePresence mode="wait"> 82 <motion.div 83 animate={loading ? "loading" : "idle"} 84 className="flex items-center gap-x-1.5" 85 initial="idle" 86 transition={{ bounce: 0, duration: 0.2, type: "spring" }} 87 variants={{ 88 idle: { opacity: 1, y: 0 }, 89 loading: { opacity: 0, y: -20 } 90 }} 91 > 92 {icon} 93 {children} 94 </motion.div> 95 {loading && ( 96 <motion.div 97 animate={{ opacity: 1, y: 0 }} 98 className="absolute flex items-center justify-center" 99 exit={{ opacity: 0, y: 20 }} 100 initial={{ opacity: 0, y: 20 }} 101 transition={{ bounce: 0, duration: 0.2, type: "spring" }} 102 > 103 <Spinner size="xs" /> 104 </motion.div> 105 )} 106 </AnimatePresence> 107 </button> 108 ); 109 } 110); 111 112export default memo(Button);