117 lines
2.6 KiB
TypeScript
117 lines
2.6 KiB
TypeScript
import { type ReactNode, type HTMLAttributes } from 'react'
|
|
import { clsx } from 'clsx'
|
|
|
|
interface GlitchTextProps extends HTMLAttributes<HTMLSpanElement> {
|
|
children: ReactNode
|
|
as?: 'span' | 'h1' | 'h2' | 'h3' | 'h4' | 'p'
|
|
intensity?: 'low' | 'medium' | 'high'
|
|
color?: 'neon' | 'purple' | 'pink' | 'white'
|
|
hover?: boolean
|
|
className?: string
|
|
}
|
|
|
|
export function GlitchText({
|
|
children,
|
|
as: Component = 'span',
|
|
intensity = 'medium',
|
|
color = 'neon',
|
|
hover = false,
|
|
className,
|
|
...props
|
|
}: GlitchTextProps) {
|
|
const text = typeof children === 'string' ? children : ''
|
|
|
|
const colorClasses = {
|
|
neon: 'text-neon-500',
|
|
purple: 'text-accent-500',
|
|
pink: 'text-pink-500',
|
|
white: 'text-white',
|
|
}
|
|
|
|
const glowClasses = {
|
|
neon: 'neon-text',
|
|
purple: 'neon-text-purple',
|
|
pink: '[text-shadow:0_0_8px_rgba(244,114,182,0.5),0_0_16px_rgba(244,114,182,0.25)]',
|
|
white: '[text-shadow:0_0_8px_rgba(255,255,255,0.4),0_0_16px_rgba(255,255,255,0.2)]',
|
|
}
|
|
|
|
const intensityClasses = {
|
|
low: 'animate-[glitch-skew_2s_infinite_linear_alternate-reverse]',
|
|
medium: '',
|
|
high: 'animate-glitch',
|
|
}
|
|
|
|
if (hover) {
|
|
return (
|
|
<Component
|
|
className={clsx(
|
|
colorClasses[color],
|
|
'relative inline-block cursor-pointer transition-all duration-300',
|
|
'hover:' + glowClasses[color],
|
|
'glitch-hover',
|
|
className
|
|
)}
|
|
{...props}
|
|
>
|
|
{children}
|
|
</Component>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<Component
|
|
className={clsx(
|
|
'glitch relative inline-block',
|
|
colorClasses[color],
|
|
glowClasses[color],
|
|
intensityClasses[intensity],
|
|
className
|
|
)}
|
|
data-text={text}
|
|
{...props}
|
|
>
|
|
{children}
|
|
</Component>
|
|
)
|
|
}
|
|
|
|
// Simpler glitch effect for headings
|
|
interface GlitchHeadingProps {
|
|
children: ReactNode
|
|
level?: 1 | 2 | 3 | 4
|
|
className?: string
|
|
gradient?: boolean
|
|
}
|
|
|
|
export function GlitchHeading({
|
|
children,
|
|
level = 1,
|
|
className,
|
|
gradient = false,
|
|
}: GlitchHeadingProps) {
|
|
const text = typeof children === 'string' ? children : ''
|
|
|
|
const sizeClasses = {
|
|
1: 'text-4xl md:text-5xl lg:text-6xl font-bold',
|
|
2: 'text-3xl md:text-4xl font-bold',
|
|
3: 'text-2xl md:text-3xl font-semibold',
|
|
4: 'text-xl md:text-2xl font-semibold',
|
|
}
|
|
|
|
const Component = `h${level}` as keyof JSX.IntrinsicElements
|
|
|
|
return (
|
|
<Component
|
|
className={clsx(
|
|
'glitch relative inline-block',
|
|
sizeClasses[level],
|
|
gradient ? 'gradient-neon-text' : 'text-white neon-text',
|
|
className
|
|
)}
|
|
data-text={text}
|
|
>
|
|
{children}
|
|
</Component>
|
|
)
|
|
}
|