UNPKG

aura-glass

Version:

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

121 lines (118 loc) 4.34 kB
'use client'; import React, { forwardRef } from 'react'; import { cn } from '../../design-system/utilsCore.js'; import { useReducedMotion } from '../../hooks/useReducedMotion.js'; /** * Advanced Glass Primitive Component * Token-first glassmorphism with full a11y support */ const GlassAdvanced = /*#__PURE__*/forwardRef(({ as: Component = 'div', elev = 2, variant = 'default', radius = 'lg', blur = 'lg', motion = 'none', interactive = false, contrast = 'auto', disabled = false, noise = false, specular = false, edge = false, glow = 'none', className, children, onKeyDown, onClick, role, tabIndex, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, 'aria-describedby': ariaDescribedBy, ...props }, ref) => { // MOTION_RESPECT: Check for reduced motion preference const prefersReducedMotion = useReducedMotion(); // Handle keyboard accessibility for interactive elements const isClickable = !!onClick && !disabled; const computedRole = role || (isClickable && Component === 'div' ? 'button' : undefined); const computedTabIndex = tabIndex ?? (isClickable || interactive ? 0 : undefined); const handleKeyDown = e => { // Call custom handler first onKeyDown?.(e); // Handle space/enter for clickable divs if (isClickable && Component === 'div' && (e.key === 'Enter' || e.key === ' ')) { e.preventDefault(); onClick?.(e); } }; // Token validation in development if (process.env.NODE_ENV === 'development') { const validElevations = [0, 1, 2, 3, 4, 5, 6]; const validRadii = ['none', 'sm', 'md', 'lg', 'xl', '2xl', 'full']; const validBlurs = ['none', 'sm', 'md', 'lg', 'xl']; const validMotions = ['none', 'float', 'shimmer', 'ambient', 'press']; if (!validElevations.includes(elev)) { console.warn(`GlassAdvanced: Invalid elevation "${elev}". Use 0-6.`); } if (!validRadii.includes(radius)) { console.warn(`GlassAdvanced: Invalid radius "${radius}". Use ${validRadii.join(', ')}.`); } if (!validBlurs.includes(blur)) { console.warn(`GlassAdvanced: Invalid blur "${blur}". Use ${validBlurs.join(', ')}.`); } if (!validMotions.includes(motion)) { console.warn(`GlassAdvanced: Invalid motion "${motion}". Use ${validMotions.join(', ')}.`); } } // Build class names using tokens const classes = cn( // Base glass foundation 'glass-foundation-complete', // Elevation elev > 0 && `glass-elev-${elev}`, // Radius `glass-radius-${radius}`, // CLASS_PREFIX: Blur classes use 'glass-' prefix blur !== 'lg' && `glass-blur-${blur}`, // Variant surfaces variant !== 'default' && `glass-surface-${variant}`, // MOTION_RESPECT: Respect reduced motion preference for animations motion !== 'none' && !prefersReducedMotion && `glass-animate-${motion}`, // Interactive states interactive && 'glass-state-hoverable glass-state-active', // CONTRAST_GUARD: Glass elements need contrast guard class contrast === 'auto' && 'glass-contrast-guard', // Disabled state disabled && 'glass-state-disabled', // Overlay effects noise && 'glass-overlay-noise', specular && 'glass-overlay-specular', edge && 'glass-edge', // Glow effects glow !== 'none' && `glass-glow${glow !== 'default' ? `-${glow}` : ''}`, // INTERACTIVE_FOCUS: Interactive elements with onClick need glass-focus class (isClickable || interactive) && 'glass-focus', // Custom classes className); // TOUCH_TARGET: Ensure minimum touch target for interactive elements const touchTargetClasses = isClickable || interactive ? 'glass-touch-target' : ''; return /*#__PURE__*/React.createElement(Component, { ref, className: cn(classes, touchTargetClasses), role: computedRole, tabIndex: computedTabIndex, 'aria-disabled': disabled || undefined, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, 'aria-describedby': ariaDescribedBy, onClick: disabled ? undefined : onClick, onKeyDown: handleKeyDown, ...props }, /*#__PURE__*/React.createElement('div', { className: 'glass-layer-frost' }), /*#__PURE__*/React.createElement('div', { className: 'glass-layer-ink' }, children)); }); GlassAdvanced.displayName = 'GlassAdvanced'; export { GlassAdvanced }; //# sourceMappingURL=GlassAdvanced.js.map