यह पृष्ठ अंग्रेज़ी से अनुवादित है। अंग्रेज़ी पृष्ठ पढ़ें
स्थिति: crates/zeyn/assets/zeyn.css में लागू।
डिफ़ॉल्ट UI किट हर रंग, फ़ॉन्ट, आकार और त्रिज्या :root पर CSS custom properties से पढ़ती है। संगठन उनमें से कुछ को ओवरराइड करके रूप बदलता है। उसे कभी zeyn.css संपादित करने या सेलेक्टर लिखने की ज़रूरत नहीं।
1. थीम कैसे लागू होती है
सर्वर पहले zeyn.css परोसता है और फिर, जब ऐप के पास हो, टोकन ओवरराइड वाली एक अतिरिक्त स्टाइलशीट। ओवरराइड फ़ाइल में केवल :root ब्लॉक होते हैं:
:root {
--z-brand: #7a2448;
--z-font: "Source Sans 3", "Segoe UI", system-ui, sans-serif;
--z-radius: 8px;
--z-density: 0.75;
}ओवरराइड फ़ाइल के नियम:
- इसे ऐप के अपने origin से परोसा जाना चाहिए। Content Security Policy
style-src 'self'है, इसलिए इनलाइन<style>ब्लॉक और तीसरे पक्ष की स्टाइलशीट अवरुद्ध हैं। - फ़ॉन्ट उपयोगकर्ताओं की मशीनों पर पहले से इंस्टॉल होने चाहिए या ऐप के origin से परोसे जाने चाहिए। किट खुद कोई वेब फ़ॉन्ट लोड नहीं करती।
- इसे
zeyn.cssके बाद लोड करें, ताकि समान सेलेक्टर में क्रम से जीत तय हो। - खंड 2 के आधार टोकन सेट करें। खंड 3 के व्युत्पन्न टोकन अपने आप साथ चलते हैं। व्युत्पन्न टोकन केवल तब ओवरराइड करें जब गणना किया मान आपके ब्रांड के लिए काम न करे।
लाइट, डार्क और ऐप थीम
हर ऐप के मेनू में भाषा चयनकर्ता के पास थीम चयनकर्ता है। यह System (prefers-color-scheme का पालन करता है), Light, Dark और ऐप द्वारा परिभाषित कोई भी थीम देता है:
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सूचीबद्ध करता है कि उपयोगकर्ता क्या चुन सकते हैं। इसके बिना सूची Light और Dark है। जब दोनों सूची में हों तब System दिया जाता है।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> | System: prefers-color-scheme का पालन करता है |
<html data-theme="light"> | हमेशा लाइट |
<html data-theme="dark"> | हमेशा डार्क |
<html data-theme="light" data-zeyn-theme="sand"> | ऐप थीम sand, लाइट थीम पर |
चयनकर्ता में थीम बदलना केवल ये एट्रिब्यूट और color-scheme meta बदलता है, फिर 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 px से छोटी नहीं होतीं, इसलिए कॉम्पैक्ट मोड भी WCAG 2.2 लक्ष्य आकार पूरा करता है।
वर्चुअल ग्रिड की पंक्ति ऊँचाई सर्वर तय करता है (Paging::virtual_rows(px), डिफ़ॉल्ट 32 px) क्योंकि रनटाइम स्क्रॉल स्थितियाँ उसी से निकालता है। घनत्व इसे नहीं बदलता।
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 px) | वही |
--z-font-size-sm | ग्रिड सेल, लेबल, फ़िल्टर | 0.8125rem (13 px) | वही |
--z-font-size-xs | कॉलम शीर्षक, मेनू समूह शीर्षक, पृष्ठ जानकारी | 0.75rem (12 px) | वही |
--z-radius | आधार कोने की त्रिज्या, 0 से 12 px। हर कंपोनेंट इसी से स्केल होता है | 4px | वही |
--z-density | स्पेसिंग गुणक, 1 सामान्य, 0.75 कॉम्पैक्ट | 1 | वही |
--z-bg | पैनल के पीछे पृष्ठ की पृष्ठभूमि | #f4f5f6 | #121416 |
--z-surface | पैनल, ग्रिड, Window, इनपुट | #ffffff | #1a1d20 |
--z-surface-2 | ग्रिड शीर्षक, ज़ेब्रा पंक्तियाँ, Window फ़ुटर, केवल पढ़ने योग्य इनपुट | #f7f8f9 | #202326 |
--z-hover | पंक्तियों, मेनू आइटम, बटन के लिए होवर पृष्ठभूमि | #eceef1 | #2a2e33 |
--z-border | विभाजक और पैनल की रूपरेखा | #dcdfe3 | #33383e |
--z-border-strong | इनपुट और बटन की रूपरेखा, शीर्षक रेखा। --z-surface के विरुद्ध 3:1 तक पहुँचना चाहिए | #7d848d | #7a818a |
--z-text | मुख्य टेक्स्ट और मान | #1a1d21 | #e4e6e9 |
--z-text-muted | लेबल, शीर्षक, गौण टेक्स्ट। --z-surface-2 के विरुद्ध 4.5:1 तक पहुँचना चाहिए | #5b626b | #a2a9b1 |
--z-danger | त्रुटियाँ, आवश्यक चिह्न, danger पंक्तियाँ | #b3261e | #f28b82 |
--z-warning | चेतावनी पंक्तियाँ | #8a5300 | #e6b45a |
--z-success | सफलता पंक्तियाँ | #1e6b3a | #6fcf8f |
--z-info | Info टोस्ट | #2b5d8a | #8ab8e6 |
3. व्युत्पन्न टोकन
आधार टोकन से color-mix() और relative color सिंटैक्स से गणना किए जाते हैं। जब आधार टोकन बदलता है तो ये अपने आप अपडेट होते हैं।
| टोकन | उद्देश्य | लाइट | डार्क |
|---|---|---|---|
--z-accent | सतह पर टेक्स्ट या पतली रेखा के रूप में इस्तेमाल हुआ ब्रांड रंग: लिंक, मौजूदा मेनू आइटम, फ़ोकस की गई पंक्ति की पट्टी | var(--z-brand) | oklch(from var(--z-brand) 0.8 c h), ब्रांड की ह्यू एक निश्चित हल्के टोन पर। relative color सिंटैक्स के बिना ब्राउज़र को 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% काले के साथ मिला हुआ | accent 84% सफ़ेद के साथ मिला हुआ |
--z-primary-active | प्राइमरी बटन दबा हुआ | ब्रांड 74% काले के साथ मिला हुआ | accent 70% सफ़ेद के साथ मिला हुआ |
--z-brand-subtle | मौजूदा मेनू आइटम और फ़ोकस की गई ग्रिड पंक्ति के पीछे की हल्की छटा | --z-surface के ऊपर --z-tint पर accent | वही सूत्र |
--z-focus | फ़ोकस रिंग | var(--z-accent) | var(--z-accent) |
--z-danger-subtle, --z-warning-subtle, --z-success-subtle, --z-info-subtle | पंक्ति और संदेश की पृष्ठभूमि | --z-surface के ऊपर --z-tint पर स्टेटस रंग | वही सूत्र |
--z-tint | हल्की छटाओं की तीव्रता | 9% | 20% |
--z-space | स्पेसिंग इकाई | calc(4px * var(--z-density)) | वही |
--z-control | बटन और इनपुट की ऊँचाई | max(24px, 8 * --z-space) (32 px) | वही |
--z-row | पृष्ठबद्ध और अनंत ग्रिड के लिए ग्रिड पंक्ति ऊँचाई | max(24px, 8 * --z-space) (32 px) | वही |
--z-gap | Screen खंडों के बीच अंतर | 3 * --z-space (12 px) | वही |
--z-radius-sm, --z-radius-lg | छोटे हिस्से (फ़िल्टर, कोड), Window | --z-radius का 0.75x और 1.5x | वही |
--z-shadow-2 | केवल Window और टोस्ट। ग्रिड पंक्तियों को कभी छाया नहीं मिलती | नरम दो परत की छाया | गहरी |
--z-backdrop | मोडल Window के पीछे | rgb(20 24 28 / 40%) | rgb(0 0 0 / 60%) |
--z-dir | पढ़ने की दिशा का चिह्न, उन ऑफ़सेट के लिए जिनका तार्किक रूप नहीं है (शुरुआती या अंतिम तरफ़ दिखाने वाली भीतरी छाया, स्लाइड ट्रांसफ़ॉर्म): calc(2px * var(--z-dir)) | 1, और dir="rtl" में -1 | वही |
सर्वर मार्कअप द्वारा सेट किए प्रति एलिमेंट टोकन: --z-width (Window चौड़ाई), --z-flex (कॉलम हिस्सा), --z-row-height (वर्चुअल ग्रिड पंक्ति ऊँचाई), और कंपोनेंट लाइब्रेरी के लिए --z-stack-gap, --z-split, --z-progress, --z-columns, --z-level और --z-pop-x / --z-pop-y (पॉपअप स्थिति)।
चार्ट श्रृंखला के रंग components.css में --z-chart-1 से --z-chart-6 हैं, डार्क थीम में हल्के मानों के साथ। हर एक --z-surface के विरुद्ध 3:1 तक पहुँचता है। इन्हें किसी भी आधार टोकन की तरह ओवरराइड करें।
4. ब्रांड रंग चुनना
--z-brandलाइट थीम में सफ़ेद टेक्स्ट वहन करता है (बटन, ऐप नाम पट्टी)। ऐसा रंग चुनें जो--z-on-brandके विरुद्ध कम से कम 4.5:1 हो। अधिकतर मध्यम से गहरे ब्रांड रंग पास होते हैं। पीले जैसे हल्के ब्रांड रंग के लिए--z-on-brandको भी गहरे रंग पर सेट करें।- डार्क थीम में किट टेक्स्ट, रिंग और प्राइमरी बटन के लिए ब्रांड को हल्का करती है, और ऐप नाम पट्टी के लिए ठोस ब्रांड रखती है। अलग ब्रांड दोनों थीम में बिना दूसरे रंग के सोच-समझकर चुना दिखता है।
- स्टेटस रंग ब्रांड से अलग रखें। लाल त्रुटि पंक्तियों के पास लाल ब्रांड त्रुटियाँ पहचानना कठिन बनाता है; ऐसे में
--z-dangerको अलग लाल की ओर खिसकाएँ या--z-brand-subtleओवरराइड करके ब्रांड को ग्रिड से दूर रखें। - अपने रंगों को खंड 5 की तालिका को लक्ष्य मानकर जाँचें। सीमा से नीचे की कोई भी जोड़ी WCAG 2.2 AA में विफल होती है।
5. सत्यापित कंट्रास्ट
चल रहे उदाहरण ऐप पर Chromium में मापा गया: हर टोकन को उसके रेंडर किए sRGB मान तक हल किया गया (color-mix() और relative colors समेत), फिर WCAG 2.x कंट्रास्ट अनुपात गणना किया गया। सीमाएँ: टेक्स्ट के लिए 4.5:1, UI कंपोनेंट रूपरेखा और फ़ोकस संकेतकों के लिए 3:1।
| जोड़ी | लाइट | डार्क | ज़रूरी |
|---|---|---|---|
--z-text on --z-bg | 15.49 | 14.77 | 4.5 |
--z-text on --z-surface | 16.91 | 13.54 | 4.5 |
--z-text on --z-surface-2 | 15.91 | 12.63 | 4.5 |
--z-text on --z-hover | 14.55 | 10.93 | 4.5 |
--z-text on --z-brand-subtle (फ़ोकस की गई पंक्ति) | 14.79 | 9.27 | 4.5 |
--z-text on --z-danger-subtle | 14.73 | 9.76 | 4.5 |
--z-text on --z-warning-subtle | 14.82 | 9.31 | 4.5 |
--z-text on --z-success-subtle | 14.76 | 9.33 | 4.5 |
--z-text-muted on --z-bg | 5.65 | 7.78 | 4.5 |
--z-text-muted on --z-surface | 6.17 | 7.13 | 4.5 |
--z-text-muted on --z-surface-2 (शीर्षक) | 5.80 | 6.65 | 4.5 |
--z-text-muted on --z-hover | 5.31 | 5.76 | 4.5 |
--z-text-muted on --z-danger-subtle (धुँधली पंक्ति) | 5.37 | 5.14 | 4.5 |
--z-text-muted on --z-warning-subtle | 5.41 | 4.90 | 4.5 |
--z-accent on --z-surface (लिंक) | 6.62 | 9.33 | 4.5 |
--z-accent on --z-bg | 6.06 | 10.18 | 4.5 |
--z-accent on --z-brand-subtle (मौजूदा मेनू आइटम) | 5.79 | 6.39 | 4.5 |
--z-on-primary on --z-primary | 6.62 | 10.18 | 4.5 |
--z-on-primary on --z-primary-hover | 8.82 | 11.26 | 4.5 |
--z-on-primary on --z-primary-active | 11.12 | 12.26 | 4.5 |
--z-on-brand on --z-brand (ऐप नाम पट्टी) | 6.62 | 6.62 | 4.5 |
--z-danger on --z-surface (फ़ील्ड त्रुटियाँ) | 6.54 | 7.09 | 4.5 |
--z-danger on --z-danger-subtle | 5.69 | 5.11 | 4.5 |
--z-warning on --z-surface | 6.33 | 8.90 | 4.5 |
--z-warning on --z-warning-subtle | 5.55 | 6.12 | 4.5 |
--z-success on --z-surface | 6.52 | 8.87 | 4.5 |
--z-info on --z-surface | 6.92 | 8.13 | 4.5 |
--z-focus on --z-surface | 6.62 | 9.33 | 3 |
--z-focus on --z-bg | 6.06 | 10.18 | 3 |
--z-focus on --z-brand-subtle | 5.79 | 6.39 | 3 |
--z-border-strong on --z-surface (इनपुट रूपरेखा) | 3.78 | 4.30 | 3 |
--z-border-strong on --z-surface-2 | 3.55 | 4.01 | 3 |
--z-border सजावटी है (उन आइटम के बीच विभाजक जिनमें पहले से टेक्स्ट है) और 3:1 के लिए बाध्य नहीं है।
6. अन्य सुगम्यता व्यवहार
- हर इंटरैक्टिव एलिमेंट
--z-focusमें 2 px:focus-visibleरिंग दिखाता है। ग्रिड पंक्तियाँ रिंग को पंक्ति के भीतर बनाती हैं ताकि वह स्क्रॉल कंटेनर से कभी कटे नहीं। - बटन, इनपुट, क्रम शीर्षक, फ़िल्टर बॉक्स, पेजर बटन और Window बंद करने का बटन किसी भी घनत्व पर कम से कम 24 x 24 px हैं।
prefers-reduced-motion: reduceटोस्ट का प्रवेश और सभी ट्रांज़िशन हटा देता है।forced-colorsमोड में आइकनCanvasTextइस्तेमाल करते हैं, प्राइमरी बटन और फ़ोकस की गई पंक्तिHighlightइस्तेमाल करते हैं, और पृष्ठभूमि की छटाओं पर निर्भर स्थिति (मौजूदा मेनू आइटम, पंक्ति स्टेटस) को इसके बजाय आउटलाइन या बॉर्डर मिलता है।