Files
code-crispies/lessons/ar/flexbox.json
Michael Czechowski c560676544 feat: implement #4 — replace answer-revealing validation messages with pedagogical hints
Rewrite ~120 validation error messages across 17 English lesson modules
and their localized variants (ar, de, es, pl, uk) to use concept questions,
property hints, and directional nudges instead of revealing the exact
CSS property-value answers.

Priority modules (flexbox, box-model, colors, positioning) fully rewritten.
All remaining CSS modules updated. Only message strings changed — no
validation logic modifications.
2026-03-28 19:40:28 +01:00

136 lines
9.7 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"$schema": "../../schemas/code-crispies-module-schema.json",
"id": "flexbox",
"title": "CSS Flexbox",
"description": "أتقن نموذج تخطيط الصندوق المرن للتصاميم المتجاوبة الحديثة",
"difficulty": "intermediate",
"lessons": [
{
"id": "flexbox-1",
"title": "Container",
"description": "قبل flexbox، كانت حتى التخطيطات البسيطة تتطلب floats أو حيل التموضع أو تخطيطات الجداول. ثورة Flexbox (تخطيط الصندوق المرن) في CSS من خلال توفير نظام تخطيط أحادي البعد مصمم خصيصاً لتوزيع المساحة ومحاذاة المحتوى.<br><br><strong>كيف يعمل:</strong> عندما تضبط <kbd>display: flex</kbd> على عنصر، يصبح <em>حاوية flex</em>. أبناؤه المباشرون يصبحون تلقائياً <em>عناصر flex</em> تتدفق على طول المحور الرئيسي (أفقياً بشكل افتراضي). هذه الخاصية الواحدة تحول العناصر الكتلية المتراصة إلى صف أفقي.<br><br><strong>المحوران:</strong><br>• <em>المحور الرئيسي</em> الاتجاه الأساسي لتدفق العناصر (row = يسار→يمين)<br>• <em>المحور المتقاطع</em> عمودي على الرئيسي (row = أعلى→أسفل)<br><br><pre>.nav {\n display: flex;\n}</pre>",
"task": "قائمة التنقل هذه تتراص عمودياً. أضف <kbd>display: flex</kbd> لترتيب الروابط أفقياً.",
"previewHTML": "<nav class=\"nav\"><a href=\"#\">Home</a><a href=\"#\">Products</a><a href=\"#\">About</a><a href=\"#\">Contact</a></nav>",
"previewBaseCSS": "body { font-family: system-ui, sans-serif; margin: 0; } .nav { background: #1a1a2e; padding: 1rem; } .nav a { color: white; text-decoration: none; padding: 8px 1rem; border-radius: 4px; } .nav a:hover { background: rgba(255,255,255,0.1); }",
"sandboxCSS": "",
"codePrefix": ".nav {\n ",
"initialCode": "",
"codeSuffix": "\n}",
"solution": "display: flex;",
"previewContainer": "preview-area",
"validations": [
{
"type": "property_value",
"value": { "property": "display", "expected": "flex" },
"message": "ما قيمة display التي تحوّل العنصر إلى حاوية صندوق مرن؟"
}
]
},
{
"id": "flexbox-2",
"title": "Gap",
"description": "خاصية <kbd>gap</kbd> تضيف تباعداً متسقاً بين عناصر flex بدون الحاجة إلى الهوامش. تُنشئ مساحة فقط بين العناصر، وليس على الحواف.",
"task": "أضف <kbd>gap: 1rem</kbd> لتوزيع روابط التنقل بالتساوي.",
"previewHTML": "<nav class=\"nav\"><a href=\"#\">Home</a><a href=\"#\">Products</a><a href=\"#\">About</a><a href=\"#\">Contact</a></nav>",
"previewBaseCSS": "body { font-family: system-ui, sans-serif; margin: 0; } .nav { background: #1a1a2e; padding: 1rem; display: flex; } .nav a { color: white; text-decoration: none; padding: 8px 1rem; border-radius: 4px; background: rgba(255,255,255,0.1); }",
"sandboxCSS": "",
"codePrefix": ".nav {\n ",
"initialCode": "",
"codeSuffix": "\n}",
"solution": "gap: 1rem;",
"previewContainer": "preview-area",
"validations": [
{
"type": "property_value",
"value": { "property": "gap", "expected": "1rem" },
"message": "ما الخاصية التي تُنشئ تباعداً بين عناصر flex بدون استخدام الهوامش؟"
}
]
},
{
"id": "flexbox-3",
"title": "Justify Content",
"description": "<kbd>justify-content</kbd> يوزع العناصر على طول المحور الرئيسي. القيم الشائعة:<br>• <kbd>flex-start</kbd> تجميع في البداية<br>• <kbd>flex-end</kbd> تجميع في النهاية<br>• <kbd>center</kbd> توسيط العناصر<br>• <kbd>space-between</kbd> مسافة متساوية بين العناصر<br>• <kbd>space-around</kbd> مسافة متساوية حول العناصر",
"task": "ادفع زر \"Login\" إلى اليمين بضبط <kbd>justify-content: space-between</kbd> على التنقل.",
"previewHTML": "<nav class=\"nav\"><div class=\"links\"><a href=\"#\">Home</a><a href=\"#\">Products</a><a href=\"#\">About</a></div><a href=\"#\" class=\"login\">Login</a></nav>",
"previewBaseCSS": "body { font-family: system-ui, sans-serif; margin: 0; } .nav { background: #1a1a2e; padding: 1rem; display: flex; } .links { display: flex; gap: 8px; } .nav a { color: white; text-decoration: none; padding: 8px 1rem; border-radius: 4px; } .nav a:hover { background: rgba(255,255,255,0.1); } .login { background: steelblue; }",
"sandboxCSS": "",
"codePrefix": ".nav {\n ",
"initialCode": "",
"codeSuffix": "\n}",
"solution": "justify-content: space-between;",
"previewContainer": "preview-area",
"validations": [
{
"type": "property_value",
"value": { "property": "justify-content", "expected": "space-between" },
"message": "ما قيمة <kbd>justify-content</kbd> التي تدفع العنصر الأول والأخير إلى الحواف المتقابلة؟"
}
]
},
{
"id": "flexbox-4",
"title": "Align Items",
"description": "<kbd>align-items</kbd> يتحكم في المحاذاة على المحور المتقاطع (عمودياً عندما يكون flex-direction هو row). القيم تشمل:<br>• <kbd>stretch</kbd> تمديد للملء (افتراضي)<br>• <kbd>flex-start</kbd> محاذاة للأعلى<br>• <kbd>flex-end</kbd> محاذاة للأسفل<br>• <kbd>center</kbd> توسيط عمودي",
"task": "الشعار وروابط التنقل لها ارتفاعات مختلفة. وسّطها عمودياً باستخدام <kbd>align-items: center</kbd>.",
"previewHTML": "<header class=\"header\"><div class=\"logo\">ACME</div><nav><a href=\"#\">Products</a><a href=\"#\">Pricing</a><a href=\"#\">Docs</a></nav></header>",
"previewBaseCSS": "body { font-family: system-ui, sans-serif; margin: 0; } .header { background: white; padding: 1rem 2rem; display: flex; justify-content: space-between; border-bottom: 1px solid #eee; } .logo { font-size: 1.5rem; font-weight: bold; color: steelblue; } nav { display: flex; gap: 1rem; } nav a { color: #333; text-decoration: none; font-size: 0.9rem; }",
"sandboxCSS": "",
"codePrefix": ".header {\n ",
"initialCode": "",
"codeSuffix": "\n}",
"solution": "align-items: center;",
"previewContainer": "preview-area",
"validations": [
{
"type": "property_value",
"value": { "property": "align-items", "expected": "center" },
"message": "ما الخاصية التي تُحاذي عناصر flex على طول المحور المتقاطع؟"
}
]
},
{
"id": "flexbox-5",
"title": "Flex Wrap",
"description": "بشكل افتراضي، تنضغط عناصر flex في سطر واحد. <kbd>flex-wrap: wrap</kbd> يسمح للعناصر بالتدفق إلى أسطر متعددة عندما تنفد المساحة.",
"task": "هذه البطاقات تتجاوز الحاوية. أضف <kbd>flex-wrap: wrap</kbd> للسماح لها بالانتقال إلى صفوف جديدة.",
"previewHTML": "<div class=\"cards\"><article class=\"card\">Card 1</article><article class=\"card\">Card 2</article><article class=\"card\">Card 3</article><article class=\"card\">Card 4</article><article class=\"card\">Card 5</article><article class=\"card\">Card 6</article></div>",
"previewBaseCSS": "body { font-family: system-ui, sans-serif; padding: 1rem; background: #f5f5f5; } .cards { display: flex; gap: 1rem; } .card { background: white; padding: 2rem; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); min-width: 120px; text-align: center; }",
"sandboxCSS": "",
"codePrefix": ".cards {\n ",
"initialCode": "",
"codeSuffix": "\n}",
"solution": "flex-wrap: wrap;",
"previewContainer": "preview-area",
"validations": [
{
"type": "property_value",
"value": { "property": "flex-wrap", "expected": "wrap" },
"message": "ما الخاصية التي تسمح لعناصر flex بالتدفق إلى أسطر متعددة؟"
}
]
},
{
"id": "flexbox-6",
"title": "Flex Grow",
"description": "خاصية <kbd>flex</kbd> على العناصر تتحكم في كيفية نموها وانكماشها. <kbd>flex: 1</kbd> يجعل العنصر ينمو لملء المساحة المتاحة. عناصر متعددة مع <kbd>flex: 1</kbd> تتشارك المساحة بالتساوي.",
"task": "اجعل حقل البحث يتوسع لملء المساحة المتاحة بضبط <kbd>flex: 1</kbd> على <kbd>.search</kbd>.",
"previewHTML": "<div class=\"toolbar\"><input class=\"search\" type=\"text\" placeholder=\"Search...\"><button class=\"btn\">Search</button><button class=\"btn\">Filters</button></div>",
"previewBaseCSS": "body { font-family: system-ui, sans-serif; padding: 1rem; } .toolbar { display: flex; gap: 8px; padding: 1rem; background: #f5f5f5; border-radius: 8px; } .search { padding: 8px 1rem; border: 1px solid #ddd; border-radius: 4px; font-size: 1rem; } .btn { padding: 8px 1rem; background: steelblue; color: white; border: none; border-radius: 4px; cursor: pointer; }",
"sandboxCSS": "",
"codePrefix": ".search {\n ",
"initialCode": "",
"codeSuffix": "\n}",
"solution": "flex: 1;",
"previewContainer": "preview-area",
"validations": [
{
"type": "property_value",
"value": { "property": "flex", "expected": "1" },
"message": "ما الخاصية التي تجعل عنصر flex ينمو لملء المساحة المتبقية؟"
}
]
}
]
}