This repository has been archived on 2026-01-21. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Acad-IA/src/components/planes/GradientMesh.tsx
T
alexrg a487a8c293 feat: add AdjustAIButton, EditPlanButton, and AsignaturaPreviewCard components
- Implemented AdjustAIButton for AI-driven plan adjustments with a confetti effect on success.
- Created EditPlanButton to allow editing of plan details with form validation and optimistic updates.
- Added AsignaturaPreviewCard to display course previews with relevant statistics and details.
- Introduced Field component for consistent form field labeling.
- Developed GradientMesh for dynamic background effects based on color input.
- Added Pulse component for skeleton loading states.
- Created SmallStat and StatCard components for displaying statistical information in a card format.
- Implemented utility functions in planHelpers for color manipulation and formatting.
- Established planQueries for fetching plan and course data from the database.
- Updated the plan detail route to utilize new components and queries for improved user experience.
2025-08-29 11:14:34 -06:00

44 lines
1.8 KiB
TypeScript

import { useEffect, useRef } from "react"
import gsap from "gsap"
import { ScrollTrigger } from "gsap/ScrollTrigger"
gsap.registerPlugin(ScrollTrigger)
import { hexToRgb, lighten, toRGBA } from "./planHelpers"
export function GradientMesh({ color }: { color?: string | null }) {
const meshRef = useRef<HTMLDivElement>(null)
const base = hexToRgb(color)
const soft = lighten(base, 20)
const pop = lighten(base, -20)
useEffect(() => {
if (!meshRef.current) return
const blobs = meshRef.current.querySelectorAll('.blob')
blobs.forEach((el, i) => {
gsap.to(el, {
x: gsap.utils.random(-30, 30),
y: gsap.utils.random(-20, 20),
rotate: gsap.utils.random(-6, 6),
duration: gsap.utils.random(6, 10),
ease: 'sine.inOut',
yoyo: true,
repeat: -1,
delay: i * 0.2,
})
})
return () => gsap.killTweensOf(blobs)
}, [color])
return (
<div ref={meshRef} className="pointer-events-none absolute inset-0 -z-10 overflow-hidden">
<div className="blob absolute -top-24 -left-24 w-[38rem] h-[38rem] rounded-full blur-3xl"
style={{ background: `radial-gradient(circle, ${toRGBA(soft, .35)}, transparent 60%)` }} />
<div className="blob absolute -bottom-28 -right-20 w-[34rem] h-[34rem] rounded-full blur-[60px]"
style={{ background: `radial-gradient(circle, ${toRGBA(base, .28)}, transparent 60%)` }} />
<div className="blob absolute top-1/3 left-1/2 -translate-x-1/2 w-[22rem] h-[22rem] rounded-full blur-[50px]"
style={{ background: `radial-gradient(circle, ${toRGBA(pop, .22)}, transparent 60%)` }} />
<div className="absolute inset-0 opacity-40"
style={{ background: 'radial-gradient(800px 300px at 20% -10%, #fff, transparent 60%)' }} />
</div>
)
}