هذه الصفحة مترجمة من الإنجليزية. اقرأ الصفحة الإنجليزية
الحالة: منفذة في crates/zeyn/assets/zeyn.css.
تقرأ مجموعة واجهة المستخدم الافتراضية كل لون وخط وحجم ونصف قطر زاوية من خصائص CSS المخصصة في :root. تغيّر المؤسسة المظهر بتجاوز عدد قليل منها، ولا تحتاج إلى تعديل zeyn.css ولا إلى كتابة محددات.
1. كيف تُطبَّق السمة
يقدّم الخادم zeyn.css أولاً، ثم ورقة أنماط إضافية فيها تجاوزات الرموز (tokens) إن كان للتطبيق ورقة كهذه. يحتوي ملف التجاوز على كتل :root فقط:
:root {
--z-brand: #7a2448;
--z-font: "Source Sans 3", "Segoe UI", system-ui, sans-serif;
--z-radius: 8px;
--z-density: 0.75;
}قواعد ملف التجاوز:
- يجب تقديمه من أصل التطبيق نفسه. سياسة أمان المحتوى (Content Security Policy) هي
style-src 'self'، لذلك تُحجب كتل<style>المضمنة وأوراق الأنماط الصادرة عن أطراف خارجية. - يجب أن تكون الخطوط مثبتة مسبقاً على أجهزة المستخدمين أو أن تُقدَّم من أصل التطبيق. المجموعة نفسها لا تحمّل أي خطوط ويب.
- حمّله بعد
zeyn.css، حتى تفوز المحددات المتساوية بحسب الترتيب. - اضبط الرموز الأساسية في القسم 2. تتبعها الرموز المشتقة في القسم 3 تلقائياً. لا تتجاوز رمزاً مشتقاً إلا إذا كانت القيمة المحسوبة لا تناسب علامتك التجارية.
السمات الفاتحة والداكنة وسمات التطبيق
لكل تطبيق منتقي سمات في القائمة، بجوار منتقي اللغة. يعرض النظام (يتبع prefers-color-scheme) والفاتحة والداكنة وأي سمة يعرّفها التطبيق:
App::new("Billing")
.theme(Theme::new().brand("#7a2448").radius(6))
.themes([
Theme::light(),
Theme::dark(),
Theme::named("sand", [("--z-bg", "#f5f1ea"), ("--z-surface", "#fffdf8")]).label(t!("theme.sand")),
])
.default_theme("system")App::themeهو مظهر المؤسسة، ويُطبَّق تحت كل سمة.App::themesيسرد ما يستطيع المستخدمون اختياره. وبدونه تكون القائمة الفاتحة والداكنة. يُعرض خيار النظام عندما تكون السمتان في القائمة.Theme::named(...)يبني على السمة الفاتحة، و.dark_base()يبنيها على الداكنة.App::default_themeهي سمة المستخدمين الذين لم يختاروا. القيمةsystemما لم تُضبط.App::theme_picker(false)يخفي المنتقي، ويحصل الجميع على السمة الافتراضية.- سمة واحدة تقفل التطبيق:
.themes([Theme::named("acme", tokens)])أو.theme(Theme::dark()).
تُفحص الرموز عند بدء التطبيق. يبلّغ App::check (وبالتالي router وserve) عن أسماء الرموز غير المعروفة، والقيم التي قد تخرج من تصريحها (; والأقواس المعقوفة و\ و< و> وurl()، وأسماء السمات غير الصالحة، والسمة الافتراضية غير المعروفة، وكل زوج ألوان في القسم 5 تدفعه سمة إلى ما دون WCAG 2.2 AA. لا يمكن فحص التباين إلا لقيم #rgb و#rrggbb؛ أما صيغ الألوان الأخرى فيُوثق بها.
تُقدَّم كل السمات في ورقة أنماط واحدة، /_zeyn/theme.css، تُبنى مرة واحدة عند بدء التشغيل وتُحمَّل بعد أوراق أنماط المجموعة. يُخزَّن الاختيار في ملف تعريف الارتباط zeyn_theme، وللمستخدم المسجل الدخول في تطبيق له مخزن عروض (App::datagrid_views) يُخزَّن في ذلك المخزن أيضاً، فيتبع المستخدم إلى جهاز جديد. يعرض الخادم السمة على <html>، فيكون الرسم الأول صحيحاً من البداية ولا حاجة إلى سكربت مضمن:
| الترميز | النتيجة |
|---|---|
<html> | النظام: يتبع prefers-color-scheme |
<html data-theme="light"> | فاتحة دائماً |
<html data-theme="dark"> | داكنة دائماً |
<html data-theme="light" data-zeyn-theme="sand"> | سمة التطبيق sand، على السمة الفاتحة |
تغيير السمة في المنتقي يغيّر هذه الخصائص ووسم color-scheme فقط، ثم يستدعي POST /_zeyn/theme. لا يُعاد تحميل أي شيء.
لإعطاء السمة الداكنة قيمها الخاصة في ملف تجاوز مكتوب يدوياً، كرر المحددات التي تستخدمها المجموعة:
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) { --z-bg: #0e1012; }
}
:root[data-theme="dark"] { --z-bg: #0e1012; }الكثافة
--z-density يضبط مقياس وحدة التباعد. القيمة 1 عادية و0.75 مضغوطة. <html data-density="compact"> يضبط 0.75 دون ورقة أنماط. لا تصغر عناصر التحكم وصفوف الشبكة عن 24 بكسل أبداً، فيظل الوضع المضغوط ملتزماً بحجم الهدف في WCAG 2.2.
ارتفاع صف الشبكة الافتراضية (virtual grid) يحدده الخادم (Paging::virtual_rows(px)، و32 بكسل افتراضياً) لأن بيئة التشغيل تحسب مواضع التمرير منه. الكثافة لا تغيّره.
2. الرموز الأساسية
هذه هي الرموز التي يُتوقع أن تضبطها المؤسسة.
| الرمز | الغرض | فاتح | داكن |
|---|---|---|---|
--z-brand | لون العلامة التجارية الوحيد. الأزرار الأساسية وشريط اسم التطبيق وعنصر القائمة الحالي والصف المركَّز وحلقة التركيز | #0f6674 | القيمة نفسها؛ انظر --z-accent |
--z-on-brand | النص على سطح --z-brand الصلب | #ffffff | #ffffff |
--z-font | مجموعة خطوط الواجهة | "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, "Noto Sans", sans-serif | نفسها |
--z-font-mono | الشيفرة وأمثلة API | ui-monospace, "Cascadia Mono", "SF Mono", "Segoe UI Mono", Menlo, Consolas, monospace | نفسها |
--z-font-size | نص المتن | 0.875rem (14 بكسل) | نفسه |
--z-font-size-sm | خلايا الشبكة والتسميات والمرشحات | 0.8125rem (13 بكسل) | نفسه |
--z-font-size-xs | رؤوس الأعمدة وعناوين مجموعات القائمة ومعلومات الصفحة | 0.75rem (12 بكسل) | نفسه |
--z-radius | نصف قطر الزاوية الأساسي، من 0 إلى 12 بكسل. كل مكوّن يتدرج منه | 4px | نفسه |
--z-density | مضاعف التباعد، 1 عادي، 0.75 مضغوط | 1 | نفسه |
--z-bg | خلفية الصفحة خلف اللوحات | #f4f5f6 | #121416 |
--z-surface | اللوحات والشبكات والنوافذ وحقول الإدخال | #ffffff | #1a1d20 |
--z-surface-2 | رأس الشبكة والصفوف المخططة وتذييل النافذة وحقول الإدخال للقراءة فقط | #f7f8f9 | #202326 |
--z-hover | خلفية التمرير للصفوف وعناصر القائمة والأزرار | #eceef1 | #2a2e33 |
--z-border | الفواصل وحدود اللوحات | #dcdfe3 | #33383e |
--z-border-strong | حدود حقول الإدخال والأزرار وخط الرأس. يجب أن يبلغ 3:1 مقابل --z-surface | #7d848d | #7a818a |
--z-text | نص المتن والقيم | #1a1d21 | #e4e6e9 |
--z-text-muted | التسميات والرؤوس والنص الثانوي. يجب أن يبلغ 4.5:1 مقابل --z-surface-2 | #5b626b | #a2a9b1 |
--z-danger | الأخطاء وعلامات الحقول المطلوبة وصفوف الخطر | #b3261e | #f28b82 |
--z-warning | صفوف التحذير | #8a5300 | #e6b45a |
--z-success | صفوف النجاح | #1e6b3a | #6fcf8f |
--z-info | إشعارات المعلومات | #2b5d8a | #8ab8e6 |
3. الرموز المشتقة
تُحسب من الرموز الأساسية بـ color-mix() وصيغة الألوان النسبية. وتتحدث من تلقاء نفسها عندما يتغير رمز أساسي.
| الرمز | الغرض | فاتح | داكن |
|---|---|---|---|
--z-accent | لون العلامة المستخدم نصاً أو خطاً رفيعاً على سطح: الروابط وعنصر القائمة الحالي وشريط الصف المركَّز | var(--z-brand) | oklch(from var(--z-brand) 0.8 c h)، أي درجة لون العلامة بدرجة إضاءة ثابتة. المتصفحات التي لا تدعم صيغة الألوان النسبية تحصل على color-mix(in oklab, var(--z-brand) 45%, #fff) |
--z-primary | تعبئة الزر الأساسي | var(--z-brand) | var(--z-accent) |
--z-on-primary | نص الزر الأساسي | var(--z-on-brand) | #121416 |
--z-primary-hover | الزر الأساسي عند التمرير | العلامة 86% ممزوجة بالأسود | اللون المميز 84% ممزوج بالأبيض |
--z-primary-active | الزر الأساسي عند الضغط | العلامة 74% ممزوجة بالأسود | اللون المميز 70% ممزوج بالأبيض |
--z-brand-subtle | تدرج خفيف خلف عنصر القائمة الحالي وصف الشبكة المركَّز | اللون المميز بنسبة --z-tint فوق --z-surface | الصيغة نفسها |
--z-focus | حلقة التركيز | var(--z-accent) | var(--z-accent) |
--z-danger-subtle, --z-warning-subtle, --z-success-subtle, --z-info-subtle | خلفيات الصفوف والرسائل | لون الحالة بنسبة --z-tint فوق --z-surface | الصيغة نفسها |
--z-tint | قوة التدرجات الخفيفة | 9% | 20% |
--z-space | وحدة التباعد | calc(4px * var(--z-density)) | نفسها |
--z-control | ارتفاع الأزرار وحقول الإدخال | max(24px, 8 * --z-space) (32 بكسل) | نفسه |
--z-row | ارتفاع صف الشبكة للشبكات المقسمة إلى صفحات واللانهائية | max(24px, 8 * --z-space) (32 بكسل) | نفسه |
--z-gap | المسافة بين أقسام الشاشة | 3 * --z-space (12 بكسل) | نفسها |
--z-radius-sm, --z-radius-lg | الأجزاء الصغيرة (المرشحات والشيفرة) والنوافذ | 0.75x و1.5x من --z-radius | نفسها |
--z-shadow-2 | للنوافذ والإشعارات فقط. صفوف الشبكة لا تحصل على ظل أبداً | ظل ناعم بطبقتين | أغمق |
--z-backdrop | خلف النافذة المشروطة (modal) | rgb(20 24 28 / 40%) | rgb(0 0 0 / 60%) |
--z-dir | إشارة اتجاه القراءة، للإزاحات التي ليس لها شكل منطقي (الظلال الداخلية التي تميز جهة البداية أو النهاية، وتحويلات الانزلاق): calc(2px * var(--z-dir)) | 1، و-1 تحت dir="rtl" | نفسها |
رموز لكل عنصر يضبطها ترميز الخادم: --z-width (عرض النافذة) و--z-flex (حصة العمود) و--z-row-height (ارتفاع صف الشبكة الافتراضية)، ولمكتبة المكونات --z-stack-gap و--z-split و--z-progress و--z-columns و--z-level و--z-pop-x / --z-pop-y (موضع النافذة المنبثقة).
ألوان سلاسل المخططات هي --z-chart-1 إلى --z-chart-6 في components.css، بقيم أفتح في السمة الداكنة. كل منها يبلغ 3:1 مقابل --z-surface. تجاوزها كأي رمز أساسي.
4. اختيار لون العلامة التجارية
- يحمل
--z-brandنصاً أبيض في السمة الفاتحة (الأزرار وشريط اسم التطبيق). اختر لوناً يبلغ 4.5:1 على الأقل مقابل--z-on-brand. معظم ألوان العلامات المتوسطة إلى الداكنة تنجح. أما للون علامة فاتح مثل الأصفر، فاضبط--z-on-brandأيضاً على لون داكن. - في السمة الداكنة تفتّح المجموعة لون العلامة للنصوص والحلقات والأزرار الأساسية، وتبقي لون العلامة الصلب لشريط اسم التطبيق. فتبدو العلامة المختلفة مقصودة في السمتين دون لون ثانٍ.
- أبقِ ألوان الحالة متمايزة عن العلامة. علامة حمراء بجوار صفوف أخطاء حمراء تجعل الأخطاء أصعب في الملاحظة؛ في هذه الحالة أزِح
--z-dangerنحو درجة حمراء مختلفة أو أبعد العلامة عن الشبكات بتجاوز--z-brand-subtle. - افحص ألوانك مستعيناً بجدول القسم 5 هدفاً. أي زوج دون العتبة يفشل في WCAG 2.2 AA.
5. التباين المتحقق منه
قيس في Chromium على تطبيق المثال العامل: حُلَّ كل رمز إلى قيمة sRGB المعروضة (بما في ذلك color-mix() والألوان النسبية)، ثم حُسبت نسبة التباين وفق WCAG 2.x. العتبات: 4.5:1 للنص، و3:1 لحدود مكونات الواجهة ومؤشرات التركيز.
| الزوج | فاتح | داكن | المطلوب |
|---|---|---|---|
--z-text على --z-bg | 15.49 | 14.77 | 4.5 |
--z-text على --z-surface | 16.91 | 13.54 | 4.5 |
--z-text على --z-surface-2 | 15.91 | 12.63 | 4.5 |
--z-text على --z-hover | 14.55 | 10.93 | 4.5 |
--z-text على --z-brand-subtle (الصف المركَّز) | 14.79 | 9.27 | 4.5 |
--z-text على --z-danger-subtle | 14.73 | 9.76 | 4.5 |
--z-text على --z-warning-subtle | 14.82 | 9.31 | 4.5 |
--z-text على --z-success-subtle | 14.76 | 9.33 | 4.5 |
--z-text-muted على --z-bg | 5.65 | 7.78 | 4.5 |
--z-text-muted على --z-surface | 6.17 | 7.13 | 4.5 |
--z-text-muted على --z-surface-2 (الرؤوس) | 5.80 | 6.65 | 4.5 |
--z-text-muted على --z-hover | 5.31 | 5.76 | 4.5 |
--z-text-muted على --z-danger-subtle (صف خافت) | 5.37 | 5.14 | 4.5 |
--z-text-muted على --z-warning-subtle | 5.41 | 4.90 | 4.5 |
--z-accent على --z-surface (الروابط) | 6.62 | 9.33 | 4.5 |
--z-accent على --z-bg | 6.06 | 10.18 | 4.5 |
--z-accent على --z-brand-subtle (عنصر القائمة الحالي) | 5.79 | 6.39 | 4.5 |
--z-on-primary على --z-primary | 6.62 | 10.18 | 4.5 |
--z-on-primary على --z-primary-hover | 8.82 | 11.26 | 4.5 |
--z-on-primary على --z-primary-active | 11.12 | 12.26 | 4.5 |
--z-on-brand على --z-brand (شريط اسم التطبيق) | 6.62 | 6.62 | 4.5 |
--z-danger على --z-surface (أخطاء الحقول) | 6.54 | 7.09 | 4.5 |
--z-danger على --z-danger-subtle | 5.69 | 5.11 | 4.5 |
--z-warning على --z-surface | 6.33 | 8.90 | 4.5 |
--z-warning على --z-warning-subtle | 5.55 | 6.12 | 4.5 |
--z-success على --z-surface | 6.52 | 8.87 | 4.5 |
--z-info على --z-surface | 6.92 | 8.13 | 4.5 |
--z-focus على --z-surface | 6.62 | 9.33 | 3 |
--z-focus على --z-bg | 6.06 | 10.18 | 3 |
--z-focus على --z-brand-subtle | 5.79 | 6.39 | 3 |
--z-border-strong على --z-surface (حد حقل الإدخال) | 3.78 | 4.30 | 3 |
--z-border-strong على --z-surface-2 | 3.55 | 4.01 | 3 |
--z-border زخرفي (فواصل بين عناصر لها نص أصلاً) ولا يُلزَم بنسبة 3:1.
6. سلوك إتاحة آخر
- كل عنصر تفاعلي يعرض حلقة
:focus-visibleبسماكة 2 بكسل بلون--z-focus. ترسم صفوف الشبكة الحلقة داخل الصف حتى لا تُقصّ بحاوية التمرير. - الأزرار وحقول الإدخال ورؤوس الفرز ومربعات المرشحات وأزرار الترقيم وزر إغلاق النافذة لا تقل عن 24 × 24 بكسل عند أي كثافة.
prefers-reduced-motion: reduceيزيل دخول الإشعارات المتحرك وكل الانتقالات.- في وضع
forced-colorsتستخدم الأيقوناتCanvasText، ويستخدم الزر الأساسي والصف المركَّزHighlight، وأي حالة تعتمد على تدرجات الخلفية (عنصر القائمة الحالي وحالة الصف) تحصل على إطار أو حد بدلاً منها.