anicompo
Version:
A collection of beautiful React components with advanced glass morphism effects and Framer Motion animations
1,693 lines (1,666 loc) • 181 kB
JavaScript
'use strict';
var React = require('react');
var framerMotion = require('framer-motion');
var jsxRuntime = require('react/jsx-runtime');
const LiquidGlassButton = ({
children = "Button",
onClick,
variant = "primary",
size = "medium",
disabled = false,
className = "",
style = {},
...props
}) => {
const buttonRef = React.useRef(null);
const [mousePosition, setMousePosition] = React.useState({
x: 0,
y: 0
});
const [isPressed, setIsPressed] = React.useState(false);
// Motion values for parallax effect
const mouseX = framerMotion.useMotionValue(0);
const mouseY = framerMotion.useMotionValue(0);
// Transform mouse position to rotation and translation
const rotateX = framerMotion.useTransform(mouseY, [-100, 100], [15, -15]);
const rotateY = framerMotion.useTransform(mouseX, [-100, 100], [-15, 15]);
const translateZ = framerMotion.useTransform(mouseX, [-100, 100], [-10, 10]);
// Spring animations for smooth transitions
const springConfig = {
damping: 15,
stiffness: 150
};
const springRotateX = framerMotion.useSpring(rotateX, springConfig);
const springRotateY = framerMotion.useSpring(rotateY, springConfig);
const springTranslateZ = framerMotion.useSpring(translateZ, springConfig);
// Handle mouse movement for parallax effect
React.useEffect(() => {
const handleMouseMove = e => {
if (!buttonRef.current) return;
const rect = buttonRef.current.getBoundingClientRect();
const centerX = rect.left + rect.width / 2;
const centerY = rect.top + rect.height / 2;
const x = e.clientX - centerX;
const y = e.clientY - centerY;
mouseX.set(x);
mouseY.set(y);
setMousePosition({
x,
y
});
};
const handleMouseLeave = () => {
mouseX.set(0);
mouseY.set(0);
setMousePosition({
x: 0,
y: 0
});
};
const button = buttonRef.current;
if (button) {
button.addEventListener('mousemove', handleMouseMove);
button.addEventListener('mouseleave', handleMouseLeave);
}
return () => {
if (button) {
button.removeEventListener('mousemove', handleMouseMove);
button.removeEventListener('mouseleave', handleMouseLeave);
}
};
}, [mouseX, mouseY]);
// Variant styles
const variants = {
primary: {
background: `
linear-gradient(135deg,
rgba(255, 255, 255, 0.1) 0%,
rgba(255, 255, 255, 0.05) 50%,
rgba(255, 255, 255, 0.1) 100%
),
radial-gradient(
circle at 30% 30%,
rgba(255, 255, 255, 0.2) 0%,
transparent 50%
)
`,
borderColor: 'rgba(255, 255, 255, 0.3)',
color: 'rgba(255, 255, 255, 0.9)',
shadowColor: 'rgba(0, 123, 255, 0.3)'
},
secondary: {
background: `
linear-gradient(135deg,
rgba(255, 255, 255, 0.08) 0%,
rgba(255, 255, 255, 0.03) 50%,
rgba(255, 255, 255, 0.08) 100%
),
radial-gradient(
circle at 70% 70%,
rgba(255, 255, 255, 0.15) 0%,
transparent 50%
)
`,
borderColor: 'rgba(255, 255, 255, 0.2)',
color: 'rgba(255, 255, 255, 0.8)',
shadowColor: 'rgba(255, 255, 255, 0.2)'
},
success: {
background: `
linear-gradient(135deg,
rgba(40, 167, 69, 0.1) 0%,
rgba(40, 167, 69, 0.05) 50%,
rgba(40, 167, 69, 0.1) 100%
),
radial-gradient(
circle at 30% 30%,
rgba(40, 167, 69, 0.2) 0%,
transparent 50%
)
`,
borderColor: 'rgba(40, 167, 69, 0.3)',
color: 'rgba(255, 255, 255, 0.9)',
shadowColor: 'rgba(40, 167, 69, 0.3)'
},
danger: {
background: `
linear-gradient(135deg,
rgba(220, 53, 69, 0.1) 0%,
rgba(220, 53, 69, 0.05) 50%,
rgba(220, 53, 69, 0.1) 100%
),
radial-gradient(
circle at 70% 70%,
rgba(220, 53, 69, 0.2) 0%,
transparent 50%
)
`,
borderColor: 'rgba(220, 53, 69, 0.3)',
color: 'rgba(255, 255, 255, 0.9)',
shadowColor: 'rgba(220, 53, 69, 0.3)'
}
};
// Size styles
const sizes = {
small: {
padding: '8px 16px',
fontSize: '14px',
borderRadius: '8px',
minHeight: '32px'
},
medium: {
padding: '12px 24px',
fontSize: '16px',
borderRadius: '12px',
minHeight: '44px'
},
large: {
padding: '16px 32px',
fontSize: '18px',
borderRadius: '16px',
minHeight: '56px'
}
};
const currentVariant = variants[variant] || variants.primary;
const currentSize = sizes[size] || sizes.medium;
return /*#__PURE__*/jsxRuntime.jsxs(framerMotion.motion.button, {
ref: buttonRef,
onClick: onClick,
disabled: disabled,
className: `liquid-glass-button ${className}`,
style: {
position: 'relative',
border: `1px solid ${currentVariant.borderColor}`,
borderRadius: currentSize.borderRadius,
padding: currentSize.padding,
fontSize: currentSize.fontSize,
minHeight: currentSize.minHeight,
color: currentVariant.color,
background: currentVariant.background,
backdropFilter: 'blur(20px)',
WebkitBackdropFilter: 'blur(20px)',
backgroundBlendMode: 'overlay',
mixBlendMode: 'normal',
cursor: disabled ? 'not-allowed' : 'pointer',
outline: 'none',
transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
transformStyle: 'preserve-3d',
perspective: '1000px',
...style
},
whileHover: {
scale: disabled ? 1 : 1.02,
boxShadow: disabled ? 'none' : `
0 20px 40px rgba(0, 0, 0, 0.3),
0 0 20px ${currentVariant.shadowColor},
inset 0 1px 0 rgba(255, 255, 255, 0.2)
`,
filter: disabled ? 'none' : 'brightness(1.1)',
transition: {
duration: 0.2
}
},
whileTap: {
scale: disabled ? 1 : 0.98,
boxShadow: disabled ? 'none' : `
0 10px 20px rgba(0, 0, 0, 0.4),
inset 0 2px 4px rgba(0, 0, 0, 0.1)
`,
transition: {
duration: 0.1
}
},
animate: {
rotateX: disabled ? 0 : springRotateX,
rotateY: disabled ? 0 : springRotateY,
translateZ: disabled ? 0 : springTranslateZ
},
onMouseDown: () => !disabled && setIsPressed(true),
onMouseUp: () => setIsPressed(false),
onMouseLeave: () => setIsPressed(false),
...props,
children: [/*#__PURE__*/jsxRuntime.jsx(framerMotion.motion.div, {
style: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
background: `
linear-gradient(
135deg,
rgba(255, 255, 255, 0.1) 0%,
transparent 50%,
rgba(255, 255, 255, 0.05) 100%
)
`,
borderRadius: 'inherit',
pointerEvents: 'none',
mixBlendMode: 'overlay'
},
animate: {
opacity: isPressed ? 0.3 : 0.6,
scale: isPressed ? 0.95 : 1
},
transition: {
duration: 0.2
}
}), /*#__PURE__*/jsxRuntime.jsx(framerMotion.motion.div, {
style: {
position: 'absolute',
top: '2px',
left: '2px',
right: '2px',
bottom: '2px',
background: `
radial-gradient(
circle at 50% 0%,
rgba(255, 255, 255, 0.1) 0%,
transparent 70%
)
`,
borderRadius: 'inherit',
pointerEvents: 'none',
filter: 'blur(1px)'
},
animate: {
opacity: isPressed ? 0.1 : 0.3
},
transition: {
duration: 0.2
}
}), /*#__PURE__*/jsxRuntime.jsx(framerMotion.motion.span, {
style: {
position: 'relative',
zIndex: 1,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: '8px',
fontWeight: 500,
letterSpacing: '0.5px',
textShadow: '0 1px 2px rgba(0, 0, 0, 0.3)'
},
animate: {
y: isPressed ? 1 : 0
},
transition: {
duration: 0.1
},
children: children
}), /*#__PURE__*/jsxRuntime.jsx(framerMotion.motion.div, {
style: {
position: 'absolute',
top: '50%',
left: '50%',
width: 0,
height: 0,
borderRadius: '50%',
background: 'rgba(255, 255, 255, 0.3)',
transform: 'translate(-50%, -50%)',
pointerEvents: 'none'
},
initial: {
scale: 0,
opacity: 0
},
animate: {
scale: isPressed ? 2 : 0,
opacity: isPressed ? 0 : 0
},
transition: {
duration: 0.6,
ease: 'easeOut'
}
})]
});
};
const ButtonDemo = () => {
const [clickCount, setClickCount] = React.useState(0);
const [isLoading, setIsLoading] = React.useState(false);
const handleClick = () => {
setClickCount(prev => prev + 1);
};
const handleAsyncClick = async () => {
setIsLoading(true);
await new Promise(resolve => setTimeout(resolve, 2000));
setIsLoading(false);
setClickCount(prev => prev + 1);
};
return /*#__PURE__*/jsxRuntime.jsxs("div", {
style: {
minHeight: '100vh',
background: `
linear-gradient(135deg, #667eea 0%, #764ba2 100%),
radial-gradient(circle at 20% 80%, #f093fb 0%, transparent 50%),
radial-gradient(circle at 80% 20%, #f5576c 0%, transparent 50%),
radial-gradient(circle at 40% 40%, #4facfe 0%, transparent 50%)
`,
backgroundBlendMode: 'overlay, screen, screen, screen',
padding: '40px 20px',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: '40px',
fontFamily: 'system-ui, -apple-system, sans-serif'
},
children: [/*#__PURE__*/jsxRuntime.jsxs(framerMotion.motion.div, {
initial: {
opacity: 0,
y: -50
},
animate: {
opacity: 1,
y: 0
},
transition: {
duration: 0.8
},
style: {
textAlign: 'center',
color: 'white',
marginBottom: '20px'
},
children: [/*#__PURE__*/jsxRuntime.jsx("h1", {
style: {
fontSize: '3rem',
fontWeight: 'bold',
margin: '0 0 10px 0',
textShadow: '0 4px 8px rgba(0, 0, 0, 0.3)',
background: 'linear-gradient(45deg, #fff, #f0f0f0)',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent',
backgroundClip: 'text'
},
children: "Liquid Glass Button"
}), /*#__PURE__*/jsxRuntime.jsx("p", {
style: {
fontSize: '1.2rem',
opacity: 0.9,
margin: '0',
textShadow: '0 2px 4px rgba(0, 0, 0, 0.3)'
},
children: "Advanced glass morphism with Framer Motion animations"
})]
}), /*#__PURE__*/jsxRuntime.jsxs(framerMotion.motion.div, {
initial: {
opacity: 0,
y: 30
},
animate: {
opacity: 1,
y: 0
},
transition: {
duration: 0.8,
delay: 0.2
},
style: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: '20px',
width: '100%',
maxWidth: '800px'
},
children: [/*#__PURE__*/jsxRuntime.jsx("h2", {
style: {
color: 'white',
fontSize: '2rem',
margin: '0',
textShadow: '0 2px 4px rgba(0, 0, 0, 0.3)'
},
children: "Button Variants"
}), /*#__PURE__*/jsxRuntime.jsxs("div", {
style: {
display: 'flex',
gap: '20px',
flexWrap: 'wrap',
justifyContent: 'center'
},
children: [/*#__PURE__*/jsxRuntime.jsx(LiquidGlassButton, {
variant: "primary",
onClick: handleClick,
children: "Primary"
}), /*#__PURE__*/jsxRuntime.jsx(LiquidGlassButton, {
variant: "secondary",
onClick: handleClick,
children: "Secondary"
}), /*#__PURE__*/jsxRuntime.jsx(LiquidGlassButton, {
variant: "success",
onClick: handleClick,
children: "Success"
}), /*#__PURE__*/jsxRuntime.jsx(LiquidGlassButton, {
variant: "danger",
onClick: handleClick,
children: "Danger"
})]
})]
}), /*#__PURE__*/jsxRuntime.jsxs(framerMotion.motion.div, {
initial: {
opacity: 0,
y: 30
},
animate: {
opacity: 1,
y: 0
},
transition: {
duration: 0.8,
delay: 0.4
},
style: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: '20px',
width: '100%',
maxWidth: '800px'
},
children: [/*#__PURE__*/jsxRuntime.jsx("h2", {
style: {
color: 'white',
fontSize: '2rem',
margin: '0',
textShadow: '0 2px 4px rgba(0, 0, 0, 0.3)'
},
children: "Button Sizes"
}), /*#__PURE__*/jsxRuntime.jsxs("div", {
style: {
display: 'flex',
gap: '20px',
flexWrap: 'wrap',
justifyContent: 'center',
alignItems: 'center'
},
children: [/*#__PURE__*/jsxRuntime.jsx(LiquidGlassButton, {
size: "small",
onClick: handleClick,
children: "Small"
}), /*#__PURE__*/jsxRuntime.jsx(LiquidGlassButton, {
size: "medium",
onClick: handleClick,
children: "Medium"
}), /*#__PURE__*/jsxRuntime.jsx(LiquidGlassButton, {
size: "large",
onClick: handleClick,
children: "Large"
})]
})]
}), /*#__PURE__*/jsxRuntime.jsxs(framerMotion.motion.div, {
initial: {
opacity: 0,
y: 30
},
animate: {
opacity: 1,
y: 0
},
transition: {
duration: 0.8,
delay: 0.6
},
style: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: '20px',
width: '100%',
maxWidth: '800px'
},
children: [/*#__PURE__*/jsxRuntime.jsx("h2", {
style: {
color: 'white',
fontSize: '2rem',
margin: '0',
textShadow: '0 2px 4px rgba(0, 0, 0, 0.3)'
},
children: "Interactive Examples"
}), /*#__PURE__*/jsxRuntime.jsxs("div", {
style: {
display: 'flex',
gap: '20px',
flexWrap: 'wrap',
justifyContent: 'center',
alignItems: 'center'
},
children: [/*#__PURE__*/jsxRuntime.jsxs(LiquidGlassButton, {
variant: "primary",
onClick: handleClick,
style: {
minWidth: '150px'
},
children: ["Clicked: ", clickCount]
}), /*#__PURE__*/jsxRuntime.jsx(LiquidGlassButton, {
variant: "success",
onClick: handleAsyncClick,
disabled: isLoading,
style: {
minWidth: '150px'
},
children: isLoading ? 'Loading...' : 'Async Action'
}), /*#__PURE__*/jsxRuntime.jsx(LiquidGlassButton, {
variant: "secondary",
disabled: true,
style: {
minWidth: '150px'
},
children: "Disabled"
})]
})]
}), /*#__PURE__*/jsxRuntime.jsxs(framerMotion.motion.div, {
initial: {
opacity: 0,
y: 30
},
animate: {
opacity: 1,
y: 0
},
transition: {
duration: 0.8,
delay: 0.8
},
style: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: '20px',
width: '100%',
maxWidth: '800px'
},
children: [/*#__PURE__*/jsxRuntime.jsx("h2", {
style: {
color: 'white',
fontSize: '2rem',
margin: '0',
textShadow: '0 2px 4px rgba(0, 0, 0, 0.3)'
},
children: "Technical Features"
}), /*#__PURE__*/jsxRuntime.jsxs("div", {
style: {
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))',
gap: '20px',
width: '100%'
},
children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
style: {
background: 'rgba(255, 255, 255, 0.1)',
backdropFilter: 'blur(10px)',
borderRadius: '12px',
padding: '20px',
border: '1px solid rgba(255, 255, 255, 0.2)'
},
children: [/*#__PURE__*/jsxRuntime.jsx("h3", {
style: {
color: 'white',
margin: '0 0 10px 0'
},
children: "Glass Effects"
}), /*#__PURE__*/jsxRuntime.jsxs("ul", {
style: {
color: 'white',
margin: 0,
paddingLeft: '20px'
},
children: [/*#__PURE__*/jsxRuntime.jsx("li", {
children: "backdrop-filter: blur(20px)"
}), /*#__PURE__*/jsxRuntime.jsx("li", {
children: "rgba/hsla backgrounds"
}), /*#__PURE__*/jsxRuntime.jsx("li", {
children: "background-blend-mode"
}), /*#__PURE__*/jsxRuntime.jsx("li", {
children: "mix-blend-mode effects"
}), /*#__PURE__*/jsxRuntime.jsx("li", {
children: "Glass borders & shadows"
})]
})]
}), /*#__PURE__*/jsxRuntime.jsxs("div", {
style: {
background: 'rgba(255, 255, 255, 0.1)',
backdropFilter: 'blur(10px)',
borderRadius: '12px',
padding: '20px',
border: '1px solid rgba(255, 255, 255, 0.2)'
},
children: [/*#__PURE__*/jsxRuntime.jsx("h3", {
style: {
color: 'white',
margin: '0 0 10px 0'
},
children: "Animations"
}), /*#__PURE__*/jsxRuntime.jsxs("ul", {
style: {
color: 'white',
margin: 0,
paddingLeft: '20px'
},
children: [/*#__PURE__*/jsxRuntime.jsx("li", {
children: "Framer Motion integration"
}), /*#__PURE__*/jsxRuntime.jsx("li", {
children: "Parallax mouse tracking"
}), /*#__PURE__*/jsxRuntime.jsx("li", {
children: "Spring animations"
}), /*#__PURE__*/jsxRuntime.jsx("li", {
children: "Hover & tap effects"
}), /*#__PURE__*/jsxRuntime.jsx("li", {
children: "Ripple effects"
})]
})]
}), /*#__PURE__*/jsxRuntime.jsxs("div", {
style: {
background: 'rgba(255, 255, 255, 0.1)',
backdropFilter: 'blur(10px)',
borderRadius: '12px',
padding: '20px',
border: '1px solid rgba(255, 255, 255, 0.2)'
},
children: [/*#__PURE__*/jsxRuntime.jsx("h3", {
style: {
color: 'white',
margin: '0 0 10px 0'
},
children: "Customization"
}), /*#__PURE__*/jsxRuntime.jsxs("ul", {
style: {
color: 'white',
margin: 0,
paddingLeft: '20px'
},
children: [/*#__PURE__*/jsxRuntime.jsx("li", {
children: "Multiple variants"
}), /*#__PURE__*/jsxRuntime.jsx("li", {
children: "Size options"
}), /*#__PURE__*/jsxRuntime.jsx("li", {
children: "Disabled states"
}), /*#__PURE__*/jsxRuntime.jsx("li", {
children: "Custom styling"
}), /*#__PURE__*/jsxRuntime.jsx("li", {
children: "Accessible design"
})]
})]
})]
})]
})]
});
};
const LiquidGlassInput = /*#__PURE__*/React.forwardRef(({
type = "text",
placeholder = "Enter text...",
value = "",
onChange,
onFocus,
onBlur,
variant = "primary",
size = "medium",
disabled = false,
error = false,
success = false,
label = "",
helperText = "",
required = false,
className = "",
style = {},
...props
}, ref) => {
const inputRef = React.useRef(null);
const [isFocused, setIsFocused] = React.useState(false);
const [isFilled, setIsFilled] = React.useState(!!value);
const [mousePosition, setMousePosition] = React.useState({
x: 0,
y: 0
});
// Motion values for parallax effect
const mouseX = framerMotion.useMotionValue(0);
const mouseY = framerMotion.useMotionValue(0);
// Transform mouse position to subtle rotation and translation
const rotateX = framerMotion.useTransform(mouseY, [-100, 100], [5, -5]);
const rotateY = framerMotion.useTransform(mouseX, [-100, 100], [-5, 5]);
const translateZ = framerMotion.useTransform(mouseX, [-100, 100], [-5, 5]);
// Spring animations for smooth transitions
const springConfig = {
damping: 20,
stiffness: 200
};
const springRotateX = framerMotion.useSpring(rotateX, springConfig);
const springRotateY = framerMotion.useSpring(rotateY, springConfig);
const springTranslateZ = framerMotion.useSpring(translateZ, springConfig);
// Handle mouse movement for parallax effect
React.useEffect(() => {
const handleMouseMove = e => {
if (!inputRef.current || disabled) return;
const rect = inputRef.current.getBoundingClientRect();
const centerX = rect.left + rect.width / 2;
const centerY = rect.top + rect.height / 2;
const x = e.clientX - centerX;
const y = e.clientY - centerY;
mouseX.set(x);
mouseY.set(y);
setMousePosition({
x,
y
});
};
const handleMouseLeave = () => {
mouseX.set(0);
mouseY.set(0);
setMousePosition({
x: 0,
y: 0
});
};
const input = inputRef.current;
if (input) {
input.addEventListener('mousemove', handleMouseMove);
input.addEventListener('mouseleave', handleMouseLeave);
}
return () => {
if (input) {
input.removeEventListener('mousemove', handleMouseMove);
input.removeEventListener('mouseleave', handleMouseLeave);
}
};
}, [mouseX, mouseY, disabled]);
// Update filled state when value changes
React.useEffect(() => {
setIsFilled(!!value);
}, [value]);
// Variant styles
const variants = {
primary: {
background: `
linear-gradient(135deg,
rgba(255, 255, 255, 0.08) 0%,
rgba(255, 255, 255, 0.03) 50%,
rgba(255, 255, 255, 0.08) 100%
),
radial-gradient(
circle at 30% 30%,
rgba(255, 255, 255, 0.1) 0%,
transparent 50%
)
`,
borderColor: 'rgba(255, 255, 255, 0.3)',
focusBorderColor: 'rgba(0, 123, 255, 0.6)',
color: 'rgba(255, 255, 255, 0.9)',
placeholderColor: 'rgba(255, 255, 255, 0.5)',
shadowColor: 'rgba(0, 123, 255, 0.2)'
},
secondary: {
background: `
linear-gradient(135deg,
rgba(255, 255, 255, 0.06) 0%,
rgba(255, 255, 255, 0.02) 50%,
rgba(255, 255, 255, 0.06) 100%
),
radial-gradient(
circle at 70% 70%,
rgba(255, 255, 255, 0.08) 0%,
transparent 50%
)
`,
borderColor: 'rgba(255, 255, 255, 0.2)',
focusBorderColor: 'rgba(255, 255, 255, 0.5)',
color: 'rgba(255, 255, 255, 0.8)',
placeholderColor: 'rgba(255, 255, 255, 0.4)',
shadowColor: 'rgba(255, 255, 255, 0.15)'
},
success: {
background: `
linear-gradient(135deg,
rgba(40, 167, 69, 0.08) 0%,
rgba(40, 167, 69, 0.03) 50%,
rgba(40, 167, 69, 0.08) 100%
),
radial-gradient(
circle at 30% 30%,
rgba(40, 167, 69, 0.1) 0%,
transparent 50%
)
`,
borderColor: 'rgba(40, 167, 69, 0.3)',
focusBorderColor: 'rgba(40, 167, 69, 0.6)',
color: 'rgba(255, 255, 255, 0.9)',
placeholderColor: 'rgba(255, 255, 255, 0.5)',
shadowColor: 'rgba(40, 167, 69, 0.2)'
},
danger: {
background: `
linear-gradient(135deg,
rgba(220, 53, 69, 0.08) 0%,
rgba(220, 53, 69, 0.03) 50%,
rgba(220, 53, 69, 0.08) 100%
),
radial-gradient(
circle at 70% 70%,
rgba(220, 53, 69, 0.1) 0%,
transparent 50%
)
`,
borderColor: 'rgba(220, 53, 69, 0.3)',
focusBorderColor: 'rgba(220, 53, 69, 0.6)',
color: 'rgba(255, 255, 255, 0.9)',
placeholderColor: 'rgba(255, 255, 255, 0.5)',
shadowColor: 'rgba(220, 53, 69, 0.2)'
}
};
// Size styles
const sizes = {
small: {
padding: '8px 12px',
fontSize: '14px',
borderRadius: '8px',
minHeight: '36px',
labelFontSize: '12px'
},
medium: {
padding: '12px 16px',
fontSize: '16px',
borderRadius: '12px',
minHeight: '48px',
labelFontSize: '14px'
},
large: {
padding: '16px 20px',
fontSize: '18px',
borderRadius: '16px',
minHeight: '56px',
labelFontSize: '16px'
}
};
const currentVariant = variants[variant] || variants.primary;
const currentSize = sizes[size] || sizes.medium;
// Determine border color based on state
const getBorderColor = () => {
if (error) return 'rgba(220, 53, 69, 0.6)';
if (success) return 'rgba(40, 167, 69, 0.6)';
if (isFocused) return currentVariant.focusBorderColor;
return currentVariant.borderColor;
};
// Determine shadow color based on state
const getShadowColor = () => {
if (error) return 'rgba(220, 53, 69, 0.3)';
if (success) return 'rgba(40, 167, 69, 0.3)';
return currentVariant.shadowColor;
};
const handleFocus = e => {
setIsFocused(true);
onFocus?.(e);
};
const handleBlur = e => {
setIsFocused(false);
onBlur?.(e);
};
const handleChange = e => {
setIsFilled(!!e.target.value);
onChange?.(e);
};
// Custom increment/decrement for number input
const isNumber = type === 'number';
const isFullname = type === 'fullname';
const handleStep = step => {
if (disabled) return;
let newValue = value === '' || value === null ? 0 : Number(value);
newValue += step;
if (onChange) {
// Create a synthetic event to match React's onChange signature
const event = {
target: {
value: String(newValue)
}
};
onChange(event);
}
};
// For fullname, value should be { firstname, lastname }
const handleFullnameChange = (field, fieldValue) => {
if (onChange) {
const newValue = {
...value,
[field]: fieldValue
};
// Create a synthetic event to match React's onChange signature
const event = {
target: {
value: newValue
}
};
onChange(event);
}
};
return /*#__PURE__*/jsxRuntime.jsxs(framerMotion.motion.div, {
ref: inputRef,
className: `liquid-glass-input-container ${className}`,
style: {
position: 'relative',
width: '100%',
...style
},
animate: {
rotateX: disabled ? 0 : springRotateX,
rotateY: disabled ? 0 : springRotateY,
translateZ: disabled ? 0 : springTranslateZ
},
children: [label && /*#__PURE__*/jsxRuntime.jsxs(framerMotion.motion.label, {
style: {
display: 'block',
fontSize: currentSize.labelFontSize,
color: currentVariant.color,
marginBottom: '8px',
fontWeight: 500,
letterSpacing: '0.5px',
textShadow: '0 1px 2px rgba(0, 0, 0, 0.3)'
},
animate: {
y: isFocused || isFilled ? -2 : 0,
color: isFocused ? currentVariant.focusBorderColor : currentVariant.color
},
transition: {
duration: 0.2
},
children: [label, required && /*#__PURE__*/jsxRuntime.jsx("span", {
style: {
color: 'rgba(220, 53, 69, 0.8)'
},
children: " *"
})]
}), isFullname ? /*#__PURE__*/jsxRuntime.jsxs("div", {
style: {
display: 'flex',
gap: 12
},
children: [/*#__PURE__*/jsxRuntime.jsx(framerMotion.motion.input, {
type: "text",
value: value?.firstname || '',
onChange: e => handleFullnameChange('firstname', e.target.value),
placeholder: placeholder?.firstname || 'First name',
disabled: disabled,
required: required,
style: {
flex: 1,
padding: currentSize.padding,
fontSize: currentSize.fontSize,
borderRadius: currentSize.borderRadius,
background: currentVariant.background,
color: currentVariant.color,
border: `1px solid ${getBorderColor()}`,
outline: 'none',
fontWeight: 400,
letterSpacing: '0.3px',
textShadow: '0 1px 2px rgba(0, 0, 0, 0.3)',
boxShadow: '0 2px 8px rgba(0,0,0,0.08)',
marginBottom: 0
}
}), /*#__PURE__*/jsxRuntime.jsx(framerMotion.motion.input, {
type: "text",
value: value?.lastname || '',
onChange: e => handleFullnameChange('lastname', e.target.value),
placeholder: placeholder?.lastname || 'Last name',
disabled: disabled,
required: required,
style: {
flex: 1,
padding: currentSize.padding,
fontSize: currentSize.fontSize,
borderRadius: currentSize.borderRadius,
background: currentVariant.background,
color: currentVariant.color,
border: `1px solid ${getBorderColor()}`,
outline: 'none',
fontWeight: 400,
letterSpacing: '0.3px',
textShadow: '0 1px 2px rgba(0, 0, 0, 0.3)',
boxShadow: '0 2px 8px rgba(0,0,0,0.08)',
marginBottom: 0
}
})]
}) :
/*#__PURE__*/
// Input wrapper
jsxRuntime.jsxs(framerMotion.motion.div, {
style: {
position: 'relative',
borderRadius: currentSize.borderRadius,
background: currentVariant.background,
backdropFilter: 'blur(20px)',
WebkitBackdropFilter: 'blur(20px)',
backgroundBlendMode: 'overlay',
border: `1px solid ${getBorderColor()}`,
boxShadow: isFocused ? `
0 10px 30px rgba(0, 0, 0, 0.3),
0 0 15px ${getShadowColor()},
inset 0 1px 0 rgba(255, 255, 255, 0.1)
` : `
0 4px 16px rgba(0, 0, 0, 0.1),
inset 0 1px 0 rgba(255, 255, 255, 0.05)
`,
transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
transformStyle: 'preserve-3d',
perspective: '1000px'
},
whileHover: {
scale: disabled ? 1 : 1.01,
boxShadow: disabled ? undefined : `
0 8px 24px rgba(0, 0, 0, 0.2),
0 0 12px ${getShadowColor()},
inset 0 1px 0 rgba(255, 255, 255, 0.15)
`,
transition: {
duration: 0.2
}
},
animate: {
scale: isFocused ? 1.02 : 1,
boxShadow: isFocused ? `
0 15px 40px rgba(0, 0, 0, 0.4),
0 0 20px ${getShadowColor()},
inset 0 1px 0 rgba(255, 255, 255, 0.2)
` : undefined
},
transition: {
duration: 0.3
},
children: [/*#__PURE__*/jsxRuntime.jsx(framerMotion.motion.div, {
style: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
background: `
linear-gradient(
135deg,
rgba(255, 255, 255, 0.08) 0%,
transparent 50%,
rgba(255, 255, 255, 0.03) 100%
)
`,
borderRadius: 'inherit',
pointerEvents: 'none',
mixBlendMode: 'overlay'
},
animate: {
opacity: isFocused ? 0.8 : 0.4
},
transition: {
duration: 0.2
}
}), /*#__PURE__*/jsxRuntime.jsx(framerMotion.motion.div, {
style: {
position: 'absolute',
top: '2px',
left: '2px',
right: '2px',
bottom: '2px',
background: `
radial-gradient(
circle at 50% 0%,
rgba(255, 255, 255, 0.08) 0%,
transparent 70%
)
`,
borderRadius: 'inherit',
pointerEvents: 'none',
filter: 'blur(1px)'
},
animate: {
opacity: isFocused ? 0.4 : 0.2
},
transition: {
duration: 0.2
}
}), /*#__PURE__*/jsxRuntime.jsx(framerMotion.motion.input, {
ref: ref,
type: type,
value: value,
onChange: handleChange,
onFocus: handleFocus,
onBlur: handleBlur,
disabled: disabled,
placeholder: placeholder,
required: required,
style: {
position: 'relative',
zIndex: 1,
width: '100%',
padding: currentSize.padding,
fontSize: currentSize.fontSize,
minHeight: currentSize.minHeight,
color: currentVariant.color,
background: 'transparent',
border: 'none',
outline: 'none',
borderRadius: 'inherit',
fontWeight: 400,
letterSpacing: '0.3px',
textShadow: '0 1px 2px rgba(0, 0, 0, 0.3)',
cursor: disabled ? 'not-allowed' : 'text',
opacity: disabled ? 0.6 : 1,
// Add padding right for custom buttons
paddingRight: isNumber ? '48px' : currentSize.padding
},
animate: {
y: isFocused ? 1 : 0
},
transition: {
duration: 0.1
},
...props
}), isNumber && !disabled && /*#__PURE__*/jsxRuntime.jsxs("div", {
className: "custom-number-arrows",
style: {
position: 'absolute',
right: 8,
top: '50%',
transform: 'translateY(-50%)',
display: 'flex',
flexDirection: 'column',
gap: 4,
zIndex: 2
},
children: [/*#__PURE__*/jsxRuntime.jsx("button", {
type: "button",
tabIndex: -1,
"aria-label": "Increment",
onClick: () => handleStep(1),
style: {
width: 28,
height: 24,
borderRadius: 8,
border: 'none',
background: 'linear-gradient(135deg, rgba(255,255,255,0.18) 0%, rgba(255,255,255,0.08) 100%)',
boxShadow: '0 2px 8px rgba(0,0,0,0.10)',
color: '#fff',
fontWeight: 700,
fontSize: 18,
cursor: 'pointer',
marginBottom: 2,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
transition: 'background 0.2s',
outline: 'none',
borderTopLeftRadius: 8,
borderTopRightRadius: 8,
borderBottomLeftRadius: 0,
borderBottomRightRadius: 0,
padding: 0
},
children: "\u25B2"
}), /*#__PURE__*/jsxRuntime.jsx("button", {
type: "button",
tabIndex: -1,
"aria-label": "Decrement",
onClick: () => handleStep(-1),
style: {
width: 28,
height: 24,
borderRadius: 8,
border: 'none',
background: 'linear-gradient(135deg, rgba(255,255,255,0.18) 0%, rgba(255,255,255,0.08) 100%)',
boxShadow: '0 2px 8px rgba(0,0,0,0.10)',
color: '#fff',
fontWeight: 700,
fontSize: 18,
cursor: 'pointer',
marginTop: 2,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
transition: 'background 0.2s',
outline: 'none',
borderTopLeftRadius: 0,
borderTopRightRadius: 0,
borderBottomLeftRadius: 8,
borderBottomRightRadius: 8,
padding: 0
},
children: "\u25BC"
})]
}), /*#__PURE__*/jsxRuntime.jsx("style", {
children: `
.liquid-glass-input-container input::placeholder {
color: ${currentVariant.placeholderColor};
opacity: 1;
transition: color 0.3s ease;
}
.liquid-glass-input-container input:focus::placeholder {
color: ${currentVariant.placeholderColor}80;
}
.liquid-glass-input-container input:disabled::placeholder {
color: ${currentVariant.placeholderColor}40;
}
/* Hide default number input arrows for Webkit */
.liquid-glass-input-container input[type='number']::-webkit-inner-spin-button,
.liquid-glass-input-container input[type='number']::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
display: none;
}
/* Hide default number input arrows for Firefox */
.liquid-glass-input-container input[type='number'] {
-moz-appearance: textfield;
}
/* Show custom arrows only on hover/focus of wrapper */
.liquid-glass-input-container .custom-number-arrows {
opacity: 0;
pointer-events: none;
transition: opacity 0.2s;
}
.liquid-glass-input-container:hover .custom-number-arrows,
.liquid-glass-input-container:focus-within .custom-number-arrows {
opacity: 1;
pointer-events: auto;
}
`
}), error && /*#__PURE__*/jsxRuntime.jsx(framerMotion.motion.div, {
initial: {
scale: 0,
opacity: 0
},
animate: {
scale: 1,
opacity: 1
},
style: {
position: 'absolute',
right: '12px',
top: '50%',
transform: 'translateY(-50%)',
width: '8px',
height: '8px',
borderRadius: '50%',
background: 'rgba(220, 53, 69, 0.8)',
boxShadow: '0 0 8px rgba(220, 53, 69, 0.5)'
}
}), success && /*#__PURE__*/jsxRuntime.jsx(framerMotion.motion.div, {
initial: {
scale: 0,
opacity: 0
},
animate: {
scale: 1,
opacity: 1
},
style: {
position: 'absolute',
right: '12px',
top: '50%',
transform: 'translateY(-50%)',
width: '8px',
height: '8px',
borderRadius: '50%',
background: 'rgba(40, 167, 69, 0.8)',
boxShadow: '0 0 8px rgba(40, 167, 69, 0.5)'
}
}), isFocused && /*#__PURE__*/jsxRuntime.jsx(framerMotion.motion.div, {
initial: {
scale: 0.8,
opacity: 0
},
animate: {
scale: 1,
opacity: 1
},
style: {
position: 'absolute',
top: '-2px',
left: '-2px',
right: '-2px',
bottom: '-2px',
borderRadius: 'inherit',
background: `linear-gradient(45deg, ${getShadowColor()}, transparent)`,
zIndex: -1,
filter: 'blur(4px)'
},
transition: {
duration: 0.3
}
})]
}), helperText && /*#__PURE__*/jsxRuntime.jsx(framerMotion.motion.p, {
initial: {
opacity: 0,
y: -5
},
animate: {
opacity: 1,
y: 0
},
style: {
margin: '8px 0 0 0',
fontSize: '12px',
color: error ? 'rgba(220, 53, 69, 0.8)' : success ? 'rgba(40, 167, 69, 0.8)' : 'rgba(255, 255, 255, 0.6)',
textShadow: '0 1px 2px rgba(0, 0, 0, 0.3)',
fontWeight: 400
},
children: helperText
})]
});
});
LiquidGlassInput.displayName = 'LiquidGlassInput';
const InputDemo = () => {
const [formData, setFormData] = React.useState({
fullname: {
firstname: '',
lastname: ''
},
email: '',
password: '',
message: '',
search: ''
});
const [errors, setErrors] = React.useState({});
const [success, setSuccess] = React.useState({});
const [specialInputs, setSpecialInputs] = React.useState({
email: '',
password: '',
number: '',
phone: '',
fullname: {
firstname: '',
lastname: ''
}
});
const handleInputChange = (field, value) => {
setFormData(prev => ({
...prev,
[field]: value
}));
// Clear errors when user starts typing
if (errors[field]) {
setErrors(prev => ({
...prev,
[field]: ''
}));
}
// Validate email
if (field === 'email' && value) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(value)) {
setErrors(prev => ({
...prev,
email: 'Please enter a valid email address'
}));
} else {
setSuccess(prev => ({
...prev,
email: true
}));
}
}
// Validate password
if (field === 'password' && value) {
if (value.length < 6) {
setErrors(prev => ({
...prev,
password: 'Password must be at least 6 characters'
}));
} else {
setSuccess(prev => ({
...prev,
password: true
}));
}
}
};
const handleSpecialInputChange = (field, value) => {
setSpecialInputs(prev => ({
...prev,
[field]: value
}));
};
const handleSubmit = e => {
e.preventDefault();
console.log('Form submitted:', formData);
};
return /*#__PURE__*/jsxRuntime.jsxs("div", {
style: {
minHeight: '100vh',
background: `
linear-gradient(135deg, #667eea 0%, #764ba2 100%),
radial-gradient(circle at 20% 80%, #f093fb 0%, transparent 50%),
radial-gradient(circle at 80% 20%, #f5576c 0%, transparent 50%),
radial-gradient(circle at 40% 40%, #4facfe 0%, transparent 50%)
`,
backgroundBlendMode: 'overlay, screen, screen, screen',
padding: '40px 20px',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: '40px',
fontFamily: 'system-ui, -apple-system, sans-serif'
},
children: [/*#__PURE__*/jsxRuntime.jsxs(framerMotion.motion.div, {
initial: {
opacity: 0,
y: -50
},
animate: {
opacity: 1,
y: 0
},
transition: {
duration: 0.8
},
style: {
textAlign: 'center',
color: 'white',
marginBottom: '20px'
},
children: [/*#__PURE__*/jsxRuntime.jsx("h1", {
style: {
fontSize: '3rem',
fontWeight: 'bold',
margin: '0 0 10px 0',
textShadow: '0 4px 8px rgba(0, 0, 0, 0.3)',
background: 'linear-gradient(45deg, #fff, #f0f0f0)',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent',
backgroundClip: 'text'
},
children: "Liquid Glass Input"
}), /*#__PURE__*/jsxRuntime.jsx("p", {
style: {
fontSize: '1.2rem',
opacity: 0.9,
margin: '0',
textShadow: '0 2px 4px rgba(0, 0, 0, 0.3)'
},
children: "Advanced glass morphism input fields with validation"
})]
}), /*#__PURE__*/jsxRuntime.jsxs(framerMotion.motion.div, {
initial: {
opacity: 0,
y: 30
},
animate: {
opacity: 1,
y: 0
},
transition: {
duration: 0.8,
delay: 0.2
},
style: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: '20px',
width: '100%',
maxWidth: '800px'
},
children: [/*#__PURE__*/jsxRuntime.jsx("h2", {
style: {
color: 'white',
fontSize: '2rem',
margin: '0',
textShadow: '0 2px 4px rgba(0, 0, 0, 0.3)'
},
children: "Input Variants"
}), /*#__PURE__*/jsxRuntime.jsxs("div", {
style: {
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))',
gap: '20px',
width: '100%'
},
children: [/*#__PURE__*/jsxRuntime.jsx(LiquidGlassInput, {
variant: "primary",
label: "Primary Input",
placeholder: "Enter your text...",
value: formData.fullname.firstname,
onChange: e => handleInputChange('fullname', {
...formData.fullname,
firstname: e.target.value
})
}), /*#__PURE__*/jsxRuntime.jsx(LiquidGlassInput, {
variant: "secondary",
label: "Secondary Input",
placeholder: "Secondary style...",
value: formData.search,
onChange: e => handleInputChange('search', e.target.value)
}), /*#__PURE__*/jsxRuntime.jsx(LiquidGlassInput, {
variant: "success",
label: "Success Input",
placeholder: "Success state...",
value: "Valid input",
success: true
}), /*#__PURE__*/jsxRuntime.jsx(LiquidGlassInput, {
variant: "danger",
label: "Error Input",
placeholder: "Error state...",
value: "Invalid input",
error: true,
helperText: "This field has an error"
})]
})]
}), /*#__PURE__*/jsxRuntime.jsxs(framerMotion.motion.div, {
initial: {
opacity: 0,
y: 30
},
animate: {
opacity: 1,
y: 0
},
transition: {
duration: 0.8,
delay: 0.4
},
style: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: '20px',
width: '100%',
maxWidth: '800px'
},
children: [/*#__PURE__*/jsxRuntime.jsx("h2", {
style: {
color: 'white',
fontSize: '2rem',
margin: '0',
textShadow: '0 2px 4px rgba(0, 0, 0, 0.3)'
},
children: "Input Sizes"
}), /*#__PURE__*/jsxRuntime.jsxs("div", {
style: {
display: 'flex',
flexDirection: 'column',
gap: '20px',
width: '100%'
},
children: [/*#__PURE__*/jsxRuntime.jsx(LiquidGlassInput, {
size: "small",
label: "Small Input",
placeholder: "Small size...",
value: formData.search,
onChange: e => handleInputChange('search', e.target.value)
}), /*#__PURE__*/jsxRuntime.jsx(LiquidGlassInput, {
size: "medium",
label: "Medium Input (Default)",
placeholder: "Medium size...",
value: formData.fullname.firstname,
onChange: e => handleInputChange('fullname', {
...formData.fullname,
firstname: e.target.value
})
}), /*#__PURE__*/jsxRuntime.jsx(LiquidGlassInput, {
size: "large",
label: "Large Input",
placeholder: "Large size...",
value: formData.message,
onChange: e => handleInputChange('message', e.target.value)
})]
})]
}), /*#__PURE__*/jsxRuntime.jsxs(framerMotion.motion.div, {
initial: {
opacity: 0,
y: 30
},
animate: {
opacity: 1,
y: 0
},
transition: {
duration: 0.8,
delay: 0.6
},
style: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: '20px',
width: '100%',
maxWidth: '800px'
},
children: [/*#__PURE__*/jsxRuntime.jsx("h2", {
style: {
color: 'white',
fontSize: '2rem',
margin: '0',
textShadow: '0 2px 4px rgba(0, 0, 0, 0.3)'
},
children: "Interactive Form"
}), /*#__PURE__*/jsxRuntime.jsxs(framerMotion.motion.form, {
onSubmit: handleSubmit,
style: {
display: 'flex',
flexDirection: 'column',
gap: '20px',
width: '100%',
background: 'rgba(255, 255, 255, 0.1)',
backdropFilter: 'blur(20px)',
borderRadius: '20px',
padding: '30px',
border: '1px solid rgba(255, 255, 255, 0.2)'
},
whileHover: {
boxShadow: '0 20px 40px rgba(0, 0, 0, 0.3)'
},
transition: {
duration: 0.3
},
children: [/*#__PURE__*/jsxRuntime.jsx(LiquidGlassInput, {
type: "fullname",
label: "Full Name",
placeholder: {
firstname: 'First name',
lastname: 'Last name'
},
value: formData.fullname,
onChange: e => handleInputChange('fullname', e.target.value),
required: true,
helperText: "Please enter your complete name"
}), /*#__PURE__*/jsxRuntime.jsx(LiquidGlassInput, {
type: "email",
label: "Email Address",
placeholder: "Enter your email",
value: formData.email,
onChange: e => handleInputChange('email', e.target.value),
error: !!errors.email,
success: success.email,
helperText: errors.email || (success.email ? 'Email is valid!' : 'We\'ll never share your email'),
required: true
}), /*#__PURE__*/jsxRuntime.jsx(LiquidGlassInp