5 Formas Creativas de Usar Liquid Glass en tu Próximo Proyecto React
Descubre aplicaciones prácticas de los efectos Liquid Glass en aplicaciones React, desde componentes de navegación hasta dashboards interactivos, con ejemplos de código completos y consejos de implementación.
Los efectos Liquid Glass han revolucionado el diseño de UI moderno, trayendo la estética elegante de macOS Tahoe a las aplicaciones web. Aquí tienes cinco formas prácticas y creativas de integrar liquid-glass-react en tus proyectos, completas con ejemplos de código y mejores prácticas.
1. Headers de Navegación Interactivos
Transforma tu header de navegación con efectos Liquid Glass dinámicos que responden a las interacciones del usuario y la posición del scroll.
Implementación
'use client';
import { ConditionalLiquidGlass } from '@/components/shared/conditional-liquid-glass';
import { useState, useEffect } from 'react';
const LiquidGlassNavigation = () => {
const [scrollY, setScrollY] = useState(0);
const [isMenuOpen, setIsMenuOpen] = useState(false);
useEffect(() => {
const handleScroll = () => setScrollY(window.scrollY);
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);
// Parámetros dinámicos basados en la posición del scroll
const dynamicParams = {
displacementScale: Math.min(3.0 + scrollY * 0.01, 5.0),
blurAmount: Math.min(1.0 + scrollY * 0.005, 2.5),
elasticity: 0.8 + (scrollY * 0.001),
aberrationIntensity: Math.min(scrollY * 0.002, 0.5)
};
return (
<ConditionalLiquidGlass
{...dynamicParams}
cornerRadius={0}
className="fixed top-0 left-0 right-0 z-50 transition-all duration-300"
style={{
background: `rgba(255, 255, 255, ${Math.min(scrollY * 0.001, 0.1)})`,
backdropFilter: `blur(${Math.min(scrollY * 0.1, 20)}px) saturate(180%)`,
borderBottom: '1px solid rgba(255, 255, 255, 0.2)',
}}
>
<nav className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between items-center h-16">
<div className="flex items-center space-x-8">
<div className="text-2xl font-bold">Logo</div>
<div className="hidden md:flex space-x-6">
{['Inicio', 'Acerca', 'Servicios', 'Contacto'].map((item) => (
<a
key={item}
href={`#${item.toLowerCase()}`}
className="text-foreground/80 hover:text-foreground transition-colors"
>
{item}
</a>
))}
</div>
</div>
<button
onClick={() => setIsMenuOpen(!isMenuOpen)}
className="md:hidden p-2 rounded-lg bg-white/10 backdrop-blur-sm"
>
<div className="w-6 h-6 flex flex-col justify-center space-y-1">
<div className={`h-0.5 w-full bg-current transition-transform ${
isMenuOpen ? 'rotate-45 translate-y-1' : ''
}`} />
<div className={`h-0.5 w-full bg-current transition-opacity ${
isMenuOpen ? 'opacity-0' : ''
}`} />
<div className={`h-0.5 w-full bg-current transition-transform ${
isMenuOpen ? '-rotate-45 -translate-y-1' : ''
}`} />
</div>
</button>
</div>
</nav>
</ConditionalLiquidGlass>
);
};
Características Clave
- Efectos responsivos al scroll: Los parámetros cambian según la posición del scroll
- Amigable para móviles: Diseño responsive con menú hamburguesa
- Optimizado para rendimiento: Usa ConditionalLiquidGlass para respaldos automáticos
2. Diálogos Modales y Overlays
Crea diálogos modales impresionantes que se sienten como paneles de vidrio flotantes con profundidad e interactividad.
Implementación
'use client';
import { ConditionalLiquidGlass } from '@/components/shared/conditional-liquid-glass';
import { X } from 'lucide-react';
import { useEffect, useState } from 'react';
interface LiquidGlassModalProps {
isOpen: boolean;
onClose: () => void;
title: string;
children: React.ReactNode;
size?: 'sm' | 'md' | 'lg' | 'xl';
}
const LiquidGlassModal = ({
isOpen,
onClose,
title,
children,
size = 'md'
}: LiquidGlassModalProps) => {
const [isVisible, setIsVisible] = useState(false);
const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });
useEffect(() => {
if (isOpen) {
setIsVisible(true);
document.body.style.overflow = 'hidden';
} else {
document.body.style.overflow = 'unset';
const timer = setTimeout(() => setIsVisible(false), 150);
return () => clearTimeout(timer);
}
}, [isOpen]);
const handleMouseMove = (e: React.MouseEvent) => {
const rect = e.currentTarget.getBoundingClientRect();
setMousePosition({
x: ((e.clientX - rect.left) / rect.width) * 2 - 1,
y: ((e.clientY - rect.top) / rect.height) * 2 - 1,
});
};
const sizeClasses = {
sm: 'max-w-md',
md: 'max-w-lg',
lg: 'max-w-2xl',
xl: 'max-w-4xl'
};
if (!isVisible) return null;
return (
<div className={`fixed inset-0 z-50 flex items-center justify-center p-4 transition-opacity duration-150 ${
isOpen ? 'opacity-100' : 'opacity-0'
}`}>
{/* Fondo */}
<div
className="absolute inset-0 bg-black/50 backdrop-blur-sm"
onClick={onClose}
/>
{/* Modal */}
<ConditionalLiquidGlass
displacementScale={2.5 + Math.abs(mousePosition.x) * 0.5}
blurAmount={1.8}
elasticity={0.7 + Math.abs(mousePosition.y) * 0.1}
cornerRadius={20}
globalMousePos={mousePosition}
className={`relative ${sizeClasses[size]} w-full transform transition-all duration-150 ${
isOpen ? 'scale-100 opacity-100' : 'scale-95 opacity-0'
}`}
style={{
background: 'rgba(255, 255, 255, 0.05)',
backdropFilter: 'blur(25px) saturate(200%)',
border: '1px solid rgba(255, 255, 255, 0.2)',
boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.5)',
}}
onMouseMove={handleMouseMove}
>
<div className="p-6">
{/* Header */}
<div className="flex items-center justify-between mb-6">
<h2 className="text-2xl font-bold">{title}</h2>
<button
onClick={onClose}
className="p-2 rounded-full hover:bg-white/10 transition-colors"
>
<X className="w-5 h-5" />
</button>
</div>
{/* Contenido */}
<div className="space-y-4">
{children}
</div>
</div>
</ConditionalLiquidGlass>
</div>
);
};
// Ejemplo de Uso
const ExampleModal = () => {
const [isModalOpen, setIsModalOpen] = useState(false);
return (
<>
<button
onClick={() => setIsModalOpen(true)}
className="px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
>
Abrir Modal Liquid Glass
</button>
<LiquidGlassModal
isOpen={isModalOpen}
onClose={() => setIsModalOpen(false)}
title="Modal Liquid Glass"
size="lg"
>
<p>Este modal demuestra efectos avanzados de Liquid Glass con seguimiento del mouse y parámetros dinámicos.</p>
<div className="grid grid-cols-2 gap-4 mt-4">
<div className="p-4 bg-white/5 rounded-lg border border-white/10">
<h3 className="font-semibold mb-2">Característica 1</h3>
<p className="text-sm text-muted-foreground">Seguimiento dinámico del mouse</p>
</div>
<div className="p-4 bg-white/5 rounded-lg border border-white/10">
<h3 className="font-semibold mb-2">Característica 2</h3>
<p className="text-sm text-muted-foreground">Diseño responsive</p>
</div>
</div>
</LiquidGlassModal>
</>
);
};
3. Tarjetas de Dashboard y Widgets
Mejora la visualización de datos con componentes de dashboard interactivos que responden a la interacción del usuario.
Implementación
'use client';
import { ConditionalLiquidGlass } from '@/components/shared/conditional-liquid-glass';
import { TrendingUp, Users, DollarSign, Activity } from 'lucide-react';
import { useState } from 'react';
interface DashboardCardProps {
title: string;
value: string;
change: string;
trend: 'up' | 'down';
icon: React.ReactNode;
color: 'blue' | 'green' | 'purple' | 'orange';
}
const DashboardCard = ({ title, value, change, trend, icon, color }: DashboardCardProps) => {
const [isHovered, setIsHovered] = useState(false);
const [clickPosition, setClickPosition] = useState({ x: 0, y: 0 });
const colorSchemes = {
blue: {
background: 'rgba(59, 130, 246, 0.05)',
border: 'rgba(59, 130, 246, 0.2)',
accent: 'text-blue-400'
},
green: {
background: 'rgba(34, 197, 94, 0.05)',
border: 'rgba(34, 197, 94, 0.2)',
accent: 'text-green-400'
},
purple: {
background: 'rgba(147, 51, 234, 0.05)',
border: 'rgba(147, 51, 234, 0.2)',
accent: 'text-purple-400'
},
orange: {
background: 'rgba(249, 115, 22, 0.05)',
border: 'rgba(249, 115, 22, 0.2)',
accent: 'text-orange-400'
}
};
const handleClick = (e: React.MouseEvent) => {
const rect = e.currentTarget.getBoundingClientRect();
setClickPosition({
x: e.clientX - rect.left,
y: e.clientY - rect.top,
});
};
return (
<ConditionalLiquidGlass
displacementScale={isHovered ? 3.5 : 2.0}
blurAmount={isHovered ? 2.0 : 1.3}
elasticity={isHovered ? 0.9 : 0.7}
cornerRadius={16}
className="cursor-pointer transition-all duration-300 hover:scale-105"
style={{
background: colorSchemes[color].background,
backdropFilter: 'blur(20px) saturate(150%)',
border: `1px solid ${colorSchemes[color].border}`,
}}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
onClick={handleClick}
>
<div className="p-6">
<div className="flex items-center justify-between mb-4">
<div className={`p-3 rounded-full bg-white/10 ${colorSchemes[color].accent}`}>
{icon}
</div>
<div className={`text-sm font-medium ${
trend === 'up' ? 'text-green-400' : 'text-red-400'
}`}>
{trend === 'up' ? '↗' : '↘'} {change}
</div>
</div>
<h3 className="text-lg font-medium text-muted-foreground mb-2">{title}</h3>
<p className="text-3xl font-bold">{value}</p>
{/* Efecto de ondas al hacer clic */}
{clickPosition.x !== 0 && (
<div
className="absolute pointer-events-none"
style={{
left: clickPosition.x,
top: clickPosition.y,
transform: 'translate(-50%, -50%)',
}}
>
<div className="w-0 h-0 bg-white/20 rounded-full animate-ping"
style={{ animation: 'ping 0.6s cubic-bezier(0, 0, 0.2, 1) once' }} />
</div>
)}
</div>
</ConditionalLiquidGlass>
);
};
// Componente de Grid del Dashboard
const LiquidGlassDashboard = () => {
const cards = [
{
title: 'Ingresos Totales',
value: '$45,231',
change: '+20.1%',
trend: 'up' as const,
icon: <DollarSign className="w-6 h-6" />,
color: 'green' as const
},
{
title: 'Usuarios Activos',
value: '2,341',
change: '+5.2%',
trend: 'up' as const,
icon: <Users className="w-6 h-6" />,
color: 'blue' as const
},
{
title: 'Tasa de Conversión',
value: '3.24%',
change: '-2.1%',
trend: 'down' as const,
icon: <TrendingUp className="w-6 h-6" />,
color: 'purple' as const
},
{
title: 'Rendimiento',
value: '98.5%',
change: '+1.3%',
trend: 'up' as const,
icon: <Activity className="w-6 h-6" />,
color: 'orange' as const
}
];
return (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
{cards.map((card, index) => (
<DashboardCard key={index} {...card} />
))}
</div>
);
};
4. Formularios Interactivos y Campos de Entrada
Transforma las interacciones de formularios con campos de entrada glass-morphic que proporcionan retroalimentación visual.
Implementación
'use client';
import { ConditionalLiquidGlass } from '@/components/shared/conditional-liquid-glass';
import { Eye, EyeOff, Mail, Lock, User } from 'lucide-react';
import { useState } from 'react';
interface LiquidGlassInputProps {
type: string;
placeholder: string;
icon: React.ReactNode;
value: string;
onChange: (value: string) => void;
error?: string;
}
const LiquidGlassInput = ({
type,
placeholder,
icon,
value,
onChange,
error
}: LiquidGlassInputProps) => {
const [isFocused, setIsFocused] = useState(false);
const [showPassword, setShowPassword] = useState(false);
const [isHovered, setIsHovered] = useState(false);
const inputType = type === 'password' && showPassword ? 'text' : type;
return (
<div className="space-y-2">
<ConditionalLiquidGlass
displacementScale={isFocused ? 3.0 : isHovered ? 2.5 : 2.0}
blurAmount={isFocused ? 1.8 : 1.2}
elasticity={isFocused ? 0.8 : 0.6}
cornerRadius={12}
style={{
background: isFocused
? 'rgba(255, 255, 255, 0.08)'
: 'rgba(255, 255, 255, 0.03)',
backdropFilter: 'blur(16px) saturate(150%)',
border: `1px solid ${
error
? 'rgba(239, 68, 68, 0.5)'
: isFocused
? 'rgba(59, 130, 246, 0.5)'
: 'rgba(255, 255, 255, 0.1)'
}`,
}}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
>
<div className="flex items-center p-4 space-x-3">
<div className={`transition-colors ${
isFocused ? 'text-blue-400' : 'text-muted-foreground'
}`}>
{icon}
</div>
<input
type={inputType}
placeholder={placeholder}
value={value}
onChange={(e) => onChange(e.target.value)}
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
className="flex-1 bg-transparent border-none outline-none text-foreground placeholder-muted-foreground"
/>
{type === 'password' && (
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="text-muted-foreground hover:text-foreground transition-colors"
>
{showPassword ? <EyeOff className="w-5 h-5" /> : <Eye className="w-5 h-5" />}
</button>
)}
</div>
</ConditionalLiquidGlass>
{error && (
<p className="text-sm text-red-400 ml-4">{error}</p>
)}
</div>
);
};
// Ejemplo de Formulario de Login
const LiquidGlassLoginForm = () => {
const [formData, setFormData] = useState({
name: '',
email: '',
password: ''
});
const [errors, setErrors] = useState<Record<string, string>>({});
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
// Lógica de validación aquí
console.log('Formulario enviado:', formData);
};
return (
<ConditionalLiquidGlass
displacementScale={1.8}
blurAmount={1.5}
elasticity={0.7}
cornerRadius={20}
style={{
background: 'rgba(255, 255, 255, 0.05)',
backdropFilter: 'blur(25px) saturate(180%)',
border: '1px solid rgba(255, 255, 255, 0.1)',
}}
className="max-w-md mx-auto p-8"
>
<h2 className="text-3xl font-bold text-center mb-8">Bienvenido de Vuelta</h2>
<form onSubmit={handleSubmit} className="space-y-6">
<LiquidGlassInput
type="text"
placeholder="Nombre Completo"
icon={<User className="w-5 h-5" />}
value={formData.name}
onChange={(value) => setFormData(prev => ({ ...prev, name: value }))}
error={errors.name}
/>
<LiquidGlassInput
type="email"
placeholder="Dirección de Email"
icon={<Mail className="w-5 h-5" />}
value={formData.email}
onChange={(value) => setFormData(prev => ({ ...prev, email: value }))}
error={errors.email}
/>
<LiquidGlassInput
type="password"
placeholder="Contraseña"
icon={<Lock className="w-5 h-5" />}
value={formData.password}
onChange={(value) => setFormData(prev => ({ ...prev, password: value }))}
error={errors.password}
/>
<button
type="submit"
className="w-full py-4 mt-6 bg-gradient-to-r from-blue-500 to-purple-600 text-white font-semibold rounded-xl hover:from-blue-600 hover:to-purple-700 transition-all duration-200 transform hover:scale-105"
>
Iniciar Sesión
</button>
</form>
</ConditionalLiquidGlass>
);
};
5. Tarjetas de Presentación de Características
Crea presentaciones convincentes de características con paneles de vidrio interactivos que destacan las capacidades del producto.
Implementación
'use client';
import { ConditionalLiquidGlass } from '@/components/shared/conditional-liquid-glass';
import { Zap, Shield, Smartphone, Palette, Code, Globe } from 'lucide-react';
import { useState } from 'react';
interface FeatureCardProps {
icon: React.ReactNode;
title: string;
description: string;
features: string[];
color: string;
delay: number;
}
const FeatureCard = ({ icon, title, description, features, color, delay }: FeatureCardProps) => {
const [isHovered, setIsHovered] = useState(false);
const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });
const handleMouseMove = (e: React.MouseEvent) => {
const rect = e.currentTarget.getBoundingClientRect();
setMousePosition({
x: ((e.clientX - rect.left) / rect.width - 0.5) * 2,
y: ((e.clientY - rect.top) / rect.height - 0.5) * 2,
});
};
return (
<ConditionalLiquidGlass
displacementScale={isHovered ? 4.0 + Math.abs(mousePosition.x) : 2.5}
blurAmount={isHovered ? 2.2 : 1.4}
elasticity={0.7 + Math.abs(mousePosition.y) * 0.1}
cornerRadius={20}
globalMousePos={mousePosition}
className={`group cursor-pointer transition-all duration-500 hover:scale-105 transform`}
style={{
background: `linear-gradient(135deg, ${color}15 0%, ${color}05 100%)`,
backdropFilter: 'blur(20px) saturate(150%)',
border: `1px solid ${color}30`,
animationDelay: `${delay}ms`,
}}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
onMouseMove={handleMouseMove}
>
<div className="p-8 h-full">
{/* Icono y Título */}
<div className="flex items-center space-x-4 mb-6">
<div
className="p-4 rounded-2xl transition-all duration-300 group-hover:scale-110"
style={{
background: `${color}20`,
color: color,
}}
>
{icon}
</div>
<h3 className="text-2xl font-bold">{title}</h3>
</div>
{/* Descripción */}
<p className="text-muted-foreground mb-6 leading-relaxed">
{description}
</p>
{/* Lista de Características */}
<ul className="space-y-3">
{features.map((feature, index) => (
<li
key={index}
className="flex items-center space-x-3 text-sm opacity-80 group-hover:opacity-100 transition-opacity"
>
<div
className="w-2 h-2 rounded-full"
style={{ backgroundColor: color }}
/>
<span>{feature}</span>
</li>
))}
</ul>
{/* Overlay de Efecto Hover */}
<div
className="absolute inset-0 rounded-[20px] opacity-0 group-hover:opacity-100 transition-opacity duration-300 pointer-events-none"
style={{
background: `radial-gradient(circle at ${(mousePosition.x + 1) * 50}% ${(mousePosition.y + 1) * 50}%, ${color}10 0%, transparent 70%)`,
}}
/>
</div>
</ConditionalLiquidGlass>
);
};
// Grid de Presentación de Características
const LiquidGlassFeatureShowcase = () => {
const features = [
{
icon: <Zap className="w-8 h-8" />,
title: 'Súper Rápido',
description: 'Rendimiento optimizado con aceleración WebGL y respaldos inteligentes para máxima compatibilidad.',
features: [
'Animaciones fluidas a 60+ FPS',
'Aceleración por hardware WebGL',
'Escalado automático de rendimiento',
'Renderizado eficiente en memoria'
],
color: '#F59E0B',
delay: 0
},
{
icon: <Shield className="w-8 h-8" />,
title: 'Listo para Producción',
description: 'Componentes probados en batalla con manejo integral de errores y características de accesibilidad integradas.',
features: [
'Soporte TypeScript',
'Compatible con accesibilidad',
'Protección de límites de error',
'Cobertura extensiva de pruebas'
],
color: '#10B981',
delay: 200
},
{
icon: <Smartphone className="w-8 h-8" />,
title: 'Optimizado para Móvil',
description: 'Diseño responsive que se adapta a cualquier tamaño de pantalla con interacciones amigables al tacto.',
features: [
'Soporte de gestos táctiles',
'Breakpoints responsive',
'Rendimiento ajustado para móvil',
'Mejora progresiva'
],
color: '#3B82F6',
delay: 400
},
{
icon: <Palette className="w-8 h-8" />,
title: 'Totalmente Personalizable',
description: 'Opciones extensivas de temas y controles de parámetros para integración perfecta con tu sistema de diseño.',
features: [
'Integración del sistema de temas',
'Esquemas de colores personalizados',
'Ajuste fino de parámetros',
'Soporte de variables CSS'
],
color: '#8B5CF6',
delay: 100
},
{
icon: <Code className="w-8 h-8" />,
title: 'Amigable para Desarrolladores',
description: 'APIs limpias, documentación completa y excelente experiencia de desarrollador desde el primer momento.',
features: [
'API de componentes intuitiva',
'Documentación rica',
'Ejemplos de código incluidos',
'Soporte activo de la comunidad'
],
color: '#EF4444',
delay: 300
},
{
icon: <Globe className="w-8 h-8" />,
title: 'Multiplataforma',
description: 'Funciona sin problemas en todos los navegadores y plataformas modernas con resultados visuales consistentes.',
features: [
'Compatibilidad de navegadores',
'Consistencia de plataforma',
'Estrategias de respaldo',
'Carga progresiva'
],
color: '#06B6D4',
delay: 500
}
];
return (
<div className="max-w-7xl mx-auto px-4 py-16">
<div className="text-center mb-16">
<h2 className="text-4xl font-bold mb-4">¿Por Qué Elegir Liquid Glass?</h2>
<p className="text-xl text-muted-foreground max-w-3xl mx-auto">
Descubre las características que hacen de Liquid Glass la elección perfecta para aplicaciones web modernas
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{features.map((feature, index) => (
<FeatureCard key={index} {...feature} />
))}
</div>
</div>
);
};
Consejos de Implementación y Mejores Prácticas
Consideraciones de Rendimiento
- Usa ConditionalLiquidGlass: Siempre usa el componente wrapper para respaldos automáticos
- Carga Perezosa: Implementa carga perezosa para componentes que no son inmediatamente visibles
- Optimización de Parámetros: Ajusta parámetros basándose en las capacidades del dispositivo
- Gestión de Memoria: Limpia recursos WebGL en funciones de limpieza useEffect
Pautas de Accesibilidad
- Respeta las Preferencias de Movimiento: Honra las configuraciones de
prefers-reduced-motion - Navegación por Teclado: Asegura que todos los elementos interactivos sean accesibles por teclado
- Gestión de Foco: Proporciona indicadores de foco claros
- Soporte de Lectores de Pantalla: Usa etiquetas ARIA apropiadas y descripciones
Principios de Diseño
- Sutil es Mejor: Comienza con efectos sutiles y mejora basándote en retroalimentación del usuario
- Temas Consistentes: Mantén parámetros de vidrio consistentes en toda tu aplicación
- Apropiado al Contexto: Usa efectos más fuertes para secciones hero, más sutiles para componentes UI
- Presupuesto de Rendimiento: Monitorea el impacto en el rendimiento y ajusta en consecuencia
Conclusión
Los efectos Liquid Glass abren posibilidades emocionantes para crear interfaces web atractivas y modernas. Estos cinco casos de uso demuestran la versatilidad y poder de la biblioteca liquid-glass-react, desde headers de navegación hasta formularios interactivos.
Recuerda siempre priorizar la experiencia del usuario y el rendimiento, usando mejora progresiva para asegurar que tus aplicaciones funcionen hermosamente en todos los dispositivos y navegadores.
Recursos
¿Listo para implementar estos patrones en tu proyecto? Comienza con el componente ConditionalLiquidGlass y mejora progresivamente tu interfaz de usuario con estos patrones probados.
