UI v1 این کامپوننت را حذف کرده بود؛ ساختار قدیمی صفحهٔ جزئیات پروژه به آن وابسته است (دکمهٔ بازگشت به فهرست پروژهها).
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>
|
|
)
|
|
} |