Glass Panel
A visually stunning glass panel that reacts to mouse movements and scrolls, perfect for modern UIs.
Glass Panel
This is a cool glass panel that reacts to mouse movements and scrolls.
tsx
1import {GlassPanel} from "@/components/ui/glass-panel";
2
3export function ComponentPreview () {
4 return (
5 <div className="flex flex-col items-center justify-center gap-8 p-8">
6 <GlassPanel className="w-full max-w-md p-6">
7 <h2 className="text-2xl font-bold mb-4">Glass Panel</h2>
8 <p className="text-gray-300 mb-4">
9 This is a cool glass panel that reacts to mouse movements and scrolls.
10 </p>
11 </GlassPanel>
12 </div>
13 );
14}Installation
First, install the necessary dependencies for the glass panel effect.
tsx
1npm install react-parallax-tilt framer-motion clsxNext, copy and paste the following component code into your project.
components/ui/glass-panel.tsx
1'use client';
2
3import React, { useRef, useEffect } from 'react';
4import { motion, useInView } from 'framer-motion';
5import { clsx } from 'clsx';
6import ParallaxTilt from 'react-parallax-tilt';
7
8const PanelStyles = () => (
9 <style jsx global>{`
10
11 .kinetic-panel-aurora-border {
12 position: relative;
13 overflow: hidden;
14 border-radius: 24px;
15 }
16
17 .kinetic-panel-aurora-border::before {
18 content: '';
19 position: absolute;
20 top: 0;
21 left: 0;
22 right: 0;
23 bottom: 0;
24 z-index: 0;
25
26 background: radial-gradient(
27 350px circle at var(--mouse-x) var(--mouse-y),
28 rgba(148, 163, 184, 0.25),
29 transparent 80%
30 );
31
32 padding: 1px;
33 border-radius: inherit;
34
35 -webkit-mask:
36 linear-gradient(#fff 0 0) content-box,
37 linear-gradient(#fff 0 0);
38 mask:
39 linear-gradient(#fff 0 0) content-box,
40 linear-gradient(#fff 0 0);
41 -webkit-mask-composite: xor;
42 mask-composite: exclude;
43 }
44 `}</style>
45);
46
47interface GlassPanelProps {
48 children: React.ReactNode;
49 className?: string;
50 tiltEnable?: boolean;
51}
52
53export const GlassPanel: React.FC<GlassPanelProps> = ({
54 children,
55 className,
56 tiltEnable = true,
57}) => {
58 const ref = useRef<HTMLDivElement>(null);
59 const isInView = useInView(ref, { once: true, amount: 0.2 });
60
61 useEffect(() => {
62 const el = ref.current;
63 if (!el) return;
64
65 const handleMouseMove = (e: MouseEvent) => {
66 const rect = el.getBoundingClientRect();
67 el.style.setProperty('--mouse-x', `${e.clientX - rect.left}px`);
68 el.style.setProperty('--mouse-y', `${e.clientY - rect.top}px`);
69 };
70
71 el.addEventListener('mousemove', handleMouseMove);
72 return () => {
73 if (el) {
74 el.removeEventListener('mousemove', handleMouseMove);
75 }
76 };
77 }, []);
78
79 const contentPanel = (
80 <motion.div
81 ref={ref}
82 initial={{ opacity: 0, y: 50, filter: 'blur(8px)' }}
83 animate={isInView ? { opacity: 1, y: 0, filter: 'blur(0px)' } : {}}
84 transition={{ duration: 1.2, ease: [0.16, 1, 0.3, 1] }}
85 className={clsx(
86 'kinetic-panel-aurora-border',
87 'relative bg-white/5 backdrop-blur-xl',
88 'border border-white/10 rounded-3xl p-8',
89 'shadow-2xl shadow-black/40',
90 className
91 )}
92 >
93 <div className="relative z-10">{children}</div>
94 </motion.div>
95 );
96
97 return (
98 <>
99 <PanelStyles />
100
101 {tiltEnable ? (
102 <ParallaxTilt
103 tiltMaxAngleX={4}
104 tiltMaxAngleY={4}
105 glareEnable={true}
106 glareMaxOpacity={0.1}
107 glarePosition="all"
108 scale={1.02}
109 transitionSpeed={3000}
110 >
111 {contentPanel}
112 </ParallaxTilt>
113 ) : (
114 contentPanel
115 )}
116 </>
117 );
118};