انتهى عصر Radix، استخدم هذا البديل... (Base UI)

BBetter Stack
컴퓨터/소프트웨어AI/미래기술

Transcript

00:00:00توقف عن استخدام مكونات Radix وانتقل إلى البديل الأفضل: Base UI؛ خاصة إذا كنت من عشاق Shadcn.
00:00:06هناك بالفعل خيار للتحول الآن. إذا لم تسمع بـ Base UI من قبل، فهي في الواقع
00:00:10من المبتكرين الأصليين لـ Radix وFloating UI وMaterial UI، وهي مكتبة واجهة مستخدم بدون واجهة رسومية (Headless UI).
00:00:15فهي توفر الوظائف وسهولة الاستخدام للمكونات، لكنك لا تزال المتحكم في التصميم،
00:00:20وهو أمر بالغ الأهمية حالياً، لأن النماذج اللغوية الكبيرة (LLMs) لا تزال غير بارعة في معالجة الحالات الاستثنائية واحتياجات سهولة الوصول.
00:00:24لكن ما وصفته للتو هو بالضبط ما تفعله Radix أيضاً.
00:00:30فلماذا تحتاج إلى واحدة جديدة؟ دعنا ننتقل مباشرة لأوضح لك الفروق الجوهرية.
00:00:35سأبدأ سريعاً بعرض وثائق Base UI لترى جميع
00:00:44المكونات المتاحة. على اليسار، يمكنك رؤية أن لديهم تقريباً كل ما قد
00:00:48تحتاجه في مكتبة مكوناتك، وحتى بعض المكونات المتقدمة مثل “Combo Box” المتوفر هنا،
00:00:52والذي لا يمكنك الحصول عليه في Radix. وستلاحظ وجود أمثلة رائعة لكل هذه المكونات حول كيفية
00:00:57تنفيذها وتنسيقها باستخدام أشياء مثل CSS Modules، كما يمكنك تحويل المثال لاستخدام Tailwind
00:01:01إذا أردت أيضاً. التوثيق ممتاز حقاً، لكننا لسنا هنا لمقارنة
00:01:06التوثيق، لذا دعونا ننتقل مباشرة إلى الفرق الرئيسي الأول، وهو الذي
00:01:10ربما ستسمعه كثيراً، وهو أن Base UI تخضع لصيانة نشطة، بينما Radix في حالة شبه متوقفة.
00:01:15إذا ألقينا نظرة على مخططات مساهمات GitHub، ستجد أن Base UI
00:01:20تنمو باستمرار، بينما يبدو أن Radix لا تتلقى سوى تعديلات عابرة بين الحين والآخر، ولكن الأمر يصبح
00:01:25أوضح عند النظر إلى طلبات السحب (PRs) والمشكلات التي تم إغلاقها في الشهر الأخير. يمكنك
00:01:29رؤية أن Base UI أغلقت 58 مشكلة ودمجت 154 طلب سحب، بينما لم تغلق Radix أي مشكلة أو تدمج أي طلب سحب.
00:01:36خلاصة ما حدث لـ Radix هي أن شركة WorkOS اشترت الشركة المطورة لـ Radix
00:01:42لكنها لم تستثمر فيها حقاً، فغادر فريق Radix بمعظمه، وانتهى بنا المطاف إلى هذا الوضع.
00:01:47حتى أن المبتكر المشارك لـ Radix قال إنه لن يستخدمها إلا كملاذ أخير، وهو الآن
00:01:53يعمل على Base UI. لذا فالأمر يتعلق بضمان أن تطبيقاتك وتوابعها مدعومة
00:01:58بصيانة مستمرة، ولن تسبب لك صداعاً مستقبلياً إذا واجهت ثغرة لن يتم إصلاحها.
00:02:02والأفضل من ذلك هو أن Base UI صُممت لتكون مشابهة جداً لـ Radix، لذا لن تكون الهجرة إليها صعبة.
00:02:08لكن هذا لا يعني عدم وجود تحسينات إضافية، ومن تحسيناتي المفضلة
00:02:13هي كيفية تعاملهم مع خاصية “as child” الموجودة في Radix. إذا لم تكن
00:02:17قد شاهدت هذا من قبل، فلدي هنا مكون “select” من Radix، وإذا أردت عرض مكون مخصص
00:02:22هنا كمشغل للقائمة (select trigger)، فبمجرد لفه بمكون “select trigger”، ستلاحظ
00:02:27ظهور مكون مغلف (wrapper) ومعه الزر الذي يحمل نص “Subscribe” - وبالمناسبة، يجب عليك النقر عليه.
00:02:31لكن إذا أردت فعلياً جعل زر الاشتراك نفسه يعمل كمشغل للقائمة،
00:02:36فكل ما علي فعله في Radix هو إضافة خاصية “as child” إلى المشغل، وهذا يخبر
00:02:41Radix بدمج جميع الخصائص والوظائف الخاصة بمشغل القائمة مع المكون الذي
00:02:46وضعناه كعنصر تابع له. يمكنك رؤية ذلك من خلال دمج اسم الكلاس (class name) هنا
00:02:50مع الزر، وفي هذه الحالة يتم استبداله. فإذا حذفت تلك الخاصية وحفظت،
00:02:55سترى أن لدينا الآن زراً يعمل وظيفياً كمشغل للقائمة الخاصة بي.
00:03:00هذه وظيفة مفيدة جداً، لكن الشكوى الشائعة كانت أنها لم تكن صريحة بما يكفي.
00:03:04وأعترف أنني أحياناً كنت أتغاضى عن هذه الخاصية عند مراجعة الكود بسرعة، وبالتالي كنت أخطئ في تحديد سبب المشكلة.
00:03:09لذا إذا انتقلنا لرؤية كيفية تنفيذ ذلك في Base UI، ستجد أنك تحصل على نفس الوظيفة تماماً.
00:03:13لدي زر هنا يعمل كمشغل للقائمة، ولكن إذا نظرت إلى الكود،
00:03:18ستجد أن Base UI تستخدم خاصية “render” بدلاً من “as child”.
00:03:24وفي خاصية “render”، تحدد المكون الذي تريد عرضه كمشغل للقائمة.
00:03:29هذا تغيير طفيف، لكني أرى أنه يجعل الأمر أكثر وضوحاً
00:03:34بشأن ما يحدث بالضبط؛ فهو يعرض هذا المكون حرفياً، فلا داعي للبحث
00:03:39عما إذا كان يستخدم المكون التابع أو البحث عن خاصية “as child”. كما قلت،
00:03:43هو تغيير بسيط ولكنه ممتاز في رأيي. وهذه ليست حتى القوة الكاملة لخاصية “render”.
00:03:48يمكننا أن نرى هنا عند بناء مفتاح تبديل (switch) أنه يمكننا تمرير دالة إلى
00:03:52خاصية “render”؛ مما يتيح لنا الوصول إلى خصائص حالة المكون الذي
00:03:56نقوم ببنائه، مثل “switch thumb” في هذه الحالة. ما يتيحه لنا هذا هو اختيار المكون
00:04:01الذي نريد تطبيق الخصائص الممررة عليه، ومن ثم يمكننا أيضاً إجراء منطق عرض مخصص
00:04:05أو منطق تنسيق مخصص بناءً على حالة المكون. ففي حالة
00:04:10مفتاح التبديل، يمكننا التحقق مما إذا كان مفعلاً أو معدلاً أو معطلاً أو ممتلئاً وغيرها الكثير.
00:04:14في هذه الحالة، نقوم ببساطة بالتحقق مما إذا كان مفعلاً أم لا، وبناءً على ذلك
00:04:18نعرض أيقونة مختلفة. هناك أيضاً “hook” يتيح لك دمج خاصية العرض (render prop)
00:04:22في مكوناتك المخصصة، لكننا ندخل هنا في تفاصيل متقدمة نوعاً ما. آمل
00:04:27أن تكون قد أدركت أن أي شيء مخصص تريد القيام به، يمكنك التعامل معه في Base UI.
00:04:31والآن بالعودة إلى مكون القائمة (select)، الفرق التالي هو أن Base UI تسمح لبعض
00:04:35المكونات بأن تكون مدفوعة بالبيانات (data-driven). نرى هذا في حالة مكون القائمة هنا؛
00:04:40ما لدي حالياً هو كود Radix select؛ لدينا مصفوفة تحتوي على الاسم والقيمة،
00:04:44ولإدراج القيم فعلياً في القائمة بالأسفل، كل ما نحتاجه هو عمل “map” على مصفوفة “apples”
00:04:49ثم عرض “select item” في Radix، وهذا سيضيف القيم بهذا الشكل.
00:04:54أما إذا انتقلنا لكيفية القيام بذلك في Base UI، ستجد الأمر مشابهاً جداً. لا نزال نملك
00:04:59المصفوفة بالأعلى مع الأسماء والقيم، وبالأسفل لا نزال نقوم بعمل “map” وعرض
00:05:03“select item”، ولكننا ندرجها أيضاً في مكان آخر، وهو “select root” هنا.
00:05:08نحن ندرج تلك المصفوفة، وهذا له تأثير طفيف وذكي يعني أن المكون أصبح الآن
00:05:13على دراية بالبيانات التي سيعرضها قبل العرض الفعلي، مما يعني وجود
00:05:17أداء أفضل قليلاً، خاصة عندما يتعلق الأمر بالعرض من جانب الخادم (SSR).
00:05:22لكن هناك شيء واحد أعتقد أنه يمكن تحسينه في هذا الصدد؛ حالياً أقوم بتمرير “apples” كخاصية “items”،
00:05:26وفي الأسفل أقوم أيضاً بعمل “map” على نفس المصفوفة، فنحن نستخدمها في مكانين.
00:05:32ما أعتقد أن عليهم فعله هو ما تفعله مكتبة React Aria، وهي مكتبة أخرى بدون واجهة رسومية. هنا
00:05:36يمكنك رؤية مصفوفة الحيوانات لدينا؛ نمررها هنا كـ “items”، ومن ثم
00:05:41بالنسبة للعناصر التابعة، كل ما نفعله هو استخدام دالة، وهذه الدالة ستعرف كل العناصر التي
00:05:45تم تمريرها في العنصر الأب؛ وبذلك لا نستخدم المصفوفة في مكانين، حيث يعمل
00:05:50العنصر الأب كمزود للبيانات. لذا فمن المؤكد أنه شيء لا يزال من الممكن تحسينه قليلاً.
00:05:55ولكن بالعودة إلى مكون القائمة، أريد أن أريك فرقاً آخر،
00:05:59ولكن هذا الفرق خاص بمكون القائمة تحديداً، على عكس خاصية “render” والنهج
00:06:03المدفوع بالبيانات اللذين ستجدهما في أغلب المكونات. هذا الفرق خاص بـ “select”
00:06:08وهو إمكانية الاختيار المتعدد (multi-select)، وهو أمر كان مفقوداً بشكل مؤلم في Radix.
00:06:13يمكنك أن ترى هنا في Base UI أن كل ما عليك فعله هو إضافة خاصية “multiple” إلى “select root”
00:06:17سواء كانت قيمتها true أو false، لتصبح القائمة ببساطة تدعم الاختيار المتعدد، فالأمر بهذه السهولة.
00:06:22ولنذهب أبعد من ذلك، تمتلك Base UI مكونات أخرى نفتقدها في Radix مثل “Combo Box”
00:06:27و”Auto Complete”، وهذه هي ميزة الصيانة النشطة التي تسمح بالاستجابة لطلبات المستخدمين.
00:06:33والآن هناك فرقان آخران أريد إطلاعكم عليهما بين Radix وBase UI،
00:06:38وسننتقل لاستخدام مكون “checkbox” لأنني مللت قليلاً من
00:06:41مكون القائمة ذاك. الفرق الأول الذي أريد توضيحه يتعلق بالتنسيق (styling)؛
00:06:45توفر Base UI خياراً آخر للتنسيق أراه رائعاً حقاً. يمكننا أن نرى هنا حالياً
00:06:50أنني أستخدم Tailwind. يمكنك استخدام جميع الطرق التقليدية مثل CSS العادي أو CSS Modules
00:06:55وغيرها الكثير، ولكن إذا كنت تستخدم شيئاً مثل Tailwind، فإن إحدى الطرق
00:06:59المعتادة لتنسيق مكون كهذا هي استخدام خصائص البيانات (data attributes) للحالة، فلدينا هنا “data-checked”،
00:07:04وإذا كان مفعلاً، فسنستخدم لون الخلفية الأساسي. تلاحظون أن لدينا سلسلة نصية طويلة جداً
00:07:08للتنسيق في Tailwind، وهو ما قد يصبح مشكلة أحياناً. لذا
00:07:13أحد الخيارات التي توفرها Base UI للمساعدة في ذلك هو إمكانية استخدام دالة
00:07:17كاسم للكلاس (className). هذا يمنحك وصولاً إلى حالة المكون؛ ففي حالة
00:07:22صندوق الاختيار هنا، أقوم بتطبيق الأنماط بناءً على ما إذا كانت الحالة مفعّلة أو معطلة.
00:07:26تلاحظون أنني أقوم بذلك عبر شرط بسيط، وأرى أحياناً أن هذه الطريقة أسهل للملاحظة السريعة
00:07:31عند مراجعة الكود لمعرفة مصدر أنماط التفعيل والتعطيل بالضبط،
00:07:35بدلاً من فحص سطر واحد طويل والبحث عن خصائص البيانات تلك. أعتقد
00:07:40أنها تكون أكثر فائدة إذا كنت تستخدم شيئاً مثل Vanilla CSS، كما أنها تعمل
00:07:45بشكل رائع مع مكتبة أخرى أحبها تسمى Tailwind Variants. يمكنكم رؤية
00:07:49أنني أقوم ببساطة بتمرير الحالة إلى دالة checkbox الخاصة بي، وفي الأعلى في متغير checkbox الخاص بـ Tailwind
00:07:53لدينا الأنماط الأساسية، ولكن لدينا أيضاً المتغيرات (variants). ويمكنكم رؤية أنني أقول ببساطة:
00:07:58إذا كان “checked” صحيحاً فطبق هذه الأنماط، وإذا كان “disabled” صحيحاً فطبق هذه الأنماط.
00:08:02وأعتقد أن هذا أحياناً يكون أوضح بكثير من استخدام خصائص البيانات، لكن الأمر يعود لرأيك
00:08:06وما ترتاح لاستخدامه. من الرائع حقاً أن توفر لنا Base UI كل هذه الخيارات. سأضيف أيضاً
00:08:11أن استخدام دالة كاسم للكلاس كان شيئاً أعجبني لأول مرة في مكتبة React Aria.
00:08:14لذا يبدو لي أن لدينا React Aria من جهة، والتي تتطلب منحنى تعلم حاداً،
00:08:19وRadix من جهة أخرى وهي بسيطة للغاية، بينما جاءت Base UI لتقف في المنتصف وتأخذ
00:08:23الميزات التي أحببتها في كلتيهما لتقدم لي المكتبة المثالية. كانت هذه جميع
00:08:28الفروق الجوهرية التي أردت تغطيتها في هذا الفيديو، ولكن لا يزال هناك الكثير؛ فـ Base UI توفر
00:08:33دعماً ممتازاً لـ React Hook Form وTanStack Form، وتدعم الرسوم المتحركة لجعل
00:08:38عملية تحريك مكوناتك سهلة وسلسة، بل وتضم ميزات مثل “input scrubbing”
00:08:42والحوارات المتداخلة (nested dialogues) وتفعيل القوائم عند التمرير بالماوس. وأنا متأكد أنهم سيستجيبون
00:08:47لأي طلب منطقي على GitHub لأن المكتبة نشطة. ومع ذلك، تجدر الإشارة إلى
00:08:52أنني ربما لن أتسرع في تحويل تطبيقي المبني على Radix إلى Base UI فوراً، فلا أعتقد
00:08:57أن Radix معطلة تماماً. لكن إذا كنت أبدأ مشروعاً جديداً، سأستخدم Base UI بالتأكيد الآن،
00:09:02وإذا كنت أحتاج لميزة مثل Combo Box أو Auto-complete، سأفكر أيضاً في تحويل تطبيقي. أخبروني
00:09:07برأيكم في Base UI في التعليقات، ولا تنسوا الاشتراك، وكما هو الحال دائماً
00:09:11أراكم في الفيديو القادم.

Key Takeaway

تعتبر Base UI التطور الطبيعي والمستقر لمكتبات الواجهة البرمجية بدون واجهة رسومية (Headless UI)، حيث تجمع بين بساطة Radix وميزات React Aria المتقدمة مع ضمان الاستمرارية البرمجية.

Highlights

تعد Base UI البديل الأقوى لمكتبة Radix، حيث تم تطويرها من قبل الفريق الأصلي المبتكر لـ Radix وMaterial UI.

تتفوق Base UI على Radix بكونها تخضع لصيانة نشطة ومستمرة من قبل المطورين، بينما تبدو Radix في حالة ركود تقني.

توفير مكونات برمجية متقدمة ومفتقدة في Radix مثل "Combo Box" وخاصية الاختيار المتعدد (Multi-select) في القوائم.

استبدال خاصية "as child" التقليدية بخاصية "render" الأكثر وضوحاً، مما يسهل تتبع الكود وفهم منطق عرض المكونات.

دعم النهج المدفوع بالبيانات (Data-driven) الذي يحسن الأداء، خاصة عند استخدام العرض من جانب الخادم (SSR).

مرونة عالية في التنسيق من خلال إمكانية استخدام الدوال كأسماء للكلاسات (className) مما يسهل التعامل مع مكتبات مثل Tailwind.

Timeline

مقدمة عن Base UI ولماذا يجب الاهتمام بها

يبدأ المتحدث بالدعوة للتوقف عن استخدام Radix والانتقال إلى Base UI، خاصة لمحبين مكتبة Shadcn الشهيرة. يوضح أن هذه المكتبة من ابتكار الفريق الأصلي لـ Radix وFloating UI، وهي مكتبة بدون واجهة رسومية (Headless UI). تكمن أهميتها في توفير الوظائف الأساسية مع ترك التحكم الكامل في التصميم للمطور، وهو أمر حيوي في عصر النماذج اللغوية الضخمة. يعرض الفيديو وثائق المكتبة الممتازة التي تدعم تقنيات CSS Modules وTailwind بشكل كامل. هذا القسم يضع الأساس لفهم لماذا أصبحت Base UI منافساً شرساً في سوق تطوير الواجهات.

الفجوة في الصيانة بين Radix وBase UI

يستعرض المتحدث الفرق الجوهري الأول وهو نشاط الصيانة على GitHub، حيث يظهر أن Radix متوقفة تقريباً بينما Base UI في نمو مستمر. يشرح السياق التاريخي حيث استحوذت شركة WorkOS على فريق Radix لكنها لم تستثمر في المشروع، مما أدى لمغادرة الفريق الأصلي. يشير المتحدث إلى إحصائيات دقيقة لطلبات السحب (PRs) والمشكلات المغلقة التي ترجح كفة Base UI بوضوح. يتم التأكيد على أن المبتكر المشارك لـ Radix نفسه يعمل الآن على Base UI. هذا الأمر يجعل الانتقال ضرورة لضمان دعم التطبيقات مستقبلاً وتجنب الثغرات غير المصلحة.

تحسين خاصية العرض: من "as child" إلى "render"

يتناول هذا الجزء تحسيناً تقنياً هاماً في كيفية تعامل Base UI مع المكونات التابعة باستخدام خاصية "render" بدلاً من "as child" المربكة في Radix. يوضح المتحدث كيف أن خاصية "render" تجعل الكود أكثر صراحة ووضوحاً عند مراجعته برمجياً. تسمح هذه الخاصية أيضاً بتمرير دالة للوصول إلى حالة المكون الداخلية مثل حالة التفعيل (checked) أو التعطيل (disabled). يتيح هذا النهج للمطورين بناء منطق عرض مخصص، مثل تغيير الأيقونات بناءً على حالة المكون بسهولة فائقة. يخلص القسم إلى أن Base UI توفر مرونة مطلقة لأي تخصيص متقدم يرغب فيه المطور.

المكونات المدفوعة بالبيانات وميزة الاختيار المتعدد

يسلط الضوء هنا على ميزة المكونات المدفوعة بالبيانات (Data-driven components) في Base UI، مع التركيز على مكون القائمة (Select). من خلال تمرير مصفوفة البيانات للعنصر الأب (Root)، يصبح المكون على دراية بالبيانات قبل العرض، مما يحسن أداء SSR. يقارن المتحدث هذا النهج بما تفعله مكتبة React Aria، مقترحاً بعض التحسينات المستقبلية لتقليل تكرار الكود. تبرز هنا ميزة الاختيار المتعدد (Multi-select) كإضافة جوهرية كانت مفقودة تماماً في مكتبة Radix الأصلية. كما يتم ذكر توفر مكونات إضافية مثل Combo Box وAuto Complete التي تلبي احتياجات المستخدمين الحالية.

خيارات التنسيق المتقدمة والخلاصة النهائية

يختتم الفيديو بمناقشة خيارات التنسيق المبتكرة، حيث تسمح Base UI باستخدام دالة لتعريف "className"، مما يسهل التعامل مع حالات المكون دون سلاسل نصية طويلة. يوضح المتحدث كيف تتكامل هذه الطريقة مع مكتبة Tailwind Variants لتنظيم الأنماط البرمجية بشكل أنيق وواضح. يصف المتحدث Base UI بأنها الحل الوسط المثالي بين بساطة Radix وتعقيد React Aria. رغم أنه لا ينصح بالتحويل الفوري للمشاريع القائمة والمستقرة، إلا أنه يحث بشدة على استخدامها في أي مشروع جديد. ينتهي الفيديو بتأكيد دعم المكتبة لتقنيات حديثة مثل TanStack Form والرسوم المتحركة السلسة.

Community Posts

View all posts