الوحدة 5 · التبنّي على نطاق واسع
الـ Theming لعلامات متعدّدة على نطاق واسع
17 دقراءة 4 دبيئة تجريب الكود
الدرس في لمحة
أضف علامة تجارية ثانية إلى نظام التصميم بطبقة علامة صغيرة بين الـ primitives والـ semantic tokens، وتحقّق من التباين لكل علامة، وحدّد ما يحقّ للعلامات تغييره وما لا يحقّ لها.
لا فيديو هنا، بل الشيء الحقيقي: درس مكتوب وأمثلة قابلة للتشغيل واختبار وتدريب.
بعد ثمانية أشهر من استحواذ Northwind على Tidewater، انتقل موقعها التسويقي إلى Northwind UI. جاء فريق علامة Tidewater ومعه دليل علامة من 60 صفحة، وخط serif، ولوحة ألوان فيروزية، وأزرار على شكل حبّة دواء (pill). وجاء أيضًا بقائمة من 23 «متطلّبًا للعلامة» في المكوّنات. كانت مهمّتنا أن نقول نعم للعلامة ولا لمعظم القائمة، وأن نجعل الأمرين يبدوان معقولين.
ما يحقّ للعلامة تغييره
رسم الحوار الأول حدًّا واضحًا. العلامة تغيّر الشخصية: لوحة الألوان، والخطوط، ونصف قطر الزوايا، وأسلوب الرسوم، ونبرة الكتابة. ولا تغيّر السلوك أو البنية: التعامل مع لوحة المفاتيح، وإدارة التركيز، وسُلّم المسافات، وشبكات التخطيط، والـ component APIs، وإمكانية الوصول. يمكن أن تكون أزرار Tidewater حبّات فيروزية بتسمية بخط serif. لكن لا يمكنها أن تغلق النوافذ عند النقر خارجها بينما لا تفعل نوافذ Northwind ذلك، لأن هذا قرار منتج لا قرار علامة.
من المتطلّبات الثلاثة والعشرين، تبيّن أن 15 منها بصرية وتناسب الـ tokens. وستة كانت طلبات سلوك، فمرّت عبر مراجعة الـ API كاقتراحات عادية للعلامتين معًا (قُبل اثنان منها، للعلامتين). وأُسقط اثنان.
طبقة العلامة
قدّم القسم 2 تدرّجًا للعلامة حتى يستطيع الوضع الداكن اختيار الدرجات. ولعلامة ثانية كاملة، يكبر ذلك التدرّج ليصبح طبقة خاصة بين الـ primitives والـ semantic tokens:
طبقة العلامة صغيرة عن قصد. في Northwind تضم 24 token: تدرّج ألوان من 50 إلى 900، وعائلة خط للعناوين وأخرى للمتن، ونصفا قطر، ولون لحلقة التركيز. الـ semantic tokens تشير إلى الـ brand tokens، والمكوّنات لا تعرف أبدًا أن هناك علامة أصلًا.
:root,
[data-brand] {
--nw-color-action-bg: var(--nw-brand-600);
--nw-color-action-text: var(--nw-white);
--nw-font-heading: var(--nw-brand-font-heading);
--nw-radius-control: var(--nw-brand-radius-control);
}
[data-brand="tidewater"] {
--nw-brand-600: var(--nw-teal-600);
--nw-brand-700: var(--nw-teal-700);
--nw-brand-font-heading: Georgia, 'Times New Roman', serif;
--nw-brand-radius-control: 999px;
/* Tidewater's 600 fails contrast with white text: use the darker step. */
--nw-color-action-bg: var(--nw-brand-700);
}الـ selector المسمّى :root, [data-brand] مهمّ. تذكّر من درس الـ themes أن الـ custom property التي تحتوي var() تُحسب حيث عُرّفت. لو عُرّف --nw-color-action-bg على :root وحده، لحُسب مرة واحدة بتدرّج Northwind، ولورث قسم Tidewater في الصفحة نفسها أزرق Northwind. أما إعادة تعريف الروابط الدلالية على كل عنصر [data-brand] فتجعلها تُحسب داخل نطاق كل علامة. وهذا ما يسمح لصفحة المقارنة المشتركة في Northwind بعرض العلامتين جنبًا إلى جنب.
التباين لكل علامة
السطر الأخير في كتلة Tidewater هو المثير للاهتمام. لون الإجراء في Northwind هو الدرجة 600 من تدرّجها. أما 600 في Tidewater فأفتح، فيفشل نص الزر الأبيض فوقه:
function luminance(hex) {
const [r, g, b] = [1, 3, 5].map((i) => parseInt(hex.slice(i, i + 2), 16) / 255)
.map((v) => (v <= 0.04045 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4));
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
}
function contrast(a, b) {
const [hi, lo] = [luminance(a), luminance(b)].sort((x, y) => y - x);
return (hi + 0.05) / (lo + 0.05);
}
const pairs = { 'northwind blue-600': '#1f5ae0', 'tidewater teal-600': '#0d9488', 'tidewater teal-700': '#0f766e' };
for (const [name, bg] of Object.entries(pairs)) {
const ratio = contrast(bg, '#ffffff');
console.log(`${name} + white text: ${ratio.toFixed(2)}:1 ${ratio >= 4.5 ? 'pass' : 'FAIL'}`);
}لذا تربط Tidewater الدور الدلالي نفسه بدرجة مختلفة. ولهذا لا تكتفي طبقة العلامة بتبديل لوحات الألوان عشوائيًا: فالربط الدلالي لكل علامة مصمَّم ومفحوص. وفحص التباين في خط الإنتاج لدى Northwind يمرّ على كل زوج موثّق في كل علامة وكل theme، وقد التقط هذه المشكلة قبل أن يرى فريق العلامة زرًا واحدًا.
تسليم العلامات
كل واجهة تحمّل ما تحتاجه. المواقع التسويقية تضع data-brand على <html> ولا تحمّل إلا ملف CSS الخاص بعلامتها، الذي يولّده خط الإنتاج من primitives + brand-tidewater + semantic. أما تطبيق الـ dispatch، الذي يعرض العلامتين في شاشات الإدارة، فيحمّل الكتلتين. وفي Figma تعيش البنية نفسها في المجموعات الممتدّة، فيرى مصمّمو Tidewater المتغيّرات الدلالية المشتركة بقيم علامتهم.
وكل علامة تضاعف أيضًا مصفوفة الاختبار. مع علامتين ونظامي ألوان ومستويي كثافة، يُعرض كل مكوّن أساسي في ثماني تركيبات في المجموعة البصرية من القسم 4. يبدو ذلك مكلفًا حتى تتذكّر البديل: مصمّم في Tidewater يكتشف في الإنتاج أن حلقة التركيز في الوضع الداكن غير مرئية على الفيروزي. الآلات مراجِعون رخيصون للتركيبات؛ والبشر لا ينظرون إلا إلى الفروقات.
في التمرين تضيف Tidewater إلى صفحة تظهر فيها العلامتان جنبًا إلى جنب. وبعدها تقيس هل يُستخدم كل هذا فعلًا.
أهم النقاط
- العلامة تغيّر الشخصية (تدرّج الألوان، والخطوط، والأشكال) عبر مجموعة صغيرة من brand tokens؛ أما السلوك والمسافات وإمكانية الوصول فتبقى مشتركة.
- ضع طبقة للعلامة بين الـ primitives والـ semantic tokens، حتى تربط كل علامة الأسماء الدلالية نفسها بلوحة ألوانها الخاصة.
- يجب فحص التباين لكل علامة على حدة، وقد تحتاج علامة درجة مختلفة من تدرّجها للدور الدلالي نفسه.
- حين يمكن أن تظهر العلامات جنبًا إلى جنب، أعد تعريف الروابط الدلالية تحت الـ selector الخاص بالعلامة حتى تُحسب داخل نطاق كل علامة.