feat: integrate Tailwind CSS with custom theme and animations
Added Tailwind CSS and tw-animate-css imports to globals.css. Introduced a custom dark variant and an extensive @theme inline block with CSS variables for colors, radii, and animations. Included keyframes for shimmer-slide, spin-around, gradient, shine, and background-position-spin to enable consistent theming and dynamic UI effects across the application.
This commit is contained in:
1 parent
55c169bd6e
commit
5c1ccbc69a
67 files changed
+8984
-160
No files matched your search
@@ -0,0 +1,103 @@
|
||||
"use client"
|
||||
|
||||
import React, { useCallback, useEffect } from "react"
|
||||
import { motion, useMotionTemplate, useMotionValue } from "motion/react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
interface MagicCardProps {
|
||||
children?: React.ReactNode
|
||||
className?: string
|
||||
gradientSize?: number
|
||||
gradientColor?: string
|
||||
gradientOpacity?: number
|
||||
gradientFrom?: string
|
||||
gradientTo?: string
|
||||
}
|
||||
|
||||
export function MagicCard({
|
||||
children,
|
||||
className,
|
||||
gradientSize = 200,
|
||||
gradientColor = "#262626",
|
||||
gradientOpacity = 0.8,
|
||||
gradientFrom = "#9E7AFF",
|
||||
gradientTo = "#FE8BBB",
|
||||
}: MagicCardProps) {
|
||||
const mouseX = useMotionValue(-gradientSize)
|
||||
const mouseY = useMotionValue(-gradientSize)
|
||||
const reset = useCallback(() => {
|
||||
mouseX.set(-gradientSize)
|
||||
mouseY.set(-gradientSize)
|
||||
}, [gradientSize, mouseX, mouseY])
|
||||
|
||||
const handlePointerMove = useCallback(
|
||||
(e: React.PointerEvent<HTMLDivElement>) => {
|
||||
const rect = e.currentTarget.getBoundingClientRect()
|
||||
mouseX.set(e.clientX - rect.left)
|
||||
mouseY.set(e.clientY - rect.top)
|
||||
},
|
||||
[mouseX, mouseY]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
reset()
|
||||
}, [reset])
|
||||
|
||||
useEffect(() => {
|
||||
const handleGlobalPointerOut = (e: PointerEvent) => {
|
||||
if (!e.relatedTarget) {
|
||||
reset()
|
||||
}
|
||||
}
|
||||
|
||||
const handleVisibility = () => {
|
||||
if (document.visibilityState !== "visible") {
|
||||
reset()
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("pointerout", handleGlobalPointerOut)
|
||||
window.addEventListener("blur", reset)
|
||||
document.addEventListener("visibilitychange", handleVisibility)
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("pointerout", handleGlobalPointerOut)
|
||||
window.removeEventListener("blur", reset)
|
||||
document.removeEventListener("visibilitychange", handleVisibility)
|
||||
}
|
||||
}, [reset])
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn("group relative rounded-[inherit]", className)}
|
||||
onPointerMove={handlePointerMove}
|
||||
onPointerLeave={reset}
|
||||
onPointerEnter={reset}
|
||||
>
|
||||
<motion.div
|
||||
className="bg-border pointer-events-none absolute inset-0 rounded-[inherit] duration-300 group-hover:opacity-100"
|
||||
style={{
|
||||
background: useMotionTemplate`
|
||||
radial-gradient(${gradientSize}px circle at ${mouseX}px ${mouseY}px,
|
||||
${gradientFrom},
|
||||
${gradientTo},
|
||||
var(--border) 100%
|
||||
)
|
||||
`,
|
||||
}}
|
||||
/>
|
||||
<div className="bg-background absolute inset-px rounded-[inherit]" />
|
||||
<motion.div
|
||||
className="pointer-events-none absolute inset-px rounded-[inherit] opacity-0 transition-opacity duration-300 group-hover:opacity-100"
|
||||
style={{
|
||||
background: useMotionTemplate`
|
||||
radial-gradient(${gradientSize}px circle at ${mouseX}px ${mouseY}px, ${gradientColor}, transparent 100%)
|
||||
`,
|
||||
opacity: gradientOpacity,
|
||||
}}
|
||||
/>
|
||||
<div className="relative">{children}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user