mirror of
https://github.com/supabase/supabase.git
synced 2026-05-06 22:18:00 +08:00
This PR migrates the whole monorepo to use Tailwind v4: - Removed `@tailwindcss/container-queries` plugin since it's included by default in v4, - Bump all instances of Tailwind to v4. Made minimal changes to the shared config to remove non-supported features (`alpha` mentions), - Migrate all apps to be compatible with v4 configs, - Fix the `typography.css` import in 3 apps, - Add missing rules which were included by default in v3, - Run `pnpm dlx @tailwindcss/upgrade` on all apps, which renames a lot of classes - Rename all misnamed classes according to https://tailwindcss.com/docs/upgrade-guide#renamed-utilities in all apps. --------- Co-authored-by: Jordi Enric <jordi.err@gmail.com>
122 lines
3.1 KiB
TypeScript
122 lines
3.1 KiB
TypeScript
import { AnimatePresence, motion } from 'framer-motion'
|
|
import { Datadog, Grafana, Sentry } from 'icons'
|
|
import { BracesIcon } from 'lucide-react'
|
|
import { useEffect, useState } from 'react'
|
|
import { cn } from 'ui'
|
|
|
|
export const AnimatedLogos = () => {
|
|
const [currIndex, setCurrIndex] = useState(0)
|
|
const timer = 2500
|
|
const iconSize = 36
|
|
|
|
const logos = [
|
|
{
|
|
id: 'datadog',
|
|
name: 'Datadog',
|
|
icon: <Datadog fill="currentColor" size={iconSize} />,
|
|
},
|
|
{
|
|
id: 'loki',
|
|
name: 'Loki',
|
|
icon: <Grafana fill="currentColor" size={iconSize} />,
|
|
},
|
|
{ id: 'https', name: 'HTTPS', icon: <BracesIcon size={iconSize} /> },
|
|
{
|
|
id: 'sentry',
|
|
name: 'Sentry',
|
|
icon: <Sentry fill="currentColor" size={iconSize} />,
|
|
},
|
|
]
|
|
|
|
useEffect(() => {
|
|
const interval = setInterval(() => {
|
|
setCurrIndex((prev) => (prev + 1) % logos.length)
|
|
}, timer)
|
|
return () => clearInterval(interval)
|
|
}, [logos.length])
|
|
|
|
const getPreviousIndex = () => (currIndex - 1 + logos.length) % logos.length
|
|
const getNextIndex = () => (currIndex + 1) % logos.length
|
|
|
|
const getPosition = (index: number) => {
|
|
if (index === currIndex) return 'center'
|
|
if (index === getPreviousIndex()) return 'left'
|
|
if (index === getNextIndex()) return 'right'
|
|
return 'hidden'
|
|
}
|
|
|
|
const logoVariants = {
|
|
hidden: {
|
|
x: 'calc(-50% + 120px)',
|
|
y: '-50%',
|
|
scale: 0.6,
|
|
opacity: 0,
|
|
filter: 'blur(1px)',
|
|
},
|
|
right: {
|
|
x: 'calc(-50% + 80px)',
|
|
y: '-50%',
|
|
scale: 0.8,
|
|
opacity: 0.5,
|
|
zIndex: 2,
|
|
filter: 'blur(1px)',
|
|
},
|
|
center: {
|
|
x: '-50%',
|
|
y: '-50%',
|
|
scale: 1,
|
|
opacity: 1,
|
|
zIndex: 3,
|
|
filter: 'blur(0px)',
|
|
},
|
|
left: {
|
|
x: 'calc(-50% - 80px)',
|
|
y: '-50%',
|
|
scale: 0.8,
|
|
opacity: 0.5,
|
|
zIndex: 2,
|
|
filter: 'blur(1px)',
|
|
},
|
|
exit: {
|
|
x: 'calc(-50% - 120px)',
|
|
y: '-50%',
|
|
scale: 0.6,
|
|
opacity: 0,
|
|
filter: 'blur(1px)',
|
|
},
|
|
}
|
|
|
|
const visibleIndices = [getPreviousIndex(), currIndex, getNextIndex()]
|
|
|
|
return (
|
|
<div className="relative w-48 h-32 mx-auto mb-8 overflow-hidden">
|
|
<AnimatePresence initial={false}>
|
|
{logos.map((logo, index) => {
|
|
if (!visibleIndices.includes(index)) return null
|
|
|
|
const position = getPosition(index)
|
|
const isCenter = index === currIndex
|
|
|
|
return (
|
|
<motion.div
|
|
key={logo.id}
|
|
className={cn(
|
|
'absolute top-1/2 left-1/2 flex items-center justify-center rounded-lg',
|
|
isCenter ? 'w-24 h-24' : 'w-20 h-20'
|
|
)}
|
|
variants={logoVariants}
|
|
initial="hidden"
|
|
animate={position}
|
|
exit="exit"
|
|
transition={{ duration: 0.5, ease: 'easeInOut' }}
|
|
>
|
|
<span>{logo.icon}</span>
|
|
</motion.div>
|
|
)
|
|
})}
|
|
</AnimatePresence>
|
|
<div className="absolute -inset-4 bg-linear-to-r from-background-surface-75 via-transparent to-background-surface-75 z-40" />
|
|
</div>
|
|
)
|
|
}
|