الوحدة 2 · الـ Design Tokens
ثلاث طبقات: Primitive وSemantic وComponent
20 دقراءة 4 دبيئة تجريب الكود
الدرس في لمحة
نظّم الـ design tokens في ثلاث طبقات primitive وsemantic وcomponent على شكل CSS custom properties، حتى يُحدّث تغييرٌ واحد في النيّة كلَّ مكوّن يتشاركها.
- 1الطبقة 1: الـ primitives
- 2الطبقة 2: الـ semantic tokens
- 3الطبقة 3: الـ component tokens
- 4كيف يحسب المتصفّح قيمة الـ token
- 5ليست الألوان وحدها
- 6طريقة سريعة لفحص طبقاتك
لا فيديو هنا، بل الشيء الحقيقي: درس مكتوب وأمثلة قابلة للتشغيل واختبار وتدريب.
كان أول ملف tokens في Northwind قائمة ألوان: --blue-600، --gray-200، --red-500. وكل مكوّن استخدمها مباشرة. بدا ذلك مرتّبًا حتى جاء الاستحواذ على Tidewater، وسأل أحدهم سؤالًا بسيطًا: «أيّ درجات الأزرق هي أزرق علامة Northwind، وأيّها مجرّد روابط؟». لم يستطع أحد الإجابة دون قراءة 300 ملف. القائمة المسطّحة من الألوان تسجّل القيم، لكنها لا تسجّل القرارات.
الطبقة 1: الـ primitives
الـ primitives (القيم الأولية) هي لوحة الألوان والقيم: كل قيمة خام يسمح بها النظام، مسمّاة بحسب ما هي.
:root {
--nw-blue-600: #1f5ae0;
--nw-blue-700: #1848b8;
--nw-gray-900: #1f2933;
--nw-gray-200: #d9dee3;
--nw-white: #ffffff;
--nw-space-2: 0.5rem;
--nw-space-4: 1rem;
}الـ primitives تجيب عن سؤال «ما القيم الموجودة؟». وهي لا تحمل أي معنى عن قصد. فـ --nw-blue-600 لا يعرف إن كان زرًا أو رابطًا أو خطًّا في رسم بياني.
الطبقة 2: الـ semantic tokens
الـ semantic tokens (الـ tokens الدلالية) تسمّي نيّة وتشير إلى primitive:
:root {
--nw-color-action-bg: var(--nw-blue-600);
--nw-color-action-bg-hover: var(--nw-blue-700);
--nw-color-action-text: var(--nw-white);
--nw-color-text: var(--nw-gray-900);
--nw-color-border: var(--nw-gray-200);
}هذه الطبقة هي الأكثر استخدامًا، وهي التي تغيّرها الـ themes. حين يصل الوضع الداكن أو علامة Tidewater، تعيد ربط هذه الأسماء بـ primitives مختلفة، ولا تلمس أي مكوّن.
الطبقة 3: الـ component tokens
الـ component tokens تسمّي الأجزاء القابلة للتعديل في مكوّن واحد، وتشير إلى الـ semantic tokens:
.nw-button {
--nw-button-bg: var(--nw-color-action-bg);
--nw-button-text: var(--nw-color-action-text);
--nw-button-padding-x: var(--nw-space-4);
background: var(--nw-button-bg);
color: var(--nw-button-text);
padding: var(--nw-space-2) var(--nw-button-padding-x);
}الآن صار لكل نوع من ثلاثة أنواع من التغيير مكان واحد واضح:
- لوحة ألوان جديدة (أزرق أفضل قليلًا في إمكانية الوصول): غيّر الـ primitive.
- theme جديد أو علامة جديدة (الوضع الداكن، Tidewater): أعد ربط الـ semantic tokens.
- مكوّن واحد يحتاج أن يختلف (زر الواجهة الرئيسية في الموقع التسويقي بحشوة أكبر): خصّص الـ token الخاص بذلك المكوّن.
والقاعدة التي تجعل كل هذا يعمل: المكوّنات تشير إلى الـ semantic tokens، ولا تشير إلى الـ primitives أبدًا. في اللحظة التي يستخدم فيها مكوّن --nw-blue-600 مباشرة، يتوقّف عن اتّباع الـ themes، وتكون قد أعدت بناء القائمة المسطّحة بأسماء أطول.
كيف يحسب المتصفّح قيمة الـ token
الـ custom properties تُورَّث كما تُورَّث color. حين يحسب المتصفّح أنماط زر ما، يبحث عن --nw-button-bg على الزر نفسه، فيجد var(--nw-color-action-bg)، ثم يبحث عن هذه أيضًا على الزر، حيث تكون القيمة موروثة من أقرب سلف حدّدها. ولهذا يمكنك تغيير theme جزء من الصفحة بتحديد semantic token على حاوية:
.campaign-banner {
--nw-color-action-bg: var(--nw-green-600);
}كل زر داخل اللافتة يصبح أخضر، وكل زر خارجها يبقى أزرق. بلا classes جديدة، وبلا تغيير في المكوّنات. وهذا السلوك في تحديد النطاق هو الأساس الذي تقوم عليه الـ themes في الدروس القادمة.
ليست الألوان وحدها
كل فئة من الـ tokens تُعامل بالطريقة نفسها. الـ primitives الخاصة بالمسافات سُلَّم (--nw-space-1 إلى --nw-space-12)؛ والمسافات الدلالية تسمّي دورًا، مثل --nw-space-inset-md للحشوة داخل البطاقة، أو --nw-space-stack-sm للفراغ بين حقول نموذج متراصّة. والـ primitives الخاصة بالطباعة هي عائلات الخطوط وأحجامها وأوزانها؛ والطباعة الدلالية تسمّي أنماطًا مثل --nw-font-body أو --nw-font-heading-lg. وتتبع أنصاف الأقطار والظلال ومُدد الحركة النمط نفسه.
وللتصوّر: لدى Northwind اليوم نحو 180 primitive، و120 semantic token، و90 component token. الطبقة الدلالية هي حيث يحدث معظم التفكير التصميمي، وهي الطبقة التي يجب أن يلجأ إليها المصمّمون والمهندسون أولًا. وإن ظلّ فريق يطلب primitive بعينه، فهذا يعني عادةً أن semantic token ناقص، والإصلاح الصحيح أن تضيف الدور، لا أن تسلّم القيمة الخام.
طريقة سريعة لفحص طبقاتك
افتح الـ CSS الخاص بأي مكوّن وابحث عن البادئة الخاصة بالـ primitives لديك، مثل --nw-blue أو --nw-gray. في النظام السليم تظهر هذه الأسماء في مكان واحد فقط: تعريفات الـ semantic tokens. تشغّل Northwind هذا الفحص كقاعدة lint في الـ CI، وستتعرّف عليها في القسم 4. في التمرين تضيف الطبقتين الدلالية والخاصة بالمكوّن إلى زر يقفز حاليًا مباشرة إلى primitive. وبعدها تسمّي هذه الـ tokens بطريقة تبقى منطقية بعد ثلاث سنوات.
أهم النقاط
- الـ primitive tokens تسمّي القيم الخام (
--nw-blue-600)، والـ semantic tokens تسمّي النيّة (--nw-color-action-bg)، والـ component tokens تسمّي مفاتيح التحكّم الخاصة بمكوّن واحد. - المكوّنات تشير إلى الـ semantic tokens ولا تشير إلى الـ primitives أبدًا، فيقتصر تغيير الـ theme على الطبقة الدلالية.
- عرّف الـ component tokens على الـ selector الخاص بالمكوّن لا على
:root، حتى تُحسب قيمتها وفق أي تخصيص في ذلك الجزء من الصفحة. - أضف الـ component tokens باقتصاد؛ فكل واحد منها API عام ستلتزم بدعمه.