إدخال Apple لـ Liquid Glass UI في macOS Tahoe 26 وضع معياراً جديداً لتصميم الواجهة. الأخبار الجيدة؟ يمكنك الآن تنفيذ تأثيرات مشابهة في تطبيقات React الخاصة بك. يتناول هذا الدليل الشامل إنشاء مكونات Liquid Glass مستوحاة من Apple لتطبيقات الويب.
يمثل Liquid Glass أكثر تطور تصميم واجهة متطور من Apple منذ إدخال الشفافية في macOS. التأثير يجمع:
الشفافية الديناميكية التي تستجيب للمحتوى
انكسار الضوء في الوقت الفعلي ينشئ العمق
الرسوم المتحركة السائلة التي تشعر بالطبيعية والاستجابة
التكيف السياقي بناءً على تفاعل المستخدم
يعتمد تأثير Liquid Glass على عدة تقنيات رئيسية:
WebGL shaders للعرض في الوقت الفعلي
CSS backdrop-filter لتأثيرات الضبابية
SVG filters لمعالجة الضوء المتقدمة
تسريع GPU للرسوم المتحركة السلسة
أولاً، ثبت مكون liquid-glass-react:
npm install liquid-glass-react
# أو
yarn add liquid-glass-react
import React from 'react' ;
import { LiquidGlass } from 'liquid-glass-react' ;
import './App.css' ;
function App () {
return (
< div className = "app" >
< LiquidGlass
displacementScale = { 2.0 }
blurAmount = { 1.5 }
elasticity = { 0.7 }
className = "liquid-container"
>
< div className = "content" >
< h1 >مرحباً بك في Liquid Glass</ h1 >
< p >اختبر تصميم واجهة Apple الثوري</ p >
</ div >
</ LiquidGlass >
</ div >
);
}
.liquid-container {
width : 100 % ;
height : 100 vh ;
background : linear-gradient ( 135 deg ,
rgba ( 255 , 255 , 255 , 0.1 ) 0 % ,
rgba ( 255 , 255 , 255 , 0.05 ) 100 % );
backdrop-filter : blur ( 10 px ) saturate ( 180 % );
border : 1 px solid rgba ( 255 , 255 , 255 , 0.2 );
border-radius : 16 px ;
}
.content {
padding : 40 px ;
color : rgba ( 255 , 255 , 255 , 0.9 );
text-align : center ;
}
مقياس الإزاحة (0.0 - 5.0)
يتحكم في شدة تأثير التشويه السائل:
< LiquidGlass displacementScale = { 2.5 }>
{ /* القيم الأعلى تخلق تشويهاً أكثر دراماتيكية */ }
</ LiquidGlass >
كمية الضبابية (0.0 - 3.0)
تحدد شدة ضبابية الخلفية:
< LiquidGlass blurAmount = { 1.8 }>
{ /* يحاكي تأثير عمق المجال في macOS Tahoe */ }
</ LiquidGlass >
المرونة (0.0 - 1.0)
تضبط مدى سيولة ظهور الزجاج:
< LiquidGlass elasticity = { 0.9 }>
{ /* القيم الأعلى تشعر بأنها أكثر سيولة */ }
</ LiquidGlass >
نصف قطر الزاوية
< LiquidGlass cornerRadius = { 20 }>
{ /* يطابق عناصر الواجهة المدورة في macOS Tahoe */ }
</ LiquidGlass >
شدة الانحراف
< LiquidGlass aberrationIntensity = { 0.4 }>
{ /* ينشئ فصل لوني خفي للشعور المتميز */ }
</ LiquidGlass >
import React, { useState } from 'react' ;
import { LiquidGlass } from 'liquid-glass-react' ;
const MenuBar = () => {
const [ isActive , setIsActive ] = useState ( false );
return (
< LiquidGlass
displacementScale = { 1.2 }
blurAmount = { 2.0 }
elasticity = { 0.8 }
className = { `menu-bar ${ isActive ? 'active' : ''}` }
style = {{
position: 'fixed' ,
top: 0 ,
left: 0 ,
right: 0 ,
height: '32px' ,
background: 'rgba(255, 255, 255, 0.05)' ,
backdropFilter: 'blur(20px) saturate(180%)' ,
borderBottom: '1px solid rgba(255, 255, 255, 0.1)' ,
zIndex: 1000
}}
>
< div className = "menu-items" >
< span className = "menu-item" >ملف</ span >
< span className = "menu-item" >تحرير</ span >
< span className = "menu-item" >عرض</ span >
< span className = "menu-item" >نافذة</ span >
< span className = "menu-item" >مساعدة</ span >
</ div >
</ LiquidGlass >
);
};
const CompatibilityCard = ({ macModel , compatibility }) => {
const [ isHovered , setIsHovered ] = useState ( false );
return (
< LiquidGlass
displacementScale = {isHovered ? 3.0 : 2.0 }
blurAmount = {isHovered ? 2.0 : 1.5 }
elasticity = { 0.85 }
className = "compatibility-card"
onMouseEnter = {() => setIsHovered ( true )}
onMouseLeave = {() => setIsHovered ( false )}
style = {{
padding: '24px' ,
margin: '16px' ,
background: compatibility.isSupported
? 'rgba(52, 199, 89, 0.1)'
: 'rgba(255, 69, 58, 0.1)' ,
border: '1px solid rgba(255, 255, 255, 0.15)' ,
borderRadius: '16px' ,
transition: 'all 0.3s ease'
}}
>
< h3 >{macModel}</ h3 >
< p >{compatibility.features. join ( ', ' )}</ p >
< div className = "support-indicator" >
{compatibility.isSupported ? '✅ مدعوم بالكامل' : '⚠️ دعم محدود' }
</ div >
</ LiquidGlass >
);
};
تمكين تسريع الأجهزة:
.liquid-glass-container {
transform : translateZ ( 0 );
will-change : transform, opacity;
contain : layout style paint;
}
تحسين للهاتف المحمول:
const isMobile = window.innerWidth < 768 ;
< LiquidGlass
displacementScale = {isMobile ? 1.0 : 2.5 }
blurAmount = {isMobile ? 0.8 : 1.5 }
elasticity = {isMobile ? 0.5 : 0.8 }
>
تنظيف المكونات:
import { useEffect, useRef } from 'react' ;
const OptimizedLiquidGlass = ({ children , ... props }) => {
const containerRef = useRef ( null );
useEffect (() => {
const container = containerRef.current;
return () => {
// تنظيف سياقات WebGL ومستمعي الأحداث
if (container) {
const canvas = container. querySelector ( 'canvas' );
if (canvas) {
const gl = canvas. getContext ( 'webgl' ) || canvas. getContext ( 'webgl2' );
if (gl) {
gl. getExtension ( 'WEBGL_lose_context' )?. loseContext ();
}
}
}
};
}, []);
return (
< div ref = {containerRef}>
< LiquidGlass { ... props}>{children}</ LiquidGlass >
</ div >
);
};
const hasWebGLSupport = () => {
try {
const canvas = document. createElement ( 'canvas' );
return !! (
window.WebGLRenderingContext &&
(canvas. getContext ( 'webgl' ) || canvas. getContext ( 'webgl2' ))
);
} catch (e) {
return false ;
}
};
const hasBackdropFilterSupport = () => {
return CSS . supports ( 'backdrop-filter' , 'blur(1px)' );
};
const ConditionalLiquidGlass = ({ children , fallbackComponent , ... props }) => {
const supportsLiquidGlass = hasWebGLSupport () && hasBackdropFilterSupport ();
if ( ! supportsLiquidGlass) {
return fallbackComponent || (
< div className = "fallback-glass" >{children}</ div >
);
}
return < LiquidGlass { ... props}>{children}</ LiquidGlass >;
};
.fallback-glass {
background : rgba ( 255 , 255 , 255 , 0.1 );
border : 1 px solid rgba ( 255 , 255 , 255 , 0.2 );
border-radius : 16 px ;
backdrop-filter : blur ( 10 px );
}
/* إصلاحات خاصة بـ Safari */
@supports ( -webkit-backdrop-filter : blur ( 10 px )) {
.fallback-glass {
-webkit-backdrop-filter : blur ( 10 px );
}
}
// مكتبة مكونات الزجاج
const GlassButton = ({ variant = 'primary' , children , ... props }) => {
const variants = {
primary: {
displacementScale: 1.5 ,
blurAmount: 1.0 ,
background: 'rgba(0, 122, 255, 0.2)'
},
secondary: {
displacementScale: 1.2 ,
blurAmount: 0.8 ,
background: 'rgba(255, 255, 255, 0.1)'
},
danger: {
displacementScale: 1.8 ,
blurAmount: 1.2 ,
background: 'rgba(255, 69, 58, 0.2)'
}
};
return (
< LiquidGlass
{ ... variants[variant]}
elasticity = { 0.7 }
cornerRadius = { 8 }
className = { `glass-button glass-button--${ variant }` }
{ ... props}
>
< button className = "button-content" >{children}</ button >
</ LiquidGlass >
);
};
const GlassCard = ({ children , ... props }) => (
< LiquidGlass
displacementScale = { 2.0 }
blurAmount = { 1.5 }
elasticity = { 0.8 }
cornerRadius = { 16 }
className = "glass-card"
{ ... props}
>
< div className = "card-content" >{children}</ div >
</ LiquidGlass >
);
import { useSpring, animated } from '@react-spring/web' ;
const AnimatedLiquidGlass = ({ isActive , children }) => {
const springProps = useSpring ({
displacementScale: isActive ? 3.0 : 2.0 ,
blurAmount: isActive ? 2.0 : 1.5 ,
elasticity: isActive ? 0.9 : 0.7 ,
config: { tension: 200 , friction: 25 }
});
return (
< animated.div style = {springProps}>
< LiquidGlass
displacementScale = {springProps.displacementScale}
blurAmount = {springProps.blurAmount}
elasticity = {springProps.elasticity}
>
{children}
</ LiquidGlass >
</ animated.div >
);
};
const customShaderConfig = {
fragmentShader: `
precision mediump float;
uniform sampler2D u_texture;
uniform float u_time;
uniform vec2 u_resolution;
varying vec2 v_texCoord;
void main() {
vec2 uv = v_texCoord;
// إضافة تشويه معتمد على الوقت
uv.x += sin(uv.y * 10.0 + u_time) * 0.01;
uv.y += sin(uv.x * 10.0 + u_time * 0.5) * 0.01;
vec4 color = texture2D(u_texture, uv);
// تطبيق انكسار شبيه بالزجاج
float aberration = 0.005;
color.r = texture2D(u_texture, uv + vec2(aberration, 0.0)).r;
color.b = texture2D(u_texture, uv - vec2(aberration, 0.0)).b;
gl_FragColor = color;
}
`
};
< LiquidGlass
customShader = {customShaderConfig}
displacementScale = { 2.5 }
>
{children}
</ LiquidGlass >
const AccessibleLiquidGlass = ({ children , ... props }) => {
const prefersReducedMotion = window. matchMedia (
'(prefers-reduced-motion: reduce)'
).matches;
const accessibleProps = prefersReducedMotion
? {
displacementScale: 0.5 ,
elasticity: 0.3 ,
// حركة مقللة للمستخدمين الحساسين
}
: props;
return (
< LiquidGlass { ... accessibleProps}>
{children}
</ LiquidGlass >
);
};
< LiquidGlass
aria-label = "عنصر واجهة زجاج تفاعلي"
role = "presentation"
{ ... props}
>
< div aria-live = "polite" className = "sr-only" >
المحتوى محدث مع تأثير الزجاج السائل
</ div >
{children}
</ LiquidGlass >
const PerformanceMonitor = ({ children }) => {
useEffect (() => {
let frameCount = 0 ;
let lastTime = performance. now ();
const measureFPS = () => {
frameCount ++ ;
const currentTime = performance. now ();
if (currentTime - lastTime >= 1000 ) {
console. log ( `Liquid Glass FPS: ${ frameCount }` );
frameCount = 0 ;
lastTime = currentTime;
}
requestAnimationFrame (measureFPS);
};
measureFPS ();
}, []);
return children;
};
class LiquidGlassErrorBoundary extends React . Component {
constructor ( props ) {
super (props);
this .state = { hasError: false };
}
static getDerivedStateFromError ( error ) {
return { hasError: true };
}
componentDidCatch ( error , errorInfo ) {
console. error ( 'Liquid Glass Error:' , error, errorInfo);
}
render () {
if ( this .state.hasError) {
return (
< div className = "fallback-glass" >
{ this .props.fallback || this .props.children}
</ div >
);
}
return this .props.children;
}
}
// webpack.config.js تحسين لـ Liquid Glass
module . exports = {
optimization: {
splitChunks: {
chunks: 'all' ,
cacheGroups: {
liquidGlass: {
test: / [ \\ /] node_modules [ \\ /] liquid-glass-react [ \\ /] / ,
name: 'liquid-glass' ,
priority: 10 ,
reuseExistingChunk: true
}
}
}
}
};
// تحميل كسول للأداء
const LiquidGlass = React. lazy (() =>
import ( 'liquid-glass-react' ). then ( module => ({
default: module .LiquidGlass
}))
);
const LazyLiquidGlass = ({ children , ... props }) => (
< Suspense fallback = {< div className = "fallback-glass" >{children}</ div >}>
< LiquidGlass { ... props}>{children}</ LiquidGlass >
</ Suspense >
);
// واجهة TypeScript لتكامل نظام التصميم
interface LiquidGlassTheme {
colors : {
glassTint : string ;
borderColor : string ;
backgroundGradient : string [];
};
effects : {
displacementScale : number ;
blurAmount : number ;
elasticity : number ;
};
accessibility : {
reducedMotion : boolean ;
highContrast : boolean ;
};
}
const ThemedLiquidGlass : React . FC <{
theme : LiquidGlassTheme ;
children : React . ReactNode ;
}> = ({ theme , children }) => {
const effectProps = theme.accessibility.reducedMotion
? { ... theme.effects, displacementScale: 0.5 }
: theme.effects;
return (
< LiquidGlass
{ ... effectProps}
style = {{
background: `linear-gradient(${ theme . colors . backgroundGradient . join ( ', ' ) })` ,
border: `1px solid ${ theme . colors . borderColor }`
}}
>
{children}
</ LiquidGlass >
);
};
تنفيذ Liquid Glass UI من Apple في React يفتح إمكانيات مثيرة لإنشاء واجهات مستخدم متميزة وجذابة. مكون liquid-glass-react يوفر أساساً صلباً، لكن السحر الحقيقي يحدث عندما تجمعه مع مبادئ التصميم المدروسة وتحسين الأداء.
النقاط الرئيسية:
ابدأ بسيط مع التكوينات الأساسية قبل إضافة التعقيد
أعط الأولوية للأداء مع تسريع GPU المناسب والاحتياطيات
فكر في إمكانية الوصول للمستخدمين ذوي حساسية الحركة
اختبر بدقة عبر أجهزة ومتصفحات مختلفة
راقب الأداء لضمان تجارب مستخدم سلسة
مع استمرار macOS Tahoe في التأثير على اتجاهات تصميم الواجهة، إتقان تنفيذ Liquid Glass يضع تطبيقاتك في مقدمة تطوير واجهة المستخدم الحديثة. الجمع بين التطور التقني والأناقة البصرية يجعله أداة قوية لإنشاء تجارب مستخدم لا تُنسى.
الخطوات التالية:
جاهز لجلب Liquid Glass إلى مشروعك؟ فحص دليل التوافق للتأكد من أن متصفحاتك المستهدفة تدعم الميزات المتقدمة المطلوبة لعرض Liquid Glass الأمثل.