{"id":"l-fig-3-2","courseId":"figma-ui-design","lang":"ar","kind":"lesson","summary":"اجمع الـ components المترابطة في variant set بأسماء خصائص واضحة، ثم أضف خصائص من نوع boolean وtext وinstance swap ليبقى زر Steady وصف العادة فيه صغيرين وسهلي الاستخدام.","html":"<p>يبدو الزر الأساسي في Steady بسيطًا حتى تكتب قائمة بما يحتاجه: أنواع primary وsecondary وghost؛ وحالات default وpressed وdisabled؛ وحجمان medium وsmall؛ وأيقونة اختيارية؛ وأي تسمية. ابنِ كلًّا من ذلك كـ component منفصل وستحصل على عشرات النسخ شبه المتطابقة، ومصمّم يختار بين <code dir=\"ltr\">Button Primary Small Disabled With Icon</code> وجيرانه.</p>\n<p>الـ Variants والـ Component properties تحوّل هذه الكومة إلى component واحد ببضعة مفاتيح واضحة.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">الـ Variants: مجموعة واحدة، نسخ كثيرة</h2>\n<p>الـ <strong>component set</strong> يحمل components مترابطة تُسمّى <strong>variants</strong>. كل variant تصفه <strong>variant properties</strong>، تُكتب كأزواج <code dir=\"ltr\">Property=Value</code>. لزر Steady:</p>\n<ul>\n<li><code dir=\"ltr\">Type</code>: ‏Primary وSecondary وGhost</li>\n<li><code dir=\"ltr\">State</code>: ‏Default وPressed وDisabled</li>\n<li><code dir=\"ltr\">Size</code>: ‏Medium وSmall</li>\n</ul>\n<p>تنشئ الـ variants إمّا بتحديد عدّة components موجودة والنقر على <strong>Combine as variants</strong>، أو بتحديد component وإضافة variant من الشريط الجانبي الأيمن، ثم إعادة تسمية الخصائص والقيم. يعتبر Figma الـ variant الموجود في الزاوية العلوية اليسرى من المجموعة هو الافتراضي.</p>\n<p>في الـ instance، لا يعود الناس يبحثون في الـ assets. يضعون Button واحدًا ويختارون القيم من قوائم منسدلة: Type ‏Secondary، وState ‏Disabled. الأسماء التي تختارها هنا هي الأسماء التي سيراها المطوّرون في Dev Mode، فاجعلها تطابق الكود حيث تستطيع. إذا كان الكود يقول <code dir=\"ltr\">variant=&quot;secondary&quot;</code>، ففكّر في تسمية خاصيتك <code dir=\"ltr\">Variant</code> بدل <code dir=\"ltr\">Type</code>، واتّفق على ذلك مع فريق الهندسة مبكرًا.</p>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 680 260\" role=\"img\" aria-labelledby=\"l-fig-3-2-t1\"><defs><marker id=\"arrow-l-fig-3-2-1\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\"><path d=\"M0 0 L10 5 L0 10 z\" class=\"d-arrowhead\"/></marker></defs>\n  <title id=\"l-fig-3-2-t1\">شبكة ثلاثة في ثلاثة من variants الزر. الأعمدة هي الحالات Default وPressed وDisabled؛ والصفوف هي الأنواع Primary وSecondary وGhost. ويحيط إطار متقطّع بالمجموعة كلها.</title>\n  <rect class=\"d-box d-dashed\" x=\"110\" y=\"30\" width=\"560\" height=\"220\" rx=\"12\"/>\n  <text class=\"d-label-muted\" x=\"210\" y=\"22\" text-anchor=\"middle\">Default</text>\n  <text class=\"d-label-muted\" x=\"390\" y=\"22\" text-anchor=\"middle\">Pressed</text>\n  <text class=\"d-label-muted\" x=\"570\" y=\"22\" text-anchor=\"middle\">Disabled</text>\n  <text class=\"d-label-muted\" x=\"100\" y=\"80\" text-anchor=\"end\">Primary</text>\n  <text class=\"d-label-muted\" x=\"100\" y=\"150\" text-anchor=\"end\">Secondary</text>\n  <text class=\"d-label-muted\" x=\"100\" y=\"220\" text-anchor=\"end\">Ghost</text>\n  <rect class=\"d-box-primary\" x=\"140\" y=\"56\" width=\"140\" height=\"40\" rx=\"10\"/>\n  <text class=\"d-label-strong\" x=\"210\" y=\"81\" text-anchor=\"middle\">Save habit</text>\n  <rect class=\"d-box-primary\" x=\"320\" y=\"56\" width=\"140\" height=\"40\" rx=\"10\"/>\n  <text class=\"d-label-strong\" x=\"390\" y=\"81\" text-anchor=\"middle\">Save habit</text>\n  <rect class=\"d-box\" x=\"500\" y=\"56\" width=\"140\" height=\"40\" rx=\"10\"/>\n  <text class=\"d-label-muted\" x=\"570\" y=\"81\" text-anchor=\"middle\">Save habit</text>\n  <rect class=\"d-box-accent\" x=\"140\" y=\"126\" width=\"140\" height=\"40\" rx=\"10\"/>\n  <text class=\"d-label\" x=\"210\" y=\"151\" text-anchor=\"middle\">Save habit</text>\n  <rect class=\"d-box-accent\" x=\"320\" y=\"126\" width=\"140\" height=\"40\" rx=\"10\"/>\n  <text class=\"d-label\" x=\"390\" y=\"151\" text-anchor=\"middle\">Save habit</text>\n  <rect class=\"d-box\" x=\"500\" y=\"126\" width=\"140\" height=\"40\" rx=\"10\"/>\n  <text class=\"d-label-muted\" x=\"570\" y=\"151\" text-anchor=\"middle\">Save habit</text>\n  <text class=\"d-label\" x=\"210\" y=\"221\" text-anchor=\"middle\">Save habit</text>\n  <rect class=\"d-box\" x=\"320\" y=\"196\" width=\"140\" height=\"40\" rx=\"10\"/>\n  <text class=\"d-label\" x=\"390\" y=\"221\" text-anchor=\"middle\">Save habit</text>\n  <text class=\"d-label-muted\" x=\"570\" y=\"221\" text-anchor=\"middle\">Save habit</text>\n</svg><figcaption>الـ component set لزر Steady: كل تركيبات Type وState لحجم واحد</figcaption></figure>\n<h2 id=\"sec-2\" tabindex=\"-1\">الـ Component properties: مفاتيح بلا مضاعفة</h2>\n<p>الـ variant properties تتضاعف. ثلاثة أنواع × ثلاث حالات × حجمان = 18 variant. أضف variant property باسم <code dir=\"ltr\">Icon</code> بقيمتين فيصبح العدد 36، وكل واحد منها يجب بناؤه وإبقاؤه متزامنًا. هذا يُسمّى انفجار الـ variants ‏(variant explosion)، وهو أشيع طريقة تصبح بها أنظمة التصميم غير قابلة للصيانة.</p>\n<p>الـ Component properties تتولّى الاختلافات التي لا تحتاج نسخة مصمّمة بشكل منفصل:</p>\n<ul>\n<li><strong>Boolean</strong>: يُظهر طبقة أو يخفيها. <code dir=\"ltr\">Show icon</code> ‏true أو false. طبقة واحدة، بلا variants جديدة.</li>\n<li><strong>Text</strong>: يكشف محتوى طبقة نص. <code dir=\"ltr\">Label</code> = “Save habit”. يعدّله الناس من لوحة الخصائص دون البحث عن الطبقة.</li>\n<li><strong>Instance swap</strong>: يختار أيّ component يملأ instance متداخلة. <code dir=\"ltr\">Icon</code> = Plus أو Check أو Bell. ويمكنك ضبط <strong>preferred values</strong>، أي قائمة قصيرة من الأيقونات المعقولة، حتى لا يضع أحد سلّة مهملات على زر الحفظ.</li>\n<li><strong>Slot</strong>: وقت كتابة هذا الدرس، نوع خاصية أحدث يعلّم منطقة يمكن للـ instances أن تحمل فيها محتواها الخاص، مثل جسم اللوحة السفلية، بينما يبقى كل ما حولها مرتبطًا.</li>\n</ul>\n<p>تضيف هذه الخصائص على الـ main component: حدّد الطبقة، ثم استخدم خيار الخاصية بجانب ظهورها (boolean)، أو محتواها النصي (text)، أو الـ instance المتداخلة فيها (instance swap) في الشريط الجانبي الأيمن، أو أنشئ خاصية من قسم الخصائص واربطها بطبقة.</p>\n<aside class=\"callout callout-tip\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5\"/><path d=\"M9 18h6\"/><path d=\"M10 22h4\"/></svg><span><span class=\"callout-kind\">نصيحة</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>السؤال الحاسم</span></p>\n<p>اسأل: <em>هل يعيد هذا الاختلاف تنسيق عدّة طبقات معًا؟</em> الزر المضغوط يغيّر التعبئة ولون التسمية وربما الظل دفعة واحدة، لذا فالـ State ‏variant. إظهار أيقونة يغيّر ظهور طبقة واحدة، فهو boolean. وأيّ أيقونة هو instance swap. وما تقوله التسمية هو text.</p>\n</aside>\n<h2 id=\"sec-3\" tabindex=\"-1\">ترتيب البناء مهم</h2>\n<p>أضف خصائص text وboolean وinstance swap إلى الـ component الأول <strong>قبل</strong> أن تضيف المزيد من الـ variants. الـ variants الجديدة المنشأة منه ترث روابط تلك الخصائص. إذا بنيت 18 variant أولًا، فستربط طبقة التسمية 18 مرة.</p>\n<p>صف العادة يُعامَل بالطريقة نفسها:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"text\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">Text</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code>Habit row (component set)\n  State      variant        To do | Done | Missed\n  Name       text           &quot;Read 20 pages&quot;\n  Show streak boolean       true\n  Icon       instance swap  Habit icon/Book  (preferred: Book, Water, Run, Sleep)</code></pre></div>\n<p>ثلاثة variants بدل العشرات، لأن Done وMissed يعيدان تنسيق عدّة طبقات (تعبئة زر التعليم، ولون الاسم، وخط يتوسّطه) بينما كل ما عدا ذلك خاصية.</p>\n<p>حين يضمّ component ‏components أخرى، يضطرّ الناس عادةً إلى التعمّق في الطبقات للوصول إلى خصائص الداخلية منها. وقت كتابة هذا الدرس، يستطيع صانع الـ component ‏<strong>كشف الـ instances المتداخلة</strong> (expose nested instances)، فتظهر خصائص Check button نفسها بجانب خصائص Habit row في اللوحة.</p>\n<aside class=\"callout callout-mistake\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"/><path d=\"M12 9v4\"/><path d=\"M12 17h.01\"/></svg><span><span class=\"callout-kind\">خطأ شائع</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>تسمية القيم حسب المظهر</span></p>\n<p><code dir=\"ltr\">State=Teal</code> و<code dir=\"ltr\">State=Grey</code> منطقيتان اليوم ومضلّلتان غدًا حين يتغيّر لون العلامة التجارية. سمِّ القيم حسب المعنى، <code dir=\"ltr\">Done</code> و<code dir=\"ltr\">To do</code>، فتصمد الأسماء أمام إعادة التصميم وتطابق ما يسمّيها به الكود.</p>\n</aside>\n<p>صار في مجموعتك عدد قليل من الـ components المرنة. لكن ألوانها وأرقامها ما زالت تُكتب يدويًا. في الدرس التالي تنقل هذه القيم إلى الـ styles والـ variables.</p>\n","toc":[{"id":"sec-1","text":"الـ Variants: مجموعة واحدة، نسخ كثيرة","level":2},{"id":"sec-2","text":"الـ Component properties: مفاتيح بلا مضاعفة","level":2},{"id":"sec-3","text":"ترتيب البناء مهم","level":2}],"takeaways":["الـ Variants تجمع نسخ الـ component في component set واحد، وتصفها خصائص مثل Type وState.","استخدم الـ variants للاختلافات التي تعيد تنسيق عدّة طبقات دفعة واحدة، مثل الحالات والأنواع والأحجام.","استخدم خاصية boolean للإظهار والإخفاء، وخاصية text للتسميات القابلة للتعديل، وخاصية instance swap لاختيار component متداخل.","كل variant property تضاعف عدد الـ variants، بينما خصائص boolean وtext وinstance swap لا تفعل ذلك.","الـ Slots، وقت كتابة هذا الدرس، تعلّم مناطق في الـ component يمكن للـ instances أن تضع فيها محتوى حرًّا دون فصل."],"further":[{"title":"Create and use variants","url":"https://help.figma.com/hc/en-us/articles/360056440594-Create-and-use-variants"},{"title":"Explore component properties","url":"https://help.figma.com/hc/en-us/articles/5579474826519-Explore-component-properties"},{"title":"The difference between slots, instance swaps, and variants","url":"https://help.figma.com/hc/en-us/articles/38741465279895-The-difference-between-slots-instance-swaps-and-variants"}],"quiz":[{"q":"<p>لزر Steady ثلاث variant properties: ‏Type ‏(Primary, Secondary, Ghost) وState ‏(Default, Pressed, Disabled) وSize ‏(Medium, Small). يريد زميلك إضافة “with icon” و&quot;without icon&quot; كـ variant property أخرى. كم variant سينتج عن ذلك، وما البديل؟</p>","options":[{"text":"36 variant. وخاصية boolean للأيقونة تُبقي العدد عند 18.","why":"صحيح. ‏3 × 3 × 2 = 18، وvariant property بقيمتين تضاعف العدد. أما الـ boolean فيُظهر طبقة الأيقونة أو يخفيها دون variants جديدة."},{"text":"20 variant. ولا يوجد بديل.","why":"الـ variant properties تتضاعف ولا تُجمع. والـ booleans موجودة تحديدًا للإظهار والإخفاء."},{"text":"18 variant. لأن Figma يدمج التخطيطات المكرّرة تلقائيًا.","why":"لا يدمج Figma الـ variants أبدًا. كل تركيبة variant منفصل عليك صيانته."},{"text":"36 variant. وخاصية instance swap تُبقي العدد عند 18.","why":"العدد صحيح، لكن الـ instance swap يختار أيّ أيقونة، لا هل تظهر. الظهور مهمّة الـ boolean."}],"answer":0},{"q":"<p>أيّ نوع من الخصائص يناسب اسم العادة في الـ component ‏Habit row؟</p>","options":[{"text":"variant property بقيمة لكل عادة.","why":"أسماء العادات محتوى غير محدود يكتبه المستخدم. الـ variants لمجموعة صغيرة ثابتة من النسخ المصمّمة."},{"text":"خاصية boolean.","why":"الـ booleans تُظهر الطبقة أو تخفيها فقط. لا يمكنها حمل محتوى نصي."},{"text":"خاصية text، ليمكن تعديل الاسم من لوحة الخصائص أو على لوحة العمل.","why":"صحيح. خاصية text تكشف النص فيستطيع الناس تغييره دون البحث في الطبقات."},{"text":"خاصية instance swap.","why":"الـ instance swap يختار component متداخلًا. الاسم نص عادي، لا component."}],"answer":2},{"q":"<p>متى يجب أن يكون الاختلاف variant بدل boolean؟</p>","options":[{"text":"حين يُستخدم في أكثر من ثلاث شاشات.","why":"عدد مرّات الاستخدام لا يحدّد نوع الخاصية. طبيعة التغيير هي التي تحدّده."},{"text":"حين يعيد الاختلاف تنسيق عدّة طبقات معًا، مثل حالة Pressed التي تغيّر التعبئة ولون التسمية والظل.","why":"صحيح. الـ booleans تبدّل ظهور طبقة واحدة فقط. أما التغييرات البصرية المنسّقة فتحتاج variant مصمّمًا."},{"text":"حين يطلب المطوّر enum.","why":"رأي المطوّر قيّم، لكن السبب التصميمي هو عدد الطبقات التي تتغيّر وكيفية تغيّرها."},{"text":"دائمًا، لأن الـ variants أحدث من الـ booleans.","why":"الـ variants ليست أحدث، واعتمادها افتراضيًا يسبّب انفجار الـ variants."}],"answer":1},{"q":"<p>يجب أن يحمل الـ component الخاص بلوحة New habit محتوى مختلفًا في مسارات مختلفة (نموذج، تأكيد، شبكة أيقونات). ما الأنسب وقت كتابة هذا الدرس؟</p>","options":[{"text":"variant لكل محتوى ممكن.","why":"كل مسار جديد سيحتاج variant جديدًا، وستكبر المجموعة بلا نهاية."},{"text":"فصل اللوحة في كل استخدام.","why":"اللوحات المفصولة يفوتها كل إصلاح مستقبلي لترويسة اللوحة ومقبضها والـ padding فيها."},{"text":"boolean لكل عنصر قد يظهر.","why":"الـ booleans لا تستطيع إلا إخفاء طبقات موجودة أصلًا، فستحمل اللوحة كل عنصر ممكن."},{"text":"slot لجسم اللوحة، فتحمل كل instance محتواها الخاص بينما يبقى إطار اللوحة مرتبطًا.","why":"صحيح. الـ slots موجودة لهذا بالضبط، أي منطقة محتوى مرنة داخل component مرتبط."}],"answer":3}],"exercise":{"kind":"order","items":["build-base","make-component","add-props","add-variants","style-variants","test-instance"],"title":"ابنِ component الزر بالترتيب الصحيح","prompt":"<p>تبني زر Steady: ‏Type وState كـ variant properties، إضافة إلى خاصية text للتسمية، وboolean لإظهار الأيقونة، وinstance swap لاختيار الأيقونة. رتّب الخطوات بالترتيب الذي يجنّبك إعادة العمل.</p>\n","hints":["لا يمكن إنشاء component property إلا على شيء هو component بالفعل.","الـ variants الجديدة تنسخ روابط الخصائص من الـ component الذي أُنشئت منه.","الـ frame الأساسي، ثم الـ component، ثم الخصائص، ثم الـ variants، ثم التنسيق، ثم الاختبار."],"explanation":"<p>ابدأ بـ <strong>frame مبني جيدًا بـ Auto layout</strong> فيه طبقتا Icon وLabel مسمّاتان، لأن كل ما يأتي بعده يرث بنيته. <strong>حوّله إلى component</strong>، ثم أضف <strong>خصائص text وboolean وinstance swap</strong> ما دام هناك variant واحد فقط تربطها به. بعد ذلك <strong>أضف الـ variants</strong> وسمِّ الـ variant properties ‏Type وState؛ فيرث كل variant جديد روابط تلك الخصائص. ثم <strong>أعِد تنسيق</strong> كل variant حسب نوعه وحالته. وأخيرًا <strong>اختبر instance</strong> بتبديل كل خاصية، بما في ذلك التسميات الطويلة وإخفاء الأيقونة، لتثبت أن لا شيء ينكسر قبل أن يستخدمه أحد غيرك.</p>\n","checkLabels":{},"itemText":{"build-base":"ابنِ الزر الأساسي الافتراضي كـ frame بـ Auto layout فيه طبقتا Icon وLabel مسمّاتان.","make-component":"حوّل الـ frame إلى main component.","add-props":"أضف خاصية text لـ Label، وboolean لـ Show icon، وinstance swap لـ Icon.","add-variants":"أضف variants وسمِّ الـ variant properties ‏Type وState بقيمها.","style-variants":"أعِد تنسيق كل variant: ألوان secondary وghost، وحالتا pressed وdisabled.","test-instance":"ضع instance وبدّل كل خاصية، مع تسمية طويلة وأيقونة مخفية، لتتأكّد أن لا شيء ينكسر."}},"words":622,"readMinutes":4}