index.tsx126 lines · main
1'use client'
2
3import { useTheme } from 'next-themes'
4import Image from 'next/image'
5import * as React from 'react'
6import { cn } from 'ui'
7
8interface Props {
9 title: string
10 icon?: string | React.ReactNode
11 children?: React.ReactNode
12 header?: string
13 background?: boolean
14 className?: string
15 logo?: string
16 logoInverse?: string
17 hasLightIcon?: boolean
18 showLink?: boolean
19 showIconBg?: boolean
20}
21
22export const GlassPanel = ({
23 title,
24 icon,
25 children,
26 header,
27 background = true,
28 logo,
29 logoInverse,
30 hasLightIcon,
31 showLink = false,
32 showIconBg = false,
33 className,
34}: Props) => {
35 const { resolvedTheme } = useTheme()
36 const showLogoInverse = logoInverse && resolvedTheme?.includes('dark')
37 const showLogo = !showLogoInverse && logo
38
39 const IconBackground: React.FC<React.PropsWithChildren> = (props) => (
40 <div
41 className={cn(
42 'shrink-0',
43 showIconBg ? 'bg-surface-75 border w-8 h-8 flex items-center justify-center rounded-sm' : ''
44 )}
45 >
46 {props.children}
47 </div>
48 )
49
50 const LogoComponent = ({ logoImage, className }: { logoImage: string; className?: string }) => (
51 <div className="relative box-content p-8 pb-0">
52 <div className="relative h-[33px] w-auto max-w-[145px]">
53 <Image
54 src={logoImage}
55 alt={title}
56 fill
57 sizes="100%"
58 className={cn('object-contain object-left', className)}
59 />
60 </div>
61 </div>
62 )
63
64 return (
65 <div
66 className={cn(
67 'relative',
68 'h-full',
69 'group',
70 'cursor-pointer',
71 'overflow-hidden',
72 'border rounded-lg',
73 'text-left',
74 background
75 ? 'hover:border-strong bg-surface-75'
76 : 'border-muted hover:border-default bg-transparent',
77 'transition',
78 className
79 )}
80 >
81 {showLogoInverse && <LogoComponent logoImage={logoInverse} className="opacity-50" />}
82 {showLogo && <LogoComponent logoImage={logo} className="opacity-75" />}
83
84 {header && (
85 <img
86 src={`${header}`}
87 className="transition-all left-0 -top-64 w-full
88 duration-700 ease-out
89 "
90 />
91 )}
92 {/* <div
93 className="absolute left-0 top-0 w-[250px] h-[150px] transform scale-100 opacity-50 group-hover:scale-150 group-hover:opacity-100 transition-all duration-700 ease-out"
94 style={{ background: `radial-gradient(100% 100% at 0% 0%, #3EACCF18, transparent)` }}
95 /> */}
96 <div
97 className={cn(
98 'px-8 pb-8 relative',
99 'flex flex-col h-full',
100 icon ? 'gap-6' : 'gap-2',
101 !header ? 'pt-8' : ''
102 )}
103 >
104 <div className="flex items-center gap-3">
105 {icon && typeof icon === 'string' ? (
106 <IconBackground>
107 <img
108 className="w-5"
109 alt={title}
110 src={`${icon}${
111 hasLightIcon && !resolvedTheme?.includes('dark') ? '-light' : ''
112 }.svg`}
113 />
114 </IconBackground>
115 ) : (
116 icon && <IconBackground>{icon}</IconBackground>
117 )}
118 <p className="text-base text-foreground">{title}</p>
119 </div>
120
121 {children && <span className="text-sm text-foreground-light grow">{children}</span>}
122 {showLink && <span className="text-brand-link justify-end text-sm">Learn more</span>}
123 </div>
124 </div>
125 )
126}