5 façons créatives d'utiliser Liquid Glass dans votre prochain projet React
Découvrez des applications pratiques des effets Liquid Glass dans les applications React, des composants de navigation aux tableaux de bord interactifs, avec des exemples de code complets et des conseils d'implémentation.
Les effets Liquid Glass ont révolutionné le design UI moderne, apportant l'esthétique élégante de macOS Tahoe aux applications web. Voici cinq façons pratiques et créatives d'intégrer liquid-glass-react dans vos projets, avec des exemples de code complets et des meilleures pratiques.
1. En-têtes de navigation interactifs
Transformez votre en-tête de navigation avec des effets Liquid Glass dynamiques qui répondent aux interactions utilisateur et à la position de défilement.
Implémentation
'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);
}, []);
// Paramètres dynamiques basés sur la position de défilement
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">
{['Accueil', 'À propos', 'Services', 'Contact'].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>
);
};
Fonctionnalités clés
- Effets réactifs au défilement : Les paramètres changent selon la position de défilement
- Adapté au mobile : Design responsive avec menu hamburger
- Optimisé pour la performance : Utilise ConditionalLiquidGlass pour replis automatiques
2. Boîtes de dialogue modales et superpositions
Créez des boîtes de dialogue modales époustouflantes qui ressemblent à des panneaux de verre flottants avec profondeur et interactivité.
Implémentation
'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'
}`}>
{/* Arrière-plan */}
<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">
{/* En-tête */}
<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>
{/* Contenu */}
<div className="space-y-4">
{children}
</div>
</div>
</ConditionalLiquidGlass>
</div>
);
};
// Exemple d'utilisation
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"
>
Ouvrir Modal Liquid Glass
</button>
<LiquidGlassModal
isOpen={isModalOpen}
onClose={() => setIsModalOpen(false)}
title="Modal Liquid Glass"
size="lg"
>
<p>Cette modal démontre des effets Liquid Glass avancés avec suivi de souris et paramètres dynamiques.</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">Fonctionnalité 1</h3>
<p className="text-sm text-muted-foreground">Suivi dynamique de souris</p>
</div>
<div className="p-4 bg-white/5 rounded-lg border border-white/10">
<h3 className="font-semibold mb-2">Fonctionnalité 2</h3>
<p className="text-sm text-muted-foreground">Design responsive</p>
</div>
</div>
</LiquidGlassModal>
</>
);
};
3. Cartes de tableau de bord et widgets
Améliorez la visualisation de données avec des composants de tableau de bord interactifs qui répondent à l'interaction utilisateur.
Implémentation
'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>
{/* Effet d'ondulation au 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>
);
};
// Composant grille de tableau de bord
const LiquidGlassDashboard = () => {
const cards = [
{
title: 'Revenus totaux',
value: '45 231€',
change: '+20.1%',
trend: 'up' as const,
icon: <DollarSign className="w-6 h-6" />,
color: 'green' as const
},
{
title: 'Utilisateurs actifs',
value: '2 341',
change: '+5.2%',
trend: 'up' as const,
icon: <Users className="w-6 h-6" />,
color: 'blue' as const
},
{
title: 'Taux de conversion',
value: '3.24%',
change: '-2.1%',
trend: 'down' as const,
icon: <TrendingUp className="w-6 h-6" />,
color: 'purple' as const
},
{
title: 'Performance',
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. Formulaires interactifs et champs de saisie
Transformez les interactions de formulaire avec des champs de saisie glass-morphiques qui fournissent un retour visuel.
Implémentation
'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>
);
};
// Exemple de formulaire de connexion
const LiquidGlassLoginForm = () => {
const [formData, setFormData] = useState({
name: '',
email: '',
password: ''
});
const [errors, setErrors] = useState<Record<string, string>>({});
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
// Logique de validation ici
console.log('Formulaire soumis :', 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">Bon retour</h2>
<form onSubmit={handleSubmit} className="space-y-6">
<LiquidGlassInput
type="text"
placeholder="Nom complet"
icon={<User className="w-5 h-5" />}
value={formData.name}
onChange={(value) => setFormData(prev => ({ ...prev, name: value }))}
error={errors.name}
/>
<LiquidGlassInput
type="email"
placeholder="Adresse e-mail"
icon={<Mail className="w-5 h-5" />}
value={formData.email}
onChange={(value) => setFormData(prev => ({ ...prev, email: value }))}
error={errors.email}
/>
<LiquidGlassInput
type="password"
placeholder="Mot de passe"
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"
>
Se connecter
</button>
</form>
</ConditionalLiquidGlass>
);
};
5. Cartes de présentation de fonctionnalités
Créez des présentations de fonctionnalités convaincantes avec des panneaux de verre interactifs qui mettent en valeur les capacités du produit.
Implémentation
'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">
{/* Icône et titre */}
<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>
{/* Description */}
<p className="text-muted-foreground mb-6 leading-relaxed">
{description}
</p>
{/* Liste de fonctionnalités */}
<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>
{/* Superposition d'effet de survol */}
<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>
);
};
// Grille de présentation de fonctionnalités
const LiquidGlassFeatureShowcase = () => {
const features = [
{
icon: <Zap className="w-8 h-8" />,
title: 'Ultra rapide',
description: 'Performance optimisée avec accélération WebGL et replis intelligents pour compatibilité maximale.',
features: [
'Animations fluides 60+ FPS',
'Accélération matérielle WebGL',
'Mise à l\'échelle automatique de performance',
'Rendu efficace en mémoire'
],
color: '#F59E0B',
delay: 0
},
{
icon: <Shield className="w-8 h-8" />,
title: 'Prêt pour production',
description: 'Composants testés en bataille avec gestion d\'erreur complète et fonctionnalités d\'accessibilité intégrées.',
features: [
'Support TypeScript',
'Conforme à l\'accessibilité',
'Protection limite d\'erreur',
'Couverture de tests étendue'
],
color: '#10B981',
delay: 200
},
{
icon: <Smartphone className="w-8 h-8" />,
title: 'Optimisé mobile',
description: 'Design responsive qui s\'adapte à toute taille d\'écran avec interactions tactiles conviviales.',
features: [
'Support gestes tactiles',
'Points de rupture responsive',
'Performance mobile ajustée',
'Amélioration progressive'
],
color: '#3B82F6',
delay: 400
},
{
icon: <Palette className="w-8 h-8" />,
title: 'Entièrement personnalisable',
description: 'Options de thème étendues et contrôles de paramètres pour intégration parfaite avec votre système de design.',
features: [
'Intégration système de thème',
'Schémas de couleurs personnalisés',
'Réglage fin des paramètres',
'Support variables CSS'
],
color: '#8B5CF6',
delay: 100
},
{
icon: <Code className="w-8 h-8" />,
title: 'Convivial développeur',
description: 'APIs propres, documentation complète et excellente expérience développeur prête à l\'emploi.',
features: [
'API composant intuitive',
'Documentation riche',
'Exemples de code inclus',
'Support communauté active'
],
color: '#EF4444',
delay: 300
},
{
icon: <Globe className="w-8 h-8" />,
title: 'Multi-plateforme',
description: 'Fonctionne parfaitement sur tous navigateurs et plateformes modernes avec résultats visuels cohérents.',
features: [
'Compatibilité navigateur',
'Cohérence plateforme',
'Stratégies de repli',
'Chargement progressif'
],
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">Pourquoi choisir Liquid Glass ?</h2>
<p className="text-xl text-muted-foreground max-w-3xl mx-auto">
Découvrez les fonctionnalités qui font de Liquid Glass le choix parfait pour les applications web modernes
</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>
);
};
Conseils d'implémentation et meilleures pratiques
Considérations de performance
- Utilisez ConditionalLiquidGlass : Toujours utiliser le composant wrapper pour replis automatiques
- Chargement paresseux : Implémenter le chargement paresseux pour composants non immédiatement visibles
- Optimisation de paramètres : Ajuster les paramètres selon les capacités d'appareil
- Gestion de mémoire : Nettoyer les ressources WebGL dans les fonctions de nettoyage useEffect
Directives d'accessibilité
- Respecter les préférences de mouvement : Honorer les paramètres
prefers-reduced-motion - Navigation clavier : S'assurer que tous éléments interactifs sont accessibles au clavier
- Gestion du focus : Fournir des indicateurs de focus clairs
- Support lecteur d'écran : Utiliser des labels ARIA et descriptions appropriés
Principes de design
- Subtil est mieux : Commencer avec des effets subtils et améliorer selon les retours utilisateur
- Thème cohérent : Maintenir des paramètres de verre cohérents dans votre application
- Approprié au contexte : Utiliser des effets plus forts pour sections héros, plus subtils pour composants UI
- Budget de performance : Surveiller l'impact performance et ajuster en conséquence
Conclusion
Les effets Liquid Glass ouvrent des possibilités passionnantes pour créer des interfaces web engageantes et modernes. Ces cinq cas d'usage démontrent la versatilité et la puissance de la bibliothèque liquid-glass-react, des en-têtes de navigation aux formulaires interactifs.
Rappelez-vous de toujours prioriser l'expérience utilisateur et la performance, en utilisant l'amélioration progressive pour s'assurer que vos applications fonctionnent magnifiquement sur tous appareils et navigateurs.
Ressources
Prêt à implémenter ces modèles dans votre projet ? Commencez avec le composant ConditionalLiquidGlass et améliorez progressivement votre interface utilisateur avec ces modèles éprouvés.
