aura-glass
Version:
A comprehensive glassmorphism design system for React applications with 142+ production-ready components
204 lines (201 loc) • 7.8 kB
JavaScript
'use client';
import { jsx, jsxs } from 'react/jsx-runtime';
import { forwardRef, useState, useRef } from 'react';
import { cn } from '../../lib/utilsComprehensive.js';
import '../../primitives/GlassCore.js';
import '../../primitives/glass/GlassAdvanced.js';
import { OptimizedGlassCore } from '../../primitives/OptimizedGlassCore.js';
import '../../primitives/glass/OptimizedGlassAdvanced.js';
import '../../primitives/MotionNative.js';
import { MotionFramer } from '../../primitives/motion/MotionFramer.js';
import { useReducedMotion } from '../../hooks/useReducedMotion.js';
import { useGlassParallax } from '../../hooks/useGlassParallax.js';
/**
* FrostedGlass Component
* Modern implementation using OptimizedGlass with frost effects
*/
const FrostedGlass = /*#__PURE__*/forwardRef(({
children,
className,
style,
elevation = "level2",
blurStrength = "standard",
opacity = "medium",
borderOpacity = "medium",
borderWidth = 1,
fullWidth = false,
fullHeight = false,
borderRadius = "md",
interactive = true,
padding = 16,
intensity = 0.5,
frostColor = "rgba(var(--glass-color-white) / var(--glass-opacity-80))",
animate = true,
pattern = "noise",
backgroundColor,
specular = true,
glow = false,
lightAngle = 135,
parallax = false,
parallaxStrength = 10,
...rest
}, ref) => {
const prefersReducedMotion = useReducedMotion();
const shouldAnimate = animate && !prefersReducedMotion;
const [isHovered, setIsHovered] = useState(false);
const containerRef = useRef(null);
// Handle parallax when enabled
useGlassParallax(containerRef, {
strength: parallaxStrength,
enabled: parallax && !prefersReducedMotion
});
// Map blur strength to intensity
const intensityMap = {
none: "subtle",
light: "subtle",
standard: "medium",
heavy: "strong"
};
// Map border radius
const radiusMap = {
none: "rounded-none",
sm: "glass-radius-sm",
md: "glass-radius-md",
lg: "glass-radius-lg",
xl: "glass-radius-xl",
full: "glass-radius-full"
};
// Map elevation to OptimizedGlass elevation levels
const getElevationLevel = elev => {
if (typeof elev === "string" && elev.startsWith("level")) {
return elev;
}
const numElev = typeof elev === "number" ? elev : 2;
if (numElev <= 1) return "level1";
if (numElev <= 2) return "level2";
if (numElev <= 3) return "level3";
return "level4";
};
// Generate frost pattern styles
const getFrostPattern = () => {
switch (pattern) {
case "lines":
return {
backgroundImage: `
linear-gradient(90deg, ${frostColor} 1px, transparent 1px),
linear-gradient(${frostColor} 1px, transparent 1px)
`,
backgroundSize: "20px 20px"
};
case "crystals":
return {
backgroundImage: `
radial-gradient(${frostColor} 5%, transparent 5%),
radial-gradient(${frostColor} 5%, transparent 5%)
`,
backgroundSize: "30px 30px",
backgroundPosition: "0 0, 15px 15px"
};
case "noise":
default:
return {
backgroundImage: `url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E")`,
backgroundSize: "100px 100px"
};
}
};
// Handle mouse events
const handleMouseEnter = () => setIsHovered(true);
const handleMouseLeave = () => setIsHovered(false);
// Merge refs
const setRefs = node => {
containerRef.current = node;
if (typeof ref === "function") ref(node);else if (ref) ref.current = node;
};
const frostPatternStyles = getFrostPattern();
const glowColor = typeof glow === "string" ? glow : glow === true ? "primary" : false;
return jsx(MotionFramer, {
preset: shouldAnimate ? "fadeIn" : "none",
className: 'relative isolate',
children: jsxs(OptimizedGlassCore, {
ref: setRefs,
intent: "neutral",
elevation: getElevationLevel(elevation),
intensity: intensityMap[blurStrength],
depth: 2,
tint: "cool",
border: borderOpacity === "none" ? "none" : "subtle",
animation: shouldAnimate ? "breathe" : "none",
performanceMode: "high",
liftOnHover: interactive,
press: interactive,
className: cn(
// Base styles
"relative block box-border overflow-hidden isolate", "transition-all duration-300",
// Size
fullWidth && "w-full", fullHeight && "h-full", !fullWidth && !fullHeight && "w-auto h-auto",
// Border radius
typeof borderRadius === "string" ? radiusMap[borderRadius] : `rounded-[${borderRadius}px]`,
// Padding
typeof padding === "number" ? `p-${Math.round(padding / 4)}` : "glass-p-4",
// Interactive styles
interactive && ["cursor-pointer", "hover:-translate-y-0.5", "active:translate-y-0"],
// Glow effect
glowColor && {
primary: "drop-shadow-[0_0_18px_var(--glass-color-primary,0.28)]",
success: "drop-shadow-[0_0_18px_var(--glass-color-success,0.28)]",
warning: "drop-shadow-[0_0_18px_var(--glass-color-warning,0.28)]",
danger: "drop-shadow-[0_0_18px_var(--glass-color-danger,0.28)]",
info: "drop-shadow-[0_0_18px_rgba(14,165,233,0.28)]"
}[glowColor], className),
style: {
backgroundColor,
borderWidth: borderWidth > 0 ? `${borderWidth}px` : undefined,
...style
},
onMouseEnter: handleMouseEnter,
onMouseLeave: handleMouseLeave,
...rest,
children: [jsx("div", {
className: cn("absolute inset-0 pointer-events-none", shouldAnimate && "animate-frost-grow"),
style: {
...frostPatternStyles,
// Reduce overlay strength to avoid washing out label text
opacity: 0.18 + intensity * 0.22,
// Use soft-light for gentler interaction with backdrop
mixBlendMode: "soft-light"
}
}), jsx("div", {
className: cn("absolute inset-0 pointer-events-none", shouldAnimate && "animate-frost-sparkle"),
style: {
backgroundImage: `radial-gradient(${frostColor} 1px, transparent 1px)`,
backgroundSize: "30px 30px",
// Tone down sparkle overlay for readability
opacity: Math.min(0.22, intensity * 0.25)
}
}), jsx("div", {
className: 'absolute inset-0 pointer-events-none glass-radius-inherit',
style: {
// Edge frost (less aggressive)
boxShadow: `inset 0 0 ${4 + intensity * 9}px ${frostColor}`,
opacity: isHovered ? 0.24 + intensity * 0.25 : 0.18 + intensity * 0.2,
// Specular highlight (dimmed)
background: specular ? `
radial-gradient(${intensity * 70 + 40}% ${intensity * 35 + 40}% at 50% -10%, rgba(255,255,255, ${Math.min(0.25, 0.1 + intensity * 0.22)}) 0%, rgba(255,255,255,0.0) 60%),
linear-gradient(${lightAngle}deg, rgba(255,255,255,0.12), rgba(255,255,255,0.00) 35%)
` : undefined,
// Softer blending to preserve label contrast
mixBlendMode: specular ? "overlay" : "normal",
transform: parallax ? "translate(var(--glass-parallax-x), var(--glass-parallax-y))" : undefined,
transition: "transform 150ms ease-out, opacity 300ms ease"
}
}), jsx("div", {
className: 'relative z-10',
children: children
})]
})
});
});
FrostedGlass.displayName = "FrostedGlass";
export { FrostedGlass, FrostedGlass as default };
//# sourceMappingURL=FrostedGlass.js.map