UNPKG

aura-glass

Version:

A comprehensive glassmorphism design system for React applications with 142+ production-ready components

171 lines (168 loc) 6.1 kB
'use client'; import { jsxs, jsx } from 'react/jsx-runtime'; import { useMotionPreferenceContext } from '../../contexts/MotionPreferenceContext.js'; import { createMotionAwareVariants, createMotionAwareInteractive } from '../../lib/motionPrimitives.js'; import { cn } from '../../lib/utilsComprehensive.js'; import { motion } from 'framer-motion'; import { forwardRef } from 'react'; import '../../tokens/glass.js'; /** * Motion-aware Glass component that automatically respects user's motion preferences * Provides beautiful glass morphism effects while being fully accessible */ const MotionAwareGlass = /*#__PURE__*/forwardRef(({ variant = "base", interactive = false, animationType = "fadeInUp", children, className, asButton = false, disabled = false, ...props }, ref) => { const { prefersReducedMotion, isMotionSafe } = useMotionPreferenceContext(); // Get appropriate glass variant classes const getVariantClasses = () => { const baseClasses = "backdrop-filter border border-opacity-20 glass-radius-lg"; switch (variant) { case "subtle": return cn(baseClasses, "glass-subtle bg-white/5 border-white/10"); case "strong": return cn(baseClasses, "glass-strong bg-white/10 border-white/20"); case "card": return cn(baseClasses, "glass-foundation-complete bg-white/8 border-white/15 glass-p-6 shadow-lg"); case "button": return cn(baseClasses, "glass-button-secondary bg-white/8 border-white/15 glass-px-6 glass-py-3 cursor-pointer"); case "input": return cn(baseClasses, "glass-input bg-white/5 border-white/10 glass-px-4 glass-py-2"); default: return cn(baseClasses, "glass-foundation-complete bg-white/8 border-white/15"); } }; // Get motion variants based on animation type and motion preference const getAnimationVariants = () => { switch (animationType) { case "fadeInScale": return createMotionAwareVariants.fadeInScale(prefersReducedMotion); case "slideLeft": return createMotionAwareVariants.slideIn("left", prefersReducedMotion); case "slideRight": return createMotionAwareVariants.slideIn("right", prefersReducedMotion); default: return createMotionAwareVariants.fadeInUp(prefersReducedMotion); } }; // Get interactive variants for hover/tap effects const getInteractiveVariants = () => { if (!interactive || disabled) return {}; if (variant === "button" || asButton) { return createMotionAwareInteractive.button(prefersReducedMotion); } if (variant === "card") { return createMotionAwareInteractive.card(prefersReducedMotion); } // Default interactive behavior if (prefersReducedMotion) { return { hover: { backgroundColor: '/* Use createGlassStyle({ intent: "neutral", elevation: "level2" }) */', borderColor: "var(--glass-bg-default)", transition: { duration: 0.001 } } }; } return { hover: { backgroundColor: '/* Use createGlassStyle({ intent: "neutral", elevation: "level2" }) */', borderColor: "var(--glass-bg-default)", y: -2, transition: { duration: 0.2 } }, tap: { y: -1, transition: { duration: 0.1 } } }; }; const combinedClassName = cn(getVariantClasses(), { "glass-card-motion-aware": interactive && !prefersReducedMotion, "cursor-pointer": (interactive || asButton) && !disabled, "cursor-not-allowed opacity-50": disabled, "focus:outline-none focus:ring-3 focus:ring-blue-500/50": asButton || interactive, "transition-none": prefersReducedMotion }, className); const animationVariants = getAnimationVariants(); const interactiveVariants = getInteractiveVariants(); // Combine all motion props ({ variants: animationVariants, initial: "hidden", animate: "visible", ...(interactive && interactiveVariants && typeof interactiveVariants === "object" && { whileHover: "hover" in interactiveVariants ? "hover" : undefined, whileTap: "tap" in interactiveVariants ? "tap" : undefined }), ...props }); // Add accessibility attributes for buttons const accessibilityProps = asButton || interactive ? { role: asButton ? "button" : undefined, tabIndex: disabled ? -1 : 0, "aria-disabled": disabled, onKeyDown: e => { if ((e.key === "Enter" || e.key === " ") && (asButton || interactive) && !disabled) { e.preventDefault(); props?.onClick?.(e); } } } : {}; return jsxs(motion.div, { ref: ref, className: combinedClassName, variants: animationVariants, initial: "hidden", animate: "visible", whileHover: interactive && "hover" in interactiveVariants ? "hover" : undefined, whileTap: interactive && "tap" in interactiveVariants ? "tap" : undefined, ...props, ...accessibilityProps, children: [children, prefersReducedMotion && jsx("span", { className: 'sr-only', children: "Motion reduced for accessibility" })] }); }); MotionAwareGlass.displayName = "MotionAwareGlass"; // Specialized variants for common use cases const MotionAwareGlassCard = /*#__PURE__*/forwardRef((props, ref) => jsx(MotionAwareGlass, { ref: ref, variant: "card", interactive: true, ...props })); MotionAwareGlassCard.displayName = "MotionAwareGlassCard"; const MotionAwareGlassButton = /*#__PURE__*/forwardRef((props, ref) => jsx(MotionAwareGlass, { ref: ref, variant: "button", asButton: true, interactive: true, ...props })); MotionAwareGlassButton.displayName = "MotionAwareGlassButton"; const MotionAwareGlassInput = /*#__PURE__*/forwardRef((props, ref) => jsx(MotionAwareGlass, { ref: ref, variant: "input", ...props })); MotionAwareGlassInput.displayName = "MotionAwareGlassInput"; export { MotionAwareGlass, MotionAwareGlassButton, MotionAwareGlassCard, MotionAwareGlassInput, MotionAwareGlass as default }; //# sourceMappingURL=MotionAwareGlass.js.map