الرموز
الحدود
نظام حدود من ثلاث طبقات يحكم عرض الخط فقط. سلّم من خمس درجات، ورموز أولية، وثمانية رموز دلالية في مجموعتين: بنيوية وحالة. اللون يأتي من طبقة الألوان.
العرض هنا، اللون هناك
المعمار
ثلاث طبقات بلا أوضاع. السلّم خمس درجات (0، 0.5، 1، 2، 4). الأولية تسمّيها (none إلى lg). الدلالية ثمانية أدوار في ستة مستويات تسلسل. المكوّنات تستخدم الأدوار الدلالية فقط.
السلّم والأولية
الحدود البنيوية
ستة أدوار بنيوية في مستويات تسلسل ١–٥. divider وcontainer كلاهما ١ بكسل لكن غير متبادلين: الأول للتجاور، والثاني للتأطير.
استخدم · أخفّ حافة دون لفت انتباه: فواصل القوائم الكثيفة، الفصل الخلفي.
تجنّب · الاحتواء، الحالات التفاعلية، أو أي حدّ يحتاج قراءة واضحة؛ ليس الفاصل الوحيد على شاشات 1x.
استخدم · الحدّ الافتراضي: الحقول والبطاقات والمكوّنات القياسية.
تجنّب · حدود الأقسام، الحالات المختارة، الفصل عالي التأكيد.
استخدم · بين الأشقاء المتجاورين تحت أب واحد: عناصر القوائم، صفوف الجداول.
تجنّب · الإطارات الخارجية، حدود الاحتواء، المناطق الكبرى.
استخدم · لتأطير مجموعة محدودة: البطاقات، مجموعات الإعدادات، اللوحات.
تجنّب · التجاور البسيط، فواصل الصفوف، تقسيم الصفحة.
استخدم · حين يجب أن يقف الحدّ فوق البنية الافتراضية دون معنى تفاعلي.
تجنّب · البنية الافتراضية، الاحتواء المتكرّر، الحالة التفاعلية.
استخدم · مناطق التخطيط الكبرى وحدود الأقسام الأساسية.
تجنّب · الحاويات الافتراضية، حدود المكوّنات، المجموعات المحلية.
حدود الحالة
رمزان محجوزان للحالات التفاعلية فقط. حلقة التركيز تُرسم عبر outline بإزاحة، بلون --color-focus-default. جرّب التركيز على الزر أدناه بلوحة المفاتيح.
استخدم · حدود العناصر المختارة/المفعّلة التفاعلية.
تجنّب · البنية المحايدة، التجميع الخامل، التأطير غير الاختياري.
استخدم · حلقات تركيز لوحة المفاتيح على كل العناصر التفاعلية (عبر outline).
تجنّب · الحدود الزخرفية، تنسيق الاختيار الدائم، مؤشّرات التحويم.
التركيز = outline؛ الاختيار = border.
متى تستخدم حدّاً
الحدّ أداة الملاذ الأخير: استنفد المساحة وتباين السطح أولاً. هذه المصفوفة تختصر القرار.
| الموقف | الأداة |
|---|---|
| حالة مختارة أو تركيز | حدّ — border.selected / border.focus |
| منطقة تخطيط كبرى | خلفية + مساحة (border.section عند الحاجة) |
| حدّ مكوّن قياسي | حدّ — border.base |
| فصل بين أشقاء | أولاً مساحة؛ ثم border.divider |
المبادئ
عشرة مبادئ حاكمة لقرارات الحدود.
كل حدّ يؤدي وظيفة بنيوية محدّدة قبل اختيار وزنه.
الحدود الأثقل تنقل أهمية بنيوية أعلى.
الحدّ أحد ثلاث أدوات بنيوية (خط/مسافة/سطح)؛ الاختيار الخاطئ يضعف الوضوح.
شدّة استخدام الحدود تتناسب مع كثافة الواجهة.
حدود الحاوية والفاصل تخدمان غرضين بنيويين مختلفين.
حدود حالة التفاعل تبقى مميّزة بصرياً عن الحدود البنيوية.
الحدود دون البكسل تتطلّب استخداماً متعمّداً ومضبوطاً.
تُضاف الحدود فقط حين تعجز المساحة والخلفية عن تحقيق الفصل.
دور رمز الحدّ الدلالي لا يتغيّر عبر السياقات.
حدود التركيز والاختيار تحقّق التباين بمعزل عن اللون.
إمكانية الوصول
| المعيار | المستوى | لماذا ينطبق |
|---|---|---|
| 2.4.7 · التركيز مرئي | AA | border.focus يجب أن يُحلّ ≥ ١ بكسل؛ 0.5 غير موثوق، و0 يُخفي حلقة التركيز. |
| 1.4.1 · استخدام اللون | AA | border.selected مؤشّر اختيار غير لوني؛ لو صار 0 يعتمد الاختيار على اللون وحده. |
| 1.4.11 · تباين غير النص | AA | حدود التركيز/الاختيار تحقّق 3:1 مع المجاور؛ هذه الطبقة تفحص كفاية العرض، واللون في طبقة الألوان. |
border.focus لا يُعاد إلى 0 أبداً.
border.selected لا يصير 0 إلا مع مؤشّر غير لوني آخر.
border.subtle (0.5) ليس الفاصل الوحيد على شاشات 1x.
تسلسل الأوزان محفوظ: مجموعة ٢ فوق مجموعة ١.
الشيفرة للمطوّرين
التسليم الأساسي لطبقة الحدود هو متغيّرات CSS المخصّصة، وهي موحّدة عبر الأوضاع (عرض فقط، لا لون ولا نمط). المكوّنات تستهلك الأدوار الدلالية فقط، وتقرنها دائماً بنمط ولون حدّ من طبقة الألوان.
سلسلة المتغيّرات
المتغيّرات تُبنى على ثلاث طبقات: مدرّج أوّلي، ثم رمز أوّلي، ثم رمز دلالي يُحلّ حسب الوضع. المكوّنات تستهلك الطبقة الدلالية فقط.
/* Tier 1 — scale (raw widths) */
--border-scale-100: 1px;
--border-scale-200: 2px;
/* Tier 2 — primitive size aliases */
--border-sm: var(--border-scale-100);
--border-md: var(--border-scale-200);
/* Tier 3 — semantic role; components consume THIS */
:root {
--border-base: var(--border-sm); /* 1px — default structure */
--border-strong: var(--border-md); /* 2px — structural emphasis */
--border-focus: var(--border-md); /* 2px — keyboard focus ring */
}
/* A component pairs the width token with a style + Color-layer color */
.card {
border: var(--border-base) solid var(--color-border-base-medium);
}جدول المرجع
| الرمز | متغيّر CSS | القيمة | الاستخدام |
|---|---|---|---|
| border.subtle | --border-subtle | 0.5px | أخفّ فصل، المستوى ١ |
| border.base | --border-base | 1px | البنية الافتراضية، المستوى ٢ |
| border.divider | --border-divider | 1px | فصل المحتوى المتجاور، المستوى ٣ |
| border.container | --border-container | 1px | تأطير مجموعة محدودة، المستوى ٣ |
| border.strong | --border-strong | 2px | تأكيد بنيوي، المستوى ٤ |
| border.selected | --border-selected | 2px | حدّ الاختيار أو النشاط |
| border.focus | --border-focus | 2px | عرض حلقة تركيز لوحة المفاتيح |
الاستخدام
.card {
border: var(--border-base) solid var(--color-border-base-medium);
border-radius: var(--shape-surface-base);
}
.card--selected {
border: var(--border-selected) solid var(--color-focus-default);
}
/* Focus uses outline, not border, so it never shifts layout */
.button:focus-visible {
outline: var(--border-focus) solid var(--color-focus-default);
outline-offset: 2px;
}أخطاء شائعة
| الخطأ | ما يفسد | الصواب |
|---|---|---|
border: 1px solid ... | العرض غير مربوط برمز؛ لا يتّسق مع الكثافة | var(--border-base) |
| استخدام border لحلقة التركيز | يزيح التخطيط عند التركيز | outline: var(--border-focus) solid var(--color-focus-default) |
| ضبط العرض بلا لون حدّ | يورّث لون النص للحدّ | اقرن دائماً بـ --color-border-* |
| تبديل divider وcontainer | انحراف دلالي بين التجاور والتأطير | اختر الدور حسب الوظيفة |
كيف تُستهلك
الرموز مصدرها واحد آلي القراءة (tokens.json في المهارة). حزمة @mercato/tokens تولّد منه: متغيّرات CSS (التسليم الأساسي)، وإعداد Tailwind جاهز، وكائن سمة مطبوع بـ TypeScript. أهداف المنصّات الأخرى (Style Dictionary وDTCG وiOS وAndroid وCompose) تتولّد من المصدر نفسه عند الطلب.
// CSS variables (canonical) — import once at the app root
import "@mercato/tokens/css";
// Tailwind preset
// tailwind.config: { presets: [require("@mercato/tokens/tailwind")] }
// Typed theme object (JS/TS)
import { tokens } from "@mercato/tokens";