mirror of
https://github.com/supabase/supabase.git
synced 2026-10-10 03:45:06 +03:00
This PR migrates the JS config for Tailwind into a CSS config. As such, all variables have been defined as CSS variables and they're using the specialized Tailwind syntax for generating utility classes. Beside the migration, these changes were also added: - Added `tailwind.config.css` to few packages to make the Tailwind Intellisense work. - Migrated away from Radix style color classes to our defined classes, the values will remain the same. - Most of the CSS is generated by scripts, they'll be removed in next PRs. * Removed redundant `border-light` classes from several components since it was undefined. * Removed redundant `text-strong` classes from several components since it was undefined. How to test: - Open all apps, compare the UI (mainly colors) to builds from #45417 and try to find a difference. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Style** * Harmonized color variable usages and updated UI color references (affects palettes, charts, gradients, hero illustrations, and scrollbars). * Tweaked border, tab, and selection visuals across components. * **New Features** * Added a suite of theme animations and refined typography presets used by site prose and docs. * **Refactor** * Overhauled Tailwind/theme configuration and color token generation for more consistent theming. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
114 lines
3.5 KiB
TypeScript
114 lines
3.5 KiB
TypeScript
'use client'
|
|
|
|
import { detectBrowser, isBrowser } from 'common'
|
|
import { motion } from 'framer-motion'
|
|
import React, { PropsWithChildren, useEffect, useRef } from 'react'
|
|
import { cn } from 'ui'
|
|
|
|
interface Props {
|
|
outerClassName?: string
|
|
innerClassName?: string
|
|
hasActiveOnHover?: boolean
|
|
activeColor?: 'default' | 'brand'
|
|
hasShimmer?: boolean
|
|
hasInnerShimmer?: boolean
|
|
shimmerFromColor?: string
|
|
shimmerToColor?: string
|
|
style?: React.CSSProperties
|
|
innerStyle?: React.CSSProperties
|
|
hasMotion?: boolean
|
|
}
|
|
|
|
const Panel = ({
|
|
outerClassName,
|
|
innerClassName,
|
|
hasActiveOnHover = false,
|
|
activeColor = 'default',
|
|
hasShimmer = false,
|
|
hasInnerShimmer = false,
|
|
shimmerFromColor,
|
|
shimmerToColor,
|
|
hasMotion = false,
|
|
children,
|
|
style,
|
|
innerStyle,
|
|
}: PropsWithChildren<Props>) => {
|
|
const outerRef = useRef(null)
|
|
const innerRef = useRef(null)
|
|
const Component = hasMotion ? motion.div : 'div'
|
|
const isSafari = isBrowser && detectBrowser() === 'Safari'
|
|
const trackCursor = hasShimmer || hasInnerShimmer
|
|
|
|
const handleGlow = (event: any) => {
|
|
if (!outerRef.current || !innerRef.current) return
|
|
|
|
const outerElement = outerRef.current as HTMLDivElement
|
|
const innerElement = innerRef.current as HTMLDivElement
|
|
const { x: elX, y: elY, width, height } = outerElement.getBoundingClientRect()
|
|
const x = event.clientX - elX
|
|
const y = event.clientY - elY
|
|
const isActive = x > -0 && x < width + 0 && y > -0 && y < height + 0
|
|
|
|
if (hasShimmer) {
|
|
const activeGlow =
|
|
hasActiveOnHover && isActive
|
|
? `radial-gradient(65rem circle at ${x}px ${y}px, ${
|
|
activeColor === 'brand' ? 'var(--color-brand-900)' : 'hsl(var(--border-stronger))'
|
|
}, transparent), `
|
|
: ''
|
|
outerElement.style.backgroundImage = `
|
|
${activeGlow}radial-gradient(30rem circle at ${x}px ${y}px, ${
|
|
shimmerFromColor ?? 'hsl(var(--border-strong))'
|
|
}, ${shimmerToColor ?? 'hsl(var(--background-surface-300))'})`
|
|
}
|
|
|
|
if (hasInnerShimmer) {
|
|
innerElement.style.backgroundImage = isActive
|
|
? `radial-gradient(7rem circle at ${x}px ${y}px, hsl(var(--background-surface-300)), transparent), radial-gradient(20rem circle at ${x}px ${y}px, hsl(var(--background-surface-200)), transparent)`
|
|
: ''
|
|
}
|
|
}
|
|
|
|
useEffect(() => {
|
|
if (!isBrowser || trackCursor || isSafari) return
|
|
|
|
window.addEventListener('mousemove', handleGlow)
|
|
return () => {
|
|
window.removeEventListener('mousemove', handleGlow)
|
|
}
|
|
}, [])
|
|
|
|
return (
|
|
<Component
|
|
ref={outerRef}
|
|
className={cn(
|
|
'group/panel relative rounded-lg md:rounded-xl p-px bg-surface-75 bg-linear-to-b from-border to-border/50 dark:to-surface-100 transition-all hover:shadow-md flex items-center justify-center',
|
|
!trackCursor && hasActiveOnHover
|
|
? activeColor === 'brand'
|
|
? 'hover:bg-none hover:bg-brand!'
|
|
: 'hover:bg-none hover:bg-border-stronger!'
|
|
: '',
|
|
outerClassName
|
|
)}
|
|
{...(hasMotion ? { whileHover: 'hover', animate: 'initial' } : undefined)}
|
|
style={style}
|
|
>
|
|
<div
|
|
className={cn(
|
|
'relative z-10 w-full h-full rounded-[7px] md:rounded-[11px] bg-surface-75 overflow-hidden text-foreground-light',
|
|
innerClassName
|
|
)}
|
|
style={innerStyle}
|
|
>
|
|
{children}
|
|
<div
|
|
ref={innerRef}
|
|
className="absolute z-10 inset-0 w-full h-full pointer-events-none opacity-20"
|
|
/>
|
|
</div>
|
|
</Component>
|
|
)
|
|
}
|
|
|
|
export default Panel
|