---
title: "أنظمة التصميم والتخصيص"
description: "مفردات واحدة وأنظمة تصميم كثيرة. غيِّر قرص ضبط، أو أعلن لوحة ألوان، أو أعد توجيه رمز، فتتبعك كل المنصات في إيداع واحد."
url: "https://tanrei.chnotchy.com/ar/foundations/design-systems/"
last_updated: 2026-10-23T06:11:40.000Z
---

# أنظمة التصميم والتخصيص

> مفردات واحدة وأنظمة تصميم كثيرة. غيِّر قرص ضبط، أو أعلن لوحة ألوان، أو أعد توجيه رمز، فتتبعك كل المنصات في إيداع واحد.

بُني Tanrei ليستطيع إعادة إنتاج أي نظام تصميم، بدقة تامة لا بالتقريب، مع بقاء مفرداته هو صغيرة. قاعدتان تجعلان ذلك ممكنًا: **أنظمة التصميم تختلف في القيم أولًا**، و**ما لا تستطيع القيمة التعبير عنه تضيفه الطبقة.**

## ما الرمز الأساس وما ليس كذلك

المفردات الأساس (core) في Tanrei هي كل حالة يمكن أن **يتخذها نظام تصميم واحد داخل منتج واحد**. ومن هذا ينتج اختبار لكل رمز (token) مقترح، هو **اختبار «المنتج الواحد»**:

- **يكون رمزًا** إذا كان منتج واحد قد يحتاج إلى التمييز، بالمعنى أو بالموضع. الدور `focus-ring` منفصل عن `primary` لأن منتجًا قد يريد لون علامة مشبعًا وحلقة تركيز هادئة. وكون النظام الافتراضي يعطيهما قيمتين متقاربتين مصادفة، لا سبب لدمجهما. وللمكوّن Button أحجام لأن المنتج الواحد يستخدم عدة أحجام.
- **لا يكون رمزًا** إذا كان موجودًا في نظام تصميم واحد فقط، أو في منتج واحد غير مألوف. الدور `tertiary` في Material Design 3 لوحة ألوان معلنة في الإعداد الجاهز الذي يعيد إنتاجه، وأدوار `primary-fixed` فيه امتدادات لذلك الإعداد، لا خانات يحملها الجميع. وعشرون حجمًا للزر من أجل منتج غريب واحد ليست من المفردات الأساس كذلك؛ يضيفها ذلك المنتج إلى طبقته.

وإذا تعذّرت مع ذلك إعادة إنتاج سمة من سمات نظام تصميم، كمادة خلفية أو جدول أحجام نص خاص به، فذلك عيب في Tanrei يُقيَّد في سجل فجوات المحاكاة (`docs/governance/mimicry-gaps.json` في المستودع).

## أقراص الضبط: تغيير واحد في كل مكان

ينبغي أن يبدو نظام التصميم صحيحًا افتراضيًّا، وأن يتبعك حين تغيّر شيئًا واحدًا. ثمانية **أقراص ضبط** (dials) رقمية تقع تحت كل شيء:

| القرص | الافتراضي | ما يحرّكه |
| --- | --- | --- |
| `dial.type.base` | 16px | كل أحجام النص |
| `dial.type.contrast` | 1 | مدى تميّز العناوين عن نص المتن |
| `dial.space.unit` | 8px | كل المسافات |
| `dial.size.unit` | 4px | ارتفاعات عناصر التحكم، وأحجام الأيقونات، وأهداف اللمس |
| `dial.density` | 1 | ارتفاع عناصر التحكم والصفوف، والمساحة حول محتواها: أقل من 1 أكثر تقاربًا، وأكثر من 1 أوسع |
| `dial.shape.unit` | 2px | كل الزوايا |
| `dial.stroke.unit` | 1px | الحدود، والحلقات، ومؤشر التركيز |
| `dial.motion.unit` | 50ms | كل المدد |

كل رمز واحد من ثلاثة أنواع:

- **مشتق**: قاعدة صغيرة، وهي في العادة معامل على قرص. `display` هو `type.base × 3`، و `space175` هو `space.unit × 1.75`. سلالم أحجام النص الحقيقية ليست هندسية، ولذلك لكل رمز معامله **الخاص**؛
- **ثابت**: قيمة حرفية لها سبب مذكور، معفاة من الأقراص (`corner.full`، أو منحنى تسارع، أو حجم حاشية يفرضه القانون)؛
- **اسم بديل** (alias): إحالة يمكن إعادة توجيهها (`button.container.gap` ← `space100`).

على الويب تعمل الأقراص حيّةً أيضًا: تُكتب الرموز المشتقة تعبيرات `calc()`، فضبط `--tanrei-dial-type-base` على أي عنصر يعيد تحجيم كل ما بداخله. ويوجد اختبار يقيّم كل رمز مشتق في متصفح حقيقي تحت عدة إعدادات للأقراص، ويشترط أن يساوي نتيجة البناء.

## نظام التصميم طبقة

نظام التصميم ملف JSON صغير **يمتدّ** من نظام آخر. هو في الغالب يغيّر قيمًا؛ وحيث يلزم [يضيف إلى المفردات](https://tanrei.chnotchy.com/ar/foundations/design-systems/#%D8%A7%D9%84%D8%A5%D8%B6%D8%A7%D9%81%D8%A9-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%85%D9%81%D8%B1%D8%AF%D8%A7%D8%AA).

```json
{
  "id": "acme",
  "extends": "tanrei",
  "palettes": {
    "brand":   { "description": "أحمر Acme تحدده إرشادات العلامة التجارية.", "source": { "seed": "#e60012" }, "roles": "intent" },
    "correct": { "description": "الاختبار يعلّم الإجابات الصحيحة، وليس هذا success ولا primary.", "source": { "seed": "#0f766e" }, "roles": "intent" }
  },
  "tokens": {
    "tanrei.dial.type.base": { "$value": { "value": 17, "unit": "px" }, "reason": "جمهورنا يقرأ على بُعد ذراع." },
    "tanrei.comp.button.container.padding-inline-start.medium": { "scale": 2 },
    "tanrei.comp.button.container.gap.medium": { "$value": "{tanrei.sys.space.space50}" },
    "tanrei.sys.typescale.label-small": { "$value": { "fontSize": { "value": 11, "unit": "px" } }, "reason": "حجم الحاشية القانونية ملزم تعاقديًّا." }
  }
}
```

| ما تريده | ما تكتبه |
| --- | --- |
| كل شيء أكبر قليلًا | اضبط قرصًا |
| حشو الزر ضعف الافتراضي، مع بقائه تابعًا لقرص التباعد | `"scale": 2` |
| أن يستخدم هذا الرمز درجة أخرى | أعد توجيه الاسم البديل |
| أن تبقى هذه القيمة الواحدة في مكانها مهما فعلت الأقراص | ثبِّت `$value` مع `reason` |
| لون علامة أو لون خاص بمجالك له دورا `on-` و `-container`، مع فحص التباين | أعلن لوحة ألوان مع `"roles": "intent"` |

ولأن شيفرة كل منصة مولَّدة من النظام المحلول نفسه، فإن طلب سحب واحدًا يغيّر الويب و SwiftUI و Compose و Flutter و React Native معًا.

## الإضافة إلى المفردات

القيم لا تكفي دائمًا. في نظام مرجعي أحجام للزر ليست في الأساس؛ وفي منتجك مكوّن تقييم خاص به. لذلك تستطيع الطبقة أيضًا أن **توسّع** المفردات: تحت `vocabulary`، ومع `rationale` دائمًا، وبالإضافة فقط:

```json
"vocabulary": {
  "tanrei.sys.space.space1200":        { "$type": "dimension", "rationale": "أقسام الواجهة الرئيسية تحتاج إلى درجة إيقاع مقدارها 96px.",
                                          "derive": { "fn": "mul", "of": "{tanrei.dial.space.unit}", "by": 12 } },
  "tanrei.comp.button.size.3x":        { "from": "large", "scale": 1.5, "rationale": "زر الدعوة إلى الإجراء في شاشة الهبوط." },
  "tanrei.comp.button.variant.danger": { "from": "filled", "rationale": "تأكيد الإجراء الهدّام توكيد مستقل هنا." },
  "acme.comp.rating.star.size":        { "$type": "dimension", "rationale": "نجمة مكوّن التقييم.",
                                          "derive": { "fn": "mul", "of": "{tanrei.dial.size.unit}", "by": 5 } }
}
```

| ما تضيفه | ما يحدث |
| --- | --- |
| **درجة في سلسلة**: درجة تباعد، أو زاوية، أو دور نص، أو دور لون مع الدور المرسوم فوقه (`onRole`) | تأخذ مكانها بجوار جاراتها، وتتبع القرص نفسه، ويُفحص تباينها كأي زوج من الأساس |
| **قيمة على محور مكوّن**: حجم أو طراز (variant) للمكوّن Button | يكفي سطر واحد. الحجم ينسخ كل أعضاء المحور (الارتفاع، والحشو، ونمط التسمية، والأيقونة) من حجم آخر ويغيّر مقاسها بنسبة، مع بقائها تابعة للأقراص. والطراز ينسخ ألوان وضع السكون؛ و**قواعد الأنماط في النظام تعطي رموز التحويم والتركيز والضغط والتعطيل قيمها عنك** |
| **رموزك الخاصة**، في نطاق أسماء طبقتك (`acme.…`) | لمكوّناتك أنت. يجوز أن تحيل إلى أي رمز `tanrei.*`، وأن تتبع الأقراص والمخططات اللونية، وتصير `--acme-…` على الويب وكائنًا محدَّد النوع على كل منصة أخرى |

يقول `vocabulary` إن شيئًا ما **موجود**؛ ويعطيه `tokens` و `rules` **قيمة**، تمامًا كما في رموز الأساس، ولذلك تغيّر الطبقة الوليدة الامتداد كما تغيّر أي شيء آخر. الامتدادات تُورَّث، ولا تزيل شيئًا من الأساس ولا تغيّر نوعه أبدًا، ولا تستطيع إضافة حالات تفاعل (فهذه تخص المنصة). وتسرد كل حزمة مولَّدة الامتدادات مع من أعلنها ولماذا.

تقبل المكوّنات ما تضيفه. يعمل `<tanrei-button size="3x" variant="danger">` على الويب، وتأخذ الحزم الأصلية المفاتيح نفسها؛ والقيمة التي لا يملكها نظام التصميم الفعّال تُرسم بالقيمة الافتراضية. **النظام الذي لا يضيف شيئًا لا يدفع شيئًا**: شيفرته المولَّدة لا تذكر الامتدادات إطلاقًا.

هكذا يجتمع مثلان أعليان: تبقى مفردات Tanrei نفسه صغيرة وواضحة الأسماء، **و**يمكن مطابقة أي نظام تصميم بدقة تامة، لأنه لا يلزم أن يُضاف شيء إلى الأساس من أجل غيره.

## مظهر الحالة قيمة أيضًا

لا تحسب المكوّنات مظهر التحويم أو الضغط أبدًا. لكل حالة رموزها (`button.filled.hovered.container.color`، …)، و**قواعد الأنماط** في النظام تعطيها قيمها:

```json
{ "match": "tanrei.comp.*.*.hovered.container.color",
  "derive": { "fn": "mix", "base": "{tanrei.comp.$1.$2.container.color}", "with": "{tanrei.comp.$1.$2.label.color}", "amount": "{tanrei.sys.state.hover-state-layer-opacity}" } }
```

هذه هي طبقة الحالة في Tanrei. النظام الذي له ألوان صريحة لكل حالة يكتب أسماء بديلة مكانها؛ والذي لا تحويم فيه يجعل الحالة اسمًا بديلًا لقيمة وضع السكون؛ والذي يُعتم عند الضغط يضبط `pressed.opacity`. المفردات نفسها وقيم مختلفة.

## اختيارات النوع

فروق قليلة ليست مقادير أصلًا: ضغط يُستجاب له بتموّج أو بإعتام عنصر التحكم، وتركيز لوحة مفاتيح يُعرض حلقةً أو توهّجًا. هذان رمزان تحت `sys.behavior` (`pressed-feedback` و `focus-style`)، لكل منهما قائمة قصيرة مغلقة من الأسماء، وتختار الطبقة واحدًا منها كأي قيمة أخرى. أما طريقة انحناء الزاوية فمقدار لا اختيار: `sys.shape.corner-smoothing` في صفحة [الشكل](https://tanrei.chnotchy.com/ar/foundations/shape/#%D8%AA%D9%86%D8%B9%D9%8A%D9%85-%D8%A7%D9%84%D8%B2%D9%88%D8%A7%D9%8A%D8%A7). وتشرحها صفحة [السلوك](https://tanrei.chnotchy.com/ar/foundations/behaviour/). ومجموعة الأيقونات والخطوط مما تغيّره الطبقة كذلك: انظر [الأيقونات](https://tanrei.chnotchy.com/ar/foundations/icons/#%D9%85%D8%AC%D9%85%D9%88%D8%B9%D8%A9-%D8%A3%D9%8A%D9%82%D9%88%D9%86%D8%A7%D8%AA-%D9%84%D9%83%D9%84-%D9%86%D8%B8%D8%A7%D9%85-%D8%AA%D8%B5%D9%85%D9%8A%D9%85) و[الطباعة](https://tanrei.chnotchy.com/ar/foundations/typography/#%D8%A7%D9%84%D8%AE%D8%B7%D9%88%D8%B7-%D9%84%D9%83%D9%84-%D9%86%D8%B8%D8%A7%D9%85-%D8%AA%D8%B5%D9%85%D9%8A%D9%85).

## الأنظمة المضمَّنة

العنصر `<tanrei-button>` نفسه، والترميز نفسه. النظامان `m3-like` و `cupertino` موجودان لإثبات الآلية أمام نظامين متعاكسَي الطابع، وليكونا نقطتَي بداية لطبقتك.

**الدقة تُقاس ولا تُدَّعى.** يحمل `m3-like` خريطة مطابقة مع الرموز المنشورة في material-web (Apache-2.0): كل دور لون، وكل نمط نص، وكل رمز للمكوّن Button في المرجع يجب أن يكون مساويًا، أو مغطًّى برمز آخر، أو مسرودًا مع فجوة المحاكاة التي تفسّره. يُعرض الرقم مع الإعداد الجاهز أدناه: عدد الرموز المساوية من بين الرموز غير المغطاة برمز آخر، مقروءًا من `tokens/generated/<id>/fidelity.json`. ويُسمّى باللاحقة `-like` لأسباب تتعلق بالعلامات التجارية، لا لأنه تقريبي.

على الويب يكون الإعداد الجاهز ورقة أنماط إضافية واحدة، محصورة في سمة، فتستطيع الأنظمة أن تتجاور في الصفحة نفسها. ويسجّل مدخلُه المكوّناتِ التي يملكها، ومنها ما يتركه النظام الافتراضي (لا يسجّل `@tanrei/web` إلا مكوّنات النظام الافتراضي):

```js
import '@tanrei/web/tokens.css';
import '@tanrei/web/systems/cupertino.css';
import '@tanrei/web/cupertino'; // المكوّنات التي يملكها cupertino
```

```html
<body data-tanrei-system="cupertino">
```

ما لا تستطيع القيم ولا اختيارات النوع التعبير عنه بعد، كمواد الخلفية والتسميات بالأحرف الكبيرة على سبيل الأسلوب، مسرود عيبًا في Tanrei في `docs/governance/mimicry-gaps.json`، وليس مخفيًّا.

## مكوّن لا يملكه نظامك

يمكن للنظام أن يستبعد مكوّنًا، أو قيمة واحدة من قيم `variant` لمكوّن ما: النظام الافتراضي لا يملك زرًّا مقسَّمًا، ولا حقل نص بنمط filled أو outlined. وتذكر الطبقة ذلك تحت `components`، مع السبب وما يُستخدم بدلًا منه:

```json
"components": {
  "omit": { "carousel": { "reason": "Acme shows one thing at a time.", "insteadUse": ["list"] } },
  "variants": { "tabs": { "omit": ["tonal"] } }
}
```

ما يُستبعَد يظل يُعرض ويعمل. وفي بناء التطوير، يُصدر كل عنصر يستخدمه تحذيرًا واحدًا في وحدة التحكم، يذكر نظامك وما يستخدمه بدلًا منه. ويسمّي التحذير المكوّن الذي كتبته: يُبلَّغ عن `<tanrei-text-field variant="outlined">` على أنه نمط `outlined` لحقل النص، لا على أنه حقل الإدخال الذي يرسمه في داخله. والمكوّن الذي يقيم في طبقة نظام آخر، مثل قائمة FAB في m3-like، يُبلَّغ عنه بالطريقة نفسها، مع الطبقة التي يقيم فيها.

لتُفشِل اختباراتك عند ذلك، اجعله يُبلَّغ عنه خطأً، واسأل عمّا استُخدم:

```js
import { setAvailabilityMode, unavailableUses } from '@tanrei/web';

setAvailabilityMode('error'); // في إعداد اختباراتك، قبل أن يُعرض أي شيء

test('المنتج لا يستخدم إلا ما يملكه نظامه', async () => {
  // …اعرض شاشات المنتج…
  expect(unavailableUses()).toEqual([]);
});
```

تسرد `unavailableUses()` كل استخدام مرة واحدة، بالترتيب الأبجدي (`segmented-button`، `text-field:outlined`)، في أيٍّ من الوضعين. أما بناء الإنتاج فلا يتحقق من شيء، لذا تبقى القائمة فيه فارغة. ويضم `@tanrei/web/availability` الدالتين نفسيهما دون أن يسجّل أي عنصر.

## مشاركة النظام

ينتج عن بناء النظام **حزمة DTCG 2025.10** مكتفية بذاتها، أي ملفات رموز بسيطة كاملة القيم مع محلِّل (resolver) قياسي، فتستطيع أي أداة تقرأ رموز التصميم أن تستهلكها من دون Tanrei. وملفات الطبقات التي أنتجتها محمولة داخل الحزمة، فيستطيع Tanrei (أو وكيل ذكاء اصطناعي) إعادة بنائها أو تعديلها.

> [!WARNING]
> **إمكانية الوصول**
>
> عتبات التباين ثوابت لا يستطيع أحد تغييرها. في النظام الافتراضي تُفشل المخالفة البناء. وفي طبقة منتج تكون المخالفة **تحذيرًا** يُطبع عند البناء ويُكتب في المخرجات المولَّدة، ولا يمرّ بصمت أبدًا. أما الإعداد الجاهز الذي يحاكي نظامًا آخر فيُحكَم عليه بمطابقته لذلك النظام: لا تنطبق عليه معايير إمكانية الوصول في Tanrei، لا في التباين القياسي ولا المتوسط ولا العالي، ونسب التباين التي يقيسها البناء فيه تُسجَّل معلوماتٍ لا تحذيرات. وأما الخلل الوظيفي، مثل عنصر تحكم يتعذّر تشغيله أو اسم مفقود أو حالة مفقودة، فهو عيب في كل نظام، حتى في الإعداد الجاهز الذي يحاكي نظامًا آخر.
