web-design-mastery
> متى تُستعمل: "SchoolOS web UI: CSS layers, tokens, dark mode, RTL, HTMX, a11y. Trigger: CSS, template, component, layout, mobile. واجهة، قالب، الوضع الليلي، الجوال"
SKILL.md.claude/skills/web-design-mastery/SKILL.md
GitHubمتى تُستعمل: "SchoolOS web UI: CSS layers, tokens, dark mode, RTL, HTMX, a11y. Trigger: CSS, template, component, layout, mobile. واجهة، قالب، الوضع الليلي، الجوال"
معاييرُ الواجهة في SchoolOS
الغرض: أن تُبنى كلُّ صفحةٍ ومكوّنٍ بمصادر الحقيقة المركزيّة — رموزٌ لا قيم، ومكوّناتُ ui.py لا بنيةٌ باليد، ونمطُ تخطيطٍ مسمّى لا شبكةٌ محلّيّة — فتبقى الحرّاسُ خضراءَ والهويّةُ واحدة.
المرجعُ الأعلى CLAUDE.md (الأقسامُ عن الأنماط والبطاقات والتنبيهات والانتقال والقائمة والتخطيط)؛ هذه المهارةُ تفصّله ولا تخالفه. تحقّقٌ على main في 2026-09-28.
متى تُستعمل ومتى لا
- نعم: قالبٌ تحت
templates/، ملفٌّ تحتstatic/css/custom/أوstatic/js/، وسمٌ فيcore/templatetags/ui.py، لونٌ أو خطٌّ أو تباعد، صفحةٌ جديدة. - لا: قالبُ PDF (له إطارٌ مطبوعٌ مستقلّ)، ولا قرارُ دمجٍ أو نشر (
schoolos-flow).
الإجراء
- ابدأ من مرجع الهويّة المولَّد
.claude/rules/identity-reference.md(يُحمَّل تلقائياً حين تلمسstatic/أوtemplates/؛ وإلا اقرأه): رموزُ الألوان نهاراً وليلاً، وقاموسُ الأيقونات بمعانيها، وأنماطُ الصفحات السبعة — فلا تفتح/styleguide/(مطوّريّةٌ) ولا تخمّن لوناً أو أيقونة. مولَّدٌ من المصادر ويحرسهtests/test_identity_reference_fresh.py. - اختر نمطَ الصفحة قبل أن تكتبها:
{% block main_class %}{% page_layout "list" %}{% endblock %}— أحدُdashboard|hub|list|detail|form|sheet|report(أوcustomبسطرٍ في جدول الاستثناءات). صفحةٌ جديدةٌ بلا نمطٍ تُسقطtests/test_page_layouts.py. ←references/20-layouts-components.md - ابنِ من المكوّنات القائمة:
page_header،section_card،kpi/kpi_strip،callout(خمسة أنواع)،empty_state،field،filter_bar،action_tile،entity_card، و{% icon "…" %}. صنفٌ جديدٌ آخرُ الحلول. - الأنماطُ في ملفّ طبقتها: مكوّنٌ ←
20-components، شاشةٌ ←30..33-modules(آخرُها 33)، ليليٌّ ←40-themes، مساعدٌ ←50-utilities؛ ولا قاعدةَ خارج@layer. ←references/10-css-architecture.md - القيمُ رموز: لونٌ بدوره (
--text-*،--status-*-fg،--on-fill…)، تباعدٌvar(--sp-*)، تقوّسٌvar(--radius-*)، خطٌّ بـrem. ←references/00-tokens-theming.md - قِس على أربعة أجهزةٍ نهاراً وليلاً: 1366×768 و1920×1080 ولوحيّ (~768×1024) و375×812 — وما لم يُقَس يُقال «لم يُقَس». طريقةُ القياس على صفحةٍ محميّةٍ في
schoolos-preview-8500←03-measuring-protected-pages.md؛ ثمّ التحقّقُ البصريُّ بالدور (تداخل، معطَّلٌ بلا سبب، اقتطاع، مصفوفةُ الحالات) قبل إعلان «جاهز». ←references/50-responsive-mobile.mdوreferences/55-visual-verification.mdوإن طُلب أن تطابق صفحةٌ صفحةً قائمة فاتّبع إجراءَ «طبقَ الأصل» فيreferences/20-layouts-components.mdقبل البناء. - شغّل الحرّاس قبل الدفع (من شجرة عملك بأوامر
CLAUDE.md):tests/test_css_*.py،test_px_tokens،test_rtl_logical_properties،test_dark_parity،test_contrast_ratios،test_design_ratchet،test_a11y_ratchet،test_page_layouts. وقراءةُ الفاشل منها في مهارةschoolos-quality-guards.
تحديثاتُ الهويّة منذ 2026-09-28 (إلزاميّة)
- لا صفحةَ خارج المنصّة ولا في لسانٍ جديد (قرار المالك 2026-10-13): لا
target="_blank"ولاwindow.open(ولاhref="http(s)://"في القوالب وJS؛ الحارسtests/test_no_external_pages.py(الجديدُ ممنوع والقديمُ في خطّ أساسٍ يتناقص). - رأسُ الجدول ثابتٌ عند التمرير الرأسيّ (قرار المالك 2026-10-13): كلُّ جدولٍ بـ
{% for %}داخلtable-wrapيحملtable-wrap-scroll؛ الحارسtests/test_sticky_table_header.py. ويمرّر الجدولُ الطويلُ داخلَه لا الصفحة (خاناتُ95-checklist.mdالثلاث، W-20261009-019). - الانتقالُ: لا
transition: all؛ استعمل--q-transition-uiوخصائصَ صريحة، والاتّجاهُ بخصائص منطقيّة (41dff8110). - شعارُ المدرسة «ش» (D-404م): الوسمُ
{% school_logo "nav" %}منcore/school_logo.pyمصدرٌ واحدٌ للشاشة وPDF وExcel (الأصلstatic/icons/v3/icon-192.png). شعارُ الوزارة أُزيل ولا يعود؛ وسطرُ الانتماء للوزارة مخفيٌّ افتراضًا خلفMINISTRY_AFFILIATION_VISIBLE(core/ministry.py، الوسمministry_name). تغييرُ الأيقونات يرفعCACHE_NAMEفي عامل الخدمة. - الطباعةُ: ورقةٌ واحدة بـ
SINGLE_SHEET_BOOST، وخطّ Tajawal، وإطارٌ مطبوعٌ مركزيّ (W-057)؛ ولا تحديدَ.nav-innerبعرض 1280px. - لا صنفَ
text-xsفي القوالب (استعمل رموزَ الخطّ)، ونماذجُ الدخول هُجّرت. - ألوانُ الأجنحة من
core/dept_colors.py:WING_KEY_OF_ORDER(ترويسة الجناح وشريطه)، وأمّا لونُ الصفّ الدراسيّ (7 … 12) فمنفصلٌ: ستّةُ رموز--grade-7..12مطفأةٌ مع مرآتها فيcore/brand.py(W-20261013-016)، يُصبّ على تظليل صفّ الفصل 7/1 … 12/4 وشارته ولا يُخلط بلون جناح؛ وتدرّجُ الشعب داخل الصفّ بقرار المالك المنتظر. - أعمدةُ الجداول مرنةٌ تتكيّف مع محتواها شاشةً وPDF وإكسل (قرار المالك 2026-10-13: «مرنة مرنة»): لا عرضَ ثابتاً يقتطع النصّ ولا
ellipsisيخفي بيانة؛ لا عرضَ ثابتاً لعمود التسلسل والأسماءُ لا تنكسر؛ الحارسtests/test_flexible_table_columns.py، والتفصيلُ في.claude/rules/tables.md. - توسيطُ نصوص الجداول وترويستها (قرار المالك 2026-10-13، للقائم والمستقبليّ وبأثرٍ رجعيّ، شاشةً وPDF وإكسل): الخلايا والترويسةُ
text-align: centerعدا عمود الأسماء فيبقىstart؛ مركزيّاً لا نمطاً محلّيّاً. التفصيلُ في.claude/rules/tables.md. - حرّاسُ الهويّة
test_dead_classesوtest_design_ratchetوtest_tailwind_freezeتعمل فيprepush، ومرجعُ الهويّة المولَّد يُحمَّل مع الواجهة. - قاعدةٌ دائمة: كلُّ تعديلٍ أو إضافةٍ على الهويّة يحدّث هذه المهارةَ و
CHANGES.mdفي الطلب نفسه، وإلا عُدّ ناقصًا.
القواعد وأسبابها
- لا لونَ حرفيّاً في CSS ولا في القالب — الرموزُ تنقلب ليلاً والحرفُ لا ينقلب (
test_css_colours_are_tokens، وسقّاطةُ الهويّةhex_colour= 0). في القالب{% brand_color "MAROON" %}، ومرآتُهcore/brand.py. - نصٌّ فوق حشوٍ ثابتٍ
var(--on-fill)لا#fff؛ ونصٌّ على سطحٍ--text-*أو--status-*-fg. السبب: الأبيضُ يساوي السطحَ نهاراً مصادفةً ويُطفئ الترويسةَ ليلاً. - الذهبيُّ تمييزٌ لا نصّ (
--gold-markللأيقونة على العنّابيّ) — تباينُه على الفاتح 2.2 (test_identity_roles). - الليلُ برموزٍ تنقلب في
html.dark { --… }داخل40-themes.css، والوضعُ اختيارُ المستخدم وحدَه (زرّ +localStorage) لا تفضيلُ النظام. وخلفيّةٌ فاتحةٌ ليلاً ممنوعة — الأبيضُ للنصوص والحدود فقط. - الاتّجاهُ منطقيّ:
inset-inline-*،margin-inline-*،text-align: start— لاleft:/right:(test_rtl_logical_properties). - لا
?v=Nولاcollectstaticفي التطوير: الإنتاجُ يبصم الاسمَ بمحتواه والتطويرُ يخدم بـmax-age=0— حدِّث الصفحة وحسب (CLAUDE.md). - لا
onclickولا<script>بلاnonce: CSP بـnonceتُسقط المعالجاتِ المضمَّنة؛ السلوكُ بـdata-action/data-call(static/js/actions.js). وسكربتُ الصفحة داخل IIFE لأنّpage-nav.jsيعيد تشغيله. - لا
@container(ADR-0005 D3، مؤكَّدٌ بالقياس في ADR-0006)، ولا Tailwind جديد (test_tailwind_freeze)، ولا زرَّ طباعة صفحة (test_no_web_page_print_button)، ولا شريطٌ فرعيٌّ لقسم (قرارُ 2026-09-20). - الميزانيّاتُ من ملفّاتها الحيّة: CSS مصغَّرٌ ≤ 269KB (
tests/test_css_budget.py)، وخامٌ ≤ 470KB وJS ≤ 400KB و≤ 10 أوراقٍ حاجبة وLCP ≤ 2500 وINP ≤ 300 وCLS ≤ 0.1 (tests/web_vitals.py:BUDGET). التعليقُ العربيّ في CSS يُحسب في الخامّ (بايتان للحرف).
فخاخٌ حقيقيّة
- خطأ:
{% if request.htmx %}…{% else %}{% extends "base.html" %}{% endif %}—extendsيجب أن يكون أوّلَ وسمٍ فلا يُشرَط. الصواب: الـview تختار:core.htmx_utils.htmx_or_full(request, partial, full, ctx). - خطأ:
.data-tableو.card-headerو.card-qatarفي صفحةٍ جديدة. الصواب: الأوّلان غيرُ معرَّفين، والثالثُ «بنيةٌ باليد» تعدّها سقّاطةُ الهويّة؛ استعملsection_cardوtable-wrap. - خطأ: «النصُّ الخافت
#6b7280بتباين 4.63». الصواب:--text-mutedصار#58606d(6.35 على السطح)؛ اكتب الرمزَ لا القيمة. - خطأ: «Amiri للجداول على الويب». الصواب: الويب Tajawal (و
Tajawal Tashkeelللمشكول)؛ Amiri للـPDF وحدَه. - خطأ:
templates/base.html. الصواب: القالبُ الأساسtemplates/base/base.html. - خطأ: «mobile-first بـ
min-widthفقط». الصواب: المنصّةُ تكتب@media (max-width: 640px)للجوال وmin-width: 641px/1025pxللأوسع — اتبع الملفَّ الذي تعمل فيه، وضع قاعدةَ@mediaبعد القاعدة الأساسيّة (الأخيرةُ تغلب). - خطأ:
margin: 12pxأوfont-size: 14px. الصواب:var(--sp-3)وvar(--text-sm)/0.875rem— القيمةُ الحرفيّةُ التي تطابق درجةً ممنوعة (test_px_tokens). - خطأ: بطاقةٌ تمتدّ بطول النافذة وفيها فراغ. الصواب:
fill-grid is-fitللمحتوى المحدود؛ وقائمةٌ ضيّقةٌ طويلةٌ تُقسَّم أعمدةً بـchunk_for_gridفي الـview +.auto-grid. - خطأ: ميزانيّة «Dashboard < 800KB» و«INP < 200ms». الصواب: تلك من كتاب؛ أرقامُ المشروع أعلاه من ملفّاتها.
المراجع
| الملف | متى تقرأه |
|---|---|
references/00-tokens-theming.md |
قبل اختيار أيّ لونٍ أو خطٍّ أو تباعدٍ أو ظلّ، أو عند عملٍ ليليّ |
references/10-css-architecture.md |
قبل كتابة CSS: الملفّاتُ والطبقاتُ والحرّاسُ والميزانيّات |
references/20-layouts-components.md |
عند بناء صفحةٍ أو بطاقةٍ أو تنبيهٍ أو أيقونةٍ أو قائمة |
references/30-htmx-js.md |
عند HTMX أو JS أو تنقّلٍ أو تصديرٍ من الواجهة |
references/40-accessibility.md |
عند نموذجٍ أو حوارٍ أو جدولٍ أو تباينٍ أو تركيز |
references/50-responsive-mobile.md |
عند الجوال واللوحيّ و«بلا تمرير» والمنطقة الآمنة |
references/55-visual-verification.md |
قبل إعلان «جاهزٌ للمعاينة» على عملٍ يلمس الواجهة: الأجهزة والتداخل والحالات والأدوار |
references/60-typography.md |
عند الخطّ والأحجام والمسافات السطريّة والنصّ المختلط |
references/70-performance.md |
عند صورٍ أو خطوطٍ أو سكربتاتٍ أو عامل خدمة أو ميزانيّة |
references/80-print-and-export.md |
حين يتعلّق الطلبُ بالطباعة أو التصدير من الواجهة |
references/90-book-principles.md |
لمبادئ الكتب العشرة بعد مواءمتها مع المشروع |
references/95-checklist.md |
قائمةُ مراجعةٍ قبل الدفع |
references/99-test-cases.md |
لاختبار تفعيل المهارة وجودة جوابها |