لا يفشل نظام التصميم بإعلان. يفشل حين يحتاج مطوّر إلى زر مختلف قليلًا، فيجد أن الزر المشترك لا يستطيع تلبية ذلك، فيكتب زرًا محليًا بدلًا منه. وبعد ستة أشهر يصبح هناك أربعة عشر زرًا، والمكتبة متقادمة، ويقترح أحدهم إعادة الكتابة.
التشخيص المعتاد أن الفريق افتقر إلى الانضباط. والحقيقة في الغالب أن النظام لم يكن جديرًا بالثقة: لم يغطِّ الحالات الواقعية، أو كان استخدامه أصعب من كتابة CSS، أو تغيّر من تحت الناس دون إنذار. وتلك مشكلات تصميم، ويمكن إصلاحها.
الرموز هي العقد، لا لوحة الألوان
أشيع الأخطاء رموز تسمّي المظهر. فـ --blue-500 يخبرك كيف تبدو القيمة اليوم ولا يقول شيئًا عن وقت استخدامها، فما إن تتغير الهوية أو يصل وضع داكن حتى يحتاج كل استخدام إلى مراجعة.
ينبغي أن تسمّي الرموز القصد وأن تُحلّ إلى القيم الأولية في مكان واحد. وهذا يمنحك طبقة لتغيير السمة دون لمس مكوّن واحد.
:root {
/* Primitives — raw values, never referenced by components. */
--blue-500: #3f6bff;
--grey-950: #0b0b0d;
--grey-100: #ece8df;
/* Semantic tokens — what components actually use. */
--surface-page: var(--grey-950);
--surface-raised: #101014;
--text-primary: var(--grey-100);
--text-secondary: #8b8b84;
--action-primary: var(--blue-500);
--border-hairline: #23232c;
}
/* Re-theming touches this block and nothing else. */
[data-theme='light'] {
--surface-page: #f7f6f2;
--surface-raised: #ffffff;
--text-primary: #17171c;
--text-secondary: #63625b;
--action-primary: #2f57f0;
--border-hairline: #e4e2da;
}القاعدة التي تجعل هذا يصمد: لا يجوز لأي مكوّن أن يشير إلى قيمة أولية. إذا احتاج مكوّن إلى لون ليس له رمز دلالي، فهذه إشارة إلى أن النظام ينقصه مفهوم — وهذا حديث من خمس دقائق، وليس سببًا لكتابة قيمة hex مباشرة في الشيفرة.
سمِّ المكوّنات باسم وظيفتها لا مظهرها
مكوّن اسمه BlueCard يصبح متقادمًا يوم يحتاج أحدهم إلى بطاقة رمادية. أما مكوّن اسمه ProjectCard فيصمد أمام إعادة بناء الهوية. والاختبار هو: هل سيبقى الاسم صحيحًا لو تغيّر التصميم كليًا؟ إن لم يكن، فهو يصف الطبقة الخطأ.
وينطبق الأمر نفسه على المتغيرات. variant="primary" يصف التسلسل الهرمي وسيعيش بعد تغيير لوحة الألوان. أما variant="blue" فيصف الصبغة ولن يعيش.
صمّم واجهة البرمجة قبل البكسلات
توقيع الخصائص (props) هو الجزء الذي يعيش معه الناس. وهناك نمطا إخفاق يتكرران:
- شديد الصرامة — يغطي المكوّن 80% من الحالات ولا يوفّر مخرج طوارئ، فتُنسخ الـ 20% المتبقية وتُعدَّل. وكل نسخة هي تناقض مستقبلي.
- شديد التساهل — يقبل المكوّن تجاوزات عشوائية لـ
classNameوstyle، فلا يفرض شيئًا ويصبح النظام ديكوريًا.
الوسط هو مجموعة صغيرة من المتغيرات المختارة بعناية، مع التركيب عبر children للأجزاء المخصصة فعلًا. وحيث يلزم مخرج طوارئ، اجعله صريحًا وقابلًا للبحث بـ grep بدلًا من التظاهر بأنه غير موجود.
type ButtonProps = {
/** Hierarchy, not colour — survives a rebrand. */
variant?: 'primary' | 'secondary' | 'ghost';
size?: 'sm' | 'md' | 'lg';
/** Renders as <a> when href is present, <button> otherwise. */
href?: string;
loading?: boolean;
children: React.ReactNode;
};
// No `className` prop. If a caller needs a shape this cannot produce,
// that is a system gap worth a conversation, not a one-off override.إمكانية الوصول جزء من المكوّن، لا من المستدعي
إذا كان على كل مستهلك أن يتذكر سمات aria-، فلن يتذكرها معظمهم، وسيتحول التدقيق في نهاية المشروع إلى لعبة بحث عن كنز. ضمّنها في المكوّن: إدارة التركيز في النافذة المنبثقة، وaria-expanded على عنصر الإفصاح، وحلقة تركيز مرئية تصمد أمام تغيير السمة، وaria-live على المنطقة غير المتزامنة.
هذا أعلى أعمال إمكانية الوصول أثرًا. فإصلاح مكوّن مشترك واحد يصلح كل شاشة تستخدمه، إلى الأبد، بما فيها الشاشات التي لم يبنِها أحد بعد.
التوثيق هو حيث تُكسب الثقة
جدول الخصائص المولَّد من الأنواع ضروري، لكنه أبعد ما يكون عن الكفاية. والأسئلة التي تدفع شخصًا فعلًا إلى كتابة مكوّنه الخاص هي:
- متى أستخدم هذا بدلًا من ذاك؟
- كيف يبدو مع تسمية من 90 حرفًا، أو بدونها؟
- ماذا يحدث أثناء التحميل، أو حين يكون فارغًا، أو حين يفشل؟
- هل يمكنني وضعه داخل بطاقة؟ داخل نموذج؟
- ما الذي لا يدعمه عمدًا، وما الذي ينبغي أن أستخدمه بدلًا منه؟
وثّق الحالات الحدّية — النص الطويل، والحالة الفارغة، والإخفاق — لأنها بالضبط الحالات التي تدفع الناس إلى نسخ المكوّن. فالمكوّن الذي يطابق سلوكه الموثّق ما يحدث في الثانية صباحًا من يوم جمعة هو المكوّن الذي يواصل الناس اللجوء إليه.
أدِر إصداراته كما تدير أي تبعية
أسرع طريقة لخسارة فريق هي أن تغيّر مكوّنًا مشتركًا فتكسر ثلاثة منتجات دون إنذار. والحل: ترقيم دلالي للإصدارات (semantic versioning)، وسجل تغييرات مكتوب للبشر، وإيقاف تدريجي متداخل لا قطعي: ضع علامة الإيقاف على الواجهة القديمة، وأطلق الجديدة بجوارها، وامنح الناس إصدارًا أو اثنين، ثم أزِلها.
تجعل اختبارات الانحدار البصري هذا آمنًا لتكراره كثيرًا. فمقارنة لقطات الشاشة في كل طلب دمج تلتقط الإزاحة غير المقصودة بمقدار بكسلين التي لم يكن أحد ليلتقطها في المراجعة، وهذا ما يتيح لك مواصلة تطوير النظام بدلًا من تجميده.
المؤشر الذي ينبغي مراقبته
الاعتماد هو المقياس الوحيد المهم، وقياسه سهل: عدّ المكوّنات المحلية الفريدة في مستودعات المنتج. إذا كان هذا الرقم يتراجع فالنظام يعمل. وإذا كان يرتفع فثمة ما في النظام أصعب استخدامًا من كتابته من جديد — ولن ينفع أي قدر من التوثيق حتى تكتشف ما هو.
نظام التصميم ليس مكتبة تُطلقها، بل اتفاق تحافظ عليه، ويدوم بقدر ما يثق الناس بأنه يغطي حالتهم.