aura-glass
Version:
A comprehensive glassmorphism design system for React applications with 142+ production-ready components
149 lines (146 loc) • 5.42 kB
JavaScript
'use client';
import { jsx, jsxs } from 'react/jsx-runtime';
import { cn } from '../../lib/utilsComprehensive.js';
import React, { useState, useContext, createContext } 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';
// Context for toggle group
const ToggleGroupContext = /*#__PURE__*/createContext(null);
const useToggleGroupContext = () => {
return useContext(ToggleGroupContext);
};
/**
* GlassToggle component
* A glassmorphism toggle button
*/
const GlassToggle = /*#__PURE__*/React.forwardRef(({
pressed: controlledPressed,
defaultPressed = false,
onPressedChange,
size = "md",
variant = "default",
disabled = false,
children,
leftIcon,
rightIcon,
className,
shape = "glass-radius-md",
animation = "scale",
...props
}, ref) => {
const [internalPressed, setInternalPressed] = useState(defaultPressed);
const pressed = controlledPressed !== undefined ? controlledPressed : internalPressed;
// Check if this toggle is part of a group
const groupContext = useToggleGroupContext();
const isInGroup = !!groupContext;
const handleClick = () => {
if (disabled) return;
if (isInGroup && "value" in props) {
// Handle as group item
const itemValue = props.value;
const currentValues = groupContext.value || [];
if (groupContext.type === "single") {
const newValues = currentValues.includes(itemValue) ? [] : [itemValue];
groupContext.onValueChange?.(newValues);
} else {
const newValues = currentValues.includes(itemValue) ? currentValues.filter(v => v !== itemValue) : [...currentValues, itemValue];
groupContext.onValueChange?.(newValues);
}
} else {
// Handle as standalone toggle
const newPressed = !pressed;
if (controlledPressed === undefined) {
setInternalPressed(newPressed);
}
onPressedChange?.(newPressed);
}
};
const sizeClasses = {
sm: "h-8 glass-px-3 glass-text-sm",
md: "h-10 glass-px-4 glass-text-base",
lg: "h-12 glass-px-6 glass-text-lg"
};
const shapeClasses = {
"glass-radius-md": "glass-radius-lg",
square: "rounded-none",
circle: "glass-radius-full"
};
const getVariantClasses = () => {
const baseClasses = "glass-backdrop-blur-md border border-white/20 transition-all duration-300";
switch (variant) {
case "outline":
return cn(baseClasses, pressed ? "bg-black/40 border-white/40 glass-text-primary shadow-lg" : "bg-black/20 hover:bg-black/30 glass-text-primary/80 hover:glass-text-primary hover:border-white/30");
case "ghost":
return cn(pressed ? "bg-black/30 glass-text-primary shadow-md" : "hover:bg-black/20 glass-text-primary/70 hover:glass-text-primary", "transition-all duration-300");
default:
return cn(baseClasses, pressed ? "bg-black/40 border-white/40 glass-text-primary shadow-lg scale-105" : "bg-black/20 hover:bg-black/30 glass-text-primary/80 hover:glass-text-primary hover:border-white/30 hover:scale-105");
}
};
const getAnimationProps = () => {
if (animation === "none") return {};
switch (animation) {
case "scale":
return {
whileHover: {
scale: disabled ? 1 : 1.05
},
whileTap: {
scale: disabled ? 1 : 0.95
}
};
case "slide":
return {
initial: {
x: pressed ? 2 : 0
},
animate: {
x: pressed ? 2 : 0
},
whileHover: {
x: pressed ? 4 : 2
}
};
default:
return {};
}
};
return jsx(MotionFramer, {
"data-glass-component": true,
...getAnimationProps(),
className: 'inline-block',
children: jsxs(OptimizedGlassCore, {
intent: "neutral",
elevation: pressed ? "level3" : "level1",
intensity: "medium",
depth: 2,
tint: "neutral",
border: "subtle",
animation: "none",
performanceMode: "medium",
ref: ref,
className: cn("relative flex items-center justify-center glass-gap-2 font-medium", "focus:outline-none focus:ring-2 focus:ring-white/30 focus:ring-offset-2 focus:ring-offset-transparent", "disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:transform-none", sizeClasses[size], shapeClasses[shape], getVariantClasses(), className),
onClick: handleClick,
"aria-pressed": pressed,
...props,
children: [leftIcon && jsx("span", {
className: "glass-flex glass-items-center glass-justify-center",
children: leftIcon
}), children && jsx("span", {
className: "glass-flex glass-items-center glass-justify-center",
children: children
}), rightIcon && jsx("span", {
className: "glass-flex glass-items-center glass-justify-center",
children: rightIcon
}), variant === "ghost" && pressed && jsx("div", {
className: 'absolute inset-0 glass-surface-subtle/10 glass-radius-lg animate-pulse'
})]
})
});
});
GlassToggle.displayName = "GlassToggle";
export { GlassToggle };
//# sourceMappingURL=GlassToggle.js.map