110 lines
4.2 KiB
TypeScript
110 lines
4.2 KiB
TypeScript
import React from 'react'
|
|
import { Link } from 'react-router-dom'
|
|
|
|
type Variant = 'copper' | 'outline' | 'dark' | 'dark-ivory'
|
|
|
|
type BaseProps = {
|
|
children: React.ReactNode
|
|
variant?: Variant
|
|
className?: string
|
|
}
|
|
|
|
// استایلهای فوقلوکس شیشهای (Glassmorphic) با رنگهای اختصاصی پروژه
|
|
const STYLES: Record<Variant, { base: string; fill: string; text: string; glow: string }> = {
|
|
copper: {
|
|
// دکمه اصلی: شیشه دودی تیره با خط نوری مسی، هاله بازتاب و حاشیه کریستالی
|
|
base: 'bg-char/75 backdrop-blur-xl text-ivory border border-copper/50 shadow-[inset_0_1px_1px_rgba(255,255,255,0.25),0_8px_20px_rgba(0,0,0,0.4)]',
|
|
fill: 'bg-gradient-to-r from-copper via-[#d89f6e] to-copper',
|
|
text: 'group-hover:text-char font-semibold',
|
|
glow: 'hover:border-copper hover:shadow-[0_0_30px_rgba(197,143,92,0.5)]',
|
|
},
|
|
outline: {
|
|
// دکمه ثانویه: شیشه دودی کاملاً مات (Frosted Smoked Glass) با بازتاب لبهها
|
|
base: 'bg-white/[0.04] backdrop-blur-xl border border-white/20 text-ivory shadow-[inset_0_1px_1px_rgba(255,255,255,0.15),0_8px_20px_rgba(0,0,0,0.3)]',
|
|
fill: 'bg-white/10',
|
|
text: 'group-hover:text-copper',
|
|
glow: 'hover:border-copper/70 hover:bg-white/[0.08] hover:shadow-[0_0_25px_rgba(197,143,92,0.25)]',
|
|
},
|
|
dark: {
|
|
base: 'bg-ink/85 backdrop-blur-xl text-ivory border border-white/10 shadow-[inset_0_1px_1px_rgba(255,255,255,0.1)]',
|
|
fill: 'bg-copper',
|
|
text: 'group-hover:text-char',
|
|
glow: 'hover:border-copper/50 hover:shadow-[0_0_20px_rgba(197,143,92,0.3)]',
|
|
},
|
|
'dark-ivory': {
|
|
base: 'bg-ink/85 backdrop-blur-xl text-ivory border border-white/10 shadow-[inset_0_1px_1px_rgba(255,255,255,0.1)]',
|
|
fill: 'bg-ivory',
|
|
text: 'group-hover:text-char',
|
|
glow: 'hover:shadow-[0_0_20px_rgba(255,255,255,0.2)]',
|
|
},
|
|
}
|
|
|
|
function Inner({ children, variant = 'copper' }: { children: React.ReactNode; variant?: Variant }) {
|
|
const style = STYLES[variant]
|
|
return (
|
|
<>
|
|
{/* خط انعکاس نوری شیشه در بالای دکمه */}
|
|
<span className="pointer-events-none absolute -top-1/2 left-0 right-0 h-full rounded-full bg-gradient-to-b from-white/20 to-transparent" />
|
|
|
|
{/* انیمیشن پر شدن موجی و نرم */}
|
|
<span
|
|
aria-hidden="true"
|
|
className={`absolute inset-0 translate-y-full rounded-full transition-transform duration-500 ease-out group-hover:translate-y-0 ${style.fill}`}
|
|
/>
|
|
|
|
{/* متن و آیکون دکمه */}
|
|
<span
|
|
className={`relative z-10 flex items-center justify-center gap-3 transition-colors duration-400 ease-out ${style.text}`}
|
|
>
|
|
{children}
|
|
</span>
|
|
</>
|
|
)
|
|
}
|
|
|
|
// بدنه اصلی دکمه: کپسول کامل (rounded-full)، کلیک نرم (active:scale-95) و انتقال شیشهای
|
|
const SHELL =
|
|
'group relative inline-flex items-center justify-center overflow-hidden rounded-full px-8 py-3.5 text-sm font-medium tracking-wide focus:outline-none focus-visible:ring-2 focus-visible:ring-copper focus-visible:ring-offset-2 focus-visible:ring-offset-ink active:scale-[0.98] transition-all duration-400 ease-out cursor-pointer select-none'
|
|
|
|
export function ButtonLink({
|
|
to,
|
|
children,
|
|
variant = 'copper',
|
|
className = '',
|
|
}: BaseProps & { to: string }) {
|
|
const style = STYLES[variant]
|
|
return (
|
|
<Link to={to} className={`${SHELL} ${style.base} ${style.glow} ${className}`}>
|
|
<Inner variant={variant}>{children}</Inner>
|
|
</Link>
|
|
)
|
|
}
|
|
|
|
export function ButtonAnchor({
|
|
href,
|
|
children,
|
|
variant = 'copper',
|
|
className = '',
|
|
...rest
|
|
}: BaseProps & { href: string } & React.AnchorHTMLAttributes<HTMLAnchorElement>) {
|
|
const style = STYLES[variant]
|
|
return (
|
|
<a href={href} className={`${SHELL} ${style.base} ${style.glow} ${className}`} {...rest}>
|
|
<Inner variant={variant}>{children}</Inner>
|
|
</a>
|
|
)
|
|
}
|
|
|
|
export function Button({
|
|
children,
|
|
variant = 'copper',
|
|
className = '',
|
|
...rest
|
|
}: BaseProps & React.ButtonHTMLAttributes<HTMLButtonElement>) {
|
|
const style = STYLES[variant]
|
|
return (
|
|
<button className={`${SHELL} ${style.base} ${style.glow} ${className}`} {...rest}>
|
|
<Inner variant={variant}>{children}</Inner>
|
|
</button>
|
|
)
|
|
} |