UNPKG

aura-glass

Version:

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

223 lines (220 loc) 6.76 kB
'use client'; import { jsx, jsxs } from 'react/jsx-runtime'; import { GlassButton } from '../button/GlassButton.js'; import { cn } from '../../lib/utilsComprehensive.js'; import { forwardRef } from 'react'; 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 { useA11yId } from '../../utils/a11y.js'; import { useMotionPreferenceContext } from '../../contexts/MotionPreferenceContext.js'; /** * GlassBadge component * A glassmorphism badge with various styles and states */ const GlassBadge = /*#__PURE__*/forwardRef(({ // TODO: Integrate ContrastGuard for table cells, list items, badges, card titles, and other text content for WCAG AA compliance variant = "default", size = "sm", shape = "glass-radius-md", dot = false, leftIcon, rightIcon, removable = false, onRemove, animate = false, animation = "scale", respectMotionPreference = true, "aria-label": ariaLabel, className, children, ...props }, ref) => { const badgeId = useA11yId("badge"); const { prefersReducedMotion } = useMotionPreferenceContext(); const shouldAnimate = animate && (!respectMotionPreference || !prefersReducedMotion); const sizeClasses = { xs: dot ? "w-2 h-2" : "glass-px-1.5 glass-py-0.5 glass-text-xs", sm: dot ? "w-2.5 h-2.5" : "glass-px-2 glass-py-1 glass-text-xs", md: dot ? "w-3 h-3" : "glass-px-2.5 glass-py-1 glass-text-sm", lg: dot ? "w-3.5 h-3.5" : "glass-px-3 glass-py-1.5 glass-text-sm" }; const shapeClasses = { "glass-radius-md": "glass-radius-md", pill: "glass-radius-full", square: "rounded-none" }; const variantClasses = { default: "bg-muted/50 glass-text-secondary border-0", primary: "glass-surface-primary/10 glass-text-primary border-0", secondary: "bg-secondary/10 glass-text-primary/90 border-0", success: "glass-surface-success/10 glass-text-success border-0", warning: "glass-surface-warning/10 glass-text-primary border-0", error: "glass-surface-danger/10 glass-text-danger border-0", info: "glass-surface-info/10 glass-text-primary border-0", outline: "bg-transparent text-foreground border border-white/10", ghost: "bg-transparent glass-text-primary/70 border-0" }; const dotVariantClasses = { default: "bg-muted-foreground", primary: "bg-primary", secondary: "bg-secondary", success: "bg-success", warning: "bg-warning", error: "bg-destructive", info: "bg-info", outline: "bg-foreground", ghost: "bg-muted-foreground" }; const iconSize = { xs: "w-3 h-3", sm: "w-3 h-3", md: "w-4 h-4", lg: "w-4 h-4" }; const getAnimationPreset = () => { switch (animation) { case "scale": return "scaleIn"; case "fade": return "fadeIn"; case "bounce": return "bounceIn"; default: return "scaleIn"; } }; if (dot) { const content = jsx("span", { ref: ref, id: badgeId, className: cn("inline-block glass-radius-full flex-shrink-0", sizeClasses[size], dotVariantClasses[variant] ?? dotVariantClasses.default, className), role: "status", "aria-label": ariaLabel || `${variant} status indicator`, ...props }); return shouldAnimate ? jsx(MotionFramer, { preset: getAnimationPreset(), children: content }) : content; } const content = jsxs(OptimizedGlassCore, { elevation: variant === "ghost" ? undefined : "level1", intensity: "medium", depth: 2, tint: "neutral", border: "subtle", animation: "none", performanceMode: "medium", ref: ref, id: badgeId, className: cn("inline-flex items-center glass-gap-1 font-medium", "transition-all duration-200", sizeClasses[size], shapeClasses[shape], variantClasses[variant] ?? variantClasses.default, className), role: removable ? "button" : "status", "aria-label": ariaLabel || (children ? `Badge: ${children}` : `${variant} badge`), ...props, children: [leftIcon && jsx("span", { className: cn("flex-shrink-0", iconSize[size]), children: leftIcon }), children && jsx("span", { className: 'whitespace-nowrap', children: children }), rightIcon && !removable && jsx("span", { className: cn("flex-shrink-0", iconSize[size]), children: rightIcon }), removable && jsx(GlassButton, { type: "button", onClick: onRemove, className: cn("flex-shrink-0 flex items-center justify-center", "hover:bg-current/20 glass-radius-full transition-colors", "focus:outline-none focus:ring-1 focus:ring-current", iconSize[size]), "aria-label": "Remove badge", children: jsx("svg", { className: 'w-2.5 h-2.5', fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] }); return shouldAnimate ? jsx(MotionFramer, { preset: getAnimationPreset(), children: content }) : content; }); GlassBadge.displayName = "GlassBadge"; const StatusBadge = /*#__PURE__*/forwardRef(({ status, dotOnly = false, ...props }, ref) => { const statusConfig = { online: { variant: "success", label: "Online" }, offline: { variant: "default", label: "Offline" }, away: { variant: "warning", label: "Away" }, busy: { variant: "error", label: "Busy" }, pending: { variant: "warning", label: "Pending" }, active: { variant: "success", label: "Active" }, inactive: { variant: "default", label: "Inactive" } }; const config = statusConfig[status]; return jsx(GlassBadge, { ref: ref, variant: config.variant, dot: dotOnly, ...props, children: !dotOnly && config.label }); }); StatusBadge.displayName = "StatusBadge"; const CountBadge = /*#__PURE__*/forwardRef(({ count, max = 99, showZero = false, ...props }, ref) => { if (count <= 0 && !showZero) { return null; } const displayCount = count > max ? `${max}+` : count.toString(); return jsx(GlassBadge, { ref: ref, variant: "default", size: "xs", shape: "pill", ...props, children: displayCount }); }); CountBadge.displayName = "CountBadge"; export { CountBadge, GlassBadge, StatusBadge }; //# sourceMappingURL=GlassBadge.js.map