Nordhealth, वेब कॉम्पोनेंट में कस्टम प्रॉपर्टी का इस्तेमाल कैसे करती है

डिज़ाइन सिस्टम और कॉम्पोनेंट लाइब्रेरी में कस्टम प्रॉपर्टी इस्तेमाल करने के फ़ायदे.

David Darnes
David Darnes

मेरा नाम डेव है और मैं Nordhealth में, सीनियर फ़्रंट-एंड डेवलपर हूं. मैं अपने डिज़ाइन सिस्टम Nord के डिज़ाइन और डेवलपमेंट पर काम करता हूं. इसमें हमारे कॉम्पोनेंट लाइब्रेरी के लिए वेब कॉम्पोनेंट बनाना भी शामिल है. हम आपको यह बताना चाहते हैं कि हमने सीएसएस कस्टम प्रॉपर्टी का इस्तेमाल करके, वेब कॉम्पोनेंट को स्टाइल करने से जुड़ी समस्याओं को कैसे हल किया है. साथ ही, हम आपको डिज़ाइन सिस्टम और कॉम्पोनेंट लाइब्रेरी में कस्टम प्रॉपर्टी इस्तेमाल करने के दूसरे फ़ायदों के बारे में भी बताना चाहते हैं.

हम वेब कॉम्पोनेंट कैसे बनाते हैं

हम अपने वेब कॉम्पोनेंट बनाने के लिए, Lit लाइब्रेरी का इस्तेमाल करते हैं. यह एक ऐसी लाइब्रेरी है जो कई बॉयलरप्लेट कोड उपलब्ध कराती है. जैसे, स्टेट, स्कोप वाले स्टाइल, टेंप्लेट वगैरह. यह न सिर्फ़ Lit Light लाइटवेट है, बल्कि यह नेटिव JavaScript API पर भी काम करता है. इसका मतलब है कि हम कोड का एक शानदार बंडल डिलीवर कर सकते हैं, जो ब्राउज़र में पहले से मौजूद सुविधाओं का फ़ायदा उठाता है.


import {html, css, LitElement} from 'lit';

export class SimpleGreeting extends LitElement {
  static styles = css`:host { color: blue; font-family: sans-serif; }`;

  static properties = {
    name: {type: String},
  };

  constructor() {
    super();
    this.name = 'there';
  }

  render() {
    return html`

Hey ${this.name}, welcome to Web Components!

`; } } customElements.define('simple-greeting', SimpleGreeting);
Lit की मदद से लिखा गया वेब कॉम्पोनेंट.

हालांकि, वेब कॉम्पोनेंट के बारे में सबसे दिलचस्प बात यह है कि वे किसी भी मौजूदा JavaScript फ़्रेमवर्क के साथ काम करते हैं या किसी फ़्रेमवर्क के साथ भी काम करते हैं. पेज में मुख्य JavaScript पैकेज का रेफ़रंस देने के बाद, वेब कॉम्पोनेंट का इस्तेमाल करना बहुत हद तक किसी नेटिव एचटीएमएल एलिमेंट का इस्तेमाल करने जैसा है. टैग में मौजूद एक समान हाइफ़न, जो यह बताता है कि यह नेटिव एचटीएमएल एलिमेंट नहीं है. यह टैग, ब्राउज़र को यह बताने का एक मानक है कि यह एक वेब कॉम्पोनेंट है.


// TODO: DevSite - Code sample removed as it used inline event handlers
ऊपर बनाए गए वेब कॉम्पोनेंट का इस्तेमाल किसी पेज पर करना.

शैडो डीओएम स्टाइल एनकैप्सुलेशन

इसी तरह, नेटिव एचटीएमएल एलिमेंट में भी शैडो डीओएम होता है. इसी तरह, वेब कॉम्पोनेंट भी होता है. शैडो डीओएम, एलिमेंट में नोड का छिपा हुआ ट्री होता है. इसे विज़ुअलाइज़ करने का सबसे अच्छा तरीका यह है कि अपने वेब इंस्पेक्टर को खोलें और "Shadow DOM ट्री दिखाएं" का विकल्प चालू करें. ऐसा करने के बाद, इंस्पेक्टर में नेटिव इनपुट एलिमेंट देखें. अब आपके पास उस इनपुट को खोलने और उसमें मौजूद सभी एलिमेंट देखने का विकल्प होगा. इसे हमारे किसी वेब कॉम्पोनेंट के साथ भी आज़माया जा सकता है. इसके शैडो DOM को देखने के लिए, हमारे कस्टम इनपुट कॉम्पोनेंट की जांच करें.

DevTools में शैडो DOM की जांच की गई है.
सामान्य टेक्स्ट इनपुट एलिमेंट और हमारे Nord इनपुट वेब कॉम्पोनेंट में शैडो DOM का उदाहरण.

शैडो DOM का एक फ़ायदा (या कमियां, आपके नज़रिए के आधार पर) स्टाइल एनकैप्सुलेशन है. अगर आप अपने वेब कॉम्पोनेंट के अंदर सीएसएस लिखते हैं, तो वे स्टाइल लीक नहीं हो सकतीं और मुख्य पेज या दूसरे एलिमेंट पर असर नहीं डाल सकतीं. ये पूरी तरह से कॉम्पोनेंट में शामिल होते हैं. इसके अलावा, मुख्य पेज या किसी पैरंट वेब कॉम्पोनेंट के लिए लिखी गई सीएसएस, आपके वेब कॉम्पोनेंट में लीक नहीं हो सकती.

अलग-अलग स्टाइल को शामिल करने से, हमारी कॉम्पोनेंट लाइब्रेरी को फ़ायदा मिलता है. इससे हमें इस बात की ज़्यादा गारंटी मिलती है कि जब कोई व्यक्ति हमारे किसी कॉम्पोनेंट का इस्तेमाल करता है, तो वह वैसा ही दिखेगा जैसा हमारी उम्मीद के मुताबिक दिखेगा. इस बात से कोई फ़र्क़ नहीं पड़ता कि पैरंट पेज पर कोई स्टाइल लागू की गई है या नहीं. यह भी पक्का करने के लिए कि हम all: unset; को अपने सभी वेब कॉम्पोनेंट के रूट या "होस्ट" में जोड़ते हैं.


:host {
  all: unset;
  display: block;
  box-sizing: border-box;
  text-align: start;
  /* ... */
}
कुछ कॉम्पोनेंट बॉयलरप्लेट कोड को शैडो रूट या होस्ट सिलेक्टर पर लागू किया जा रहा है.

हालांकि, अगर आपके वेब कॉम्पोनेंट का इस्तेमाल करने वाले किसी व्यक्ति के पास किसी खास स्टाइल को बदलने की सही वजह है, तो क्या होगा? हो सकता है कि टेक्स्ट की कोई ऐसी लाइन हो जिसमें कॉन्टेक्स्ट की वजह से ज़्यादा कंट्रास्ट की ज़रूरत हो या बॉर्डर की चौड़ाई को ज़्यादा करना ज़रूरी हो? अगर आपके कॉम्पोनेंट में कोई भी स्टाइल नहीं पहुंच पाती, तो स्टाइल के उन विकल्पों को कैसे अनलॉक किया जा सकता है?

ऐसी ही स्थिति में सीएसएस कस्टम प्रॉपर्टी का इस्तेमाल किया जाता है.

सीएसएस की कस्टम प्रॉपर्टी

कस्टम प्रॉपर्टी के नाम काफ़ी सही होते हैं. ये सीएसएस प्रॉपर्टी हैं. इन्हें नाम देकर, अपनी ज़रूरत के हिसाब से कोई भी वैल्यू लागू की जा सकती है. इसके लिए बस आपको उनके पहले दो हाइफ़न का इस्तेमाल करना होगा. अपनी कस्टम प्रॉपर्टी तय करने के बाद, var() फ़ंक्शन का इस्तेमाल करके, सीएसएस में वैल्यू का इस्तेमाल किया जा सकता है.


:root {
  --n-color-accent: rgb(53, 89, 199);
  /* ... */
}

.n-color-accent-text {
  color: var(--n-color-accent);
}
डिज़ाइन टोकन के हमारे सीएसएस फ़्रेमवर्क का उदाहरण, जो कस्टम प्रॉपर्टी के तौर पर इस्तेमाल किया जा रहा है और जिसे हेल्पर क्लास में इस्तेमाल किया जा रहा है.

इनहेरिटेंस की बात करें, तो सभी कस्टम प्रॉपर्टी इनहेरिट की जाती हैं. यह सामान्य सीएसएस प्रॉपर्टी और वैल्यू के व्यवहार के मुताबिक होती है. किसी पैरंट एलिमेंट या खुद एलिमेंट पर लागू की गई किसी भी कस्टम प्रॉपर्टी का इस्तेमाल, दूसरी प्रॉपर्टी के लिए वैल्यू के तौर पर किया जा सकता है. हम अपने डिज़ाइन टोकन के लिए कस्टम प्रॉपर्टी का बहुत ज़्यादा इस्तेमाल करते हैं. इसके लिए, हम उन्हें अपने सीएसएस फ़्रेमवर्क की मदद से रूट एलिमेंट पर लागू करते हैं. इसका मतलब है कि पेज पर मौजूद सभी एलिमेंट, इन टोकन वैल्यू का इस्तेमाल कर सकते हैं. फिर चाहे वह वेब कॉम्पोनेंट, सीएसएस हेल्पर क्लास हो या कोई ऐसा डेवलपर जो हमारी टोकन की सूची से कोई वैल्यू पाना चाहता हो.

हम var() फ़ंक्शन का इस्तेमाल करके कस्टम प्रॉपर्टी इनहेरिट कर सकते हैं. ऐसा करके, हम वेब कॉम्पोनेंट के शैडो डीओएम का पता लगाते हैं. इससे, डेवलपर हमारे कॉम्पोनेंट को बेहतर तरीके से कंट्रोल कर पाते हैं.

Nord वेब कॉम्पोनेंट में कस्टम प्रॉपर्टी

जब भी हम अपने डिज़ाइन सिस्टम के लिए कोई कॉम्पोनेंट डेवलप करते हैं, तो हम सीएसएस के लिए सोच-समझकर उसके काम करते हैं. हम अच्छे और रखरखाव में आसान कोड की कोशिश करते हैं. हमारे डिज़ाइन टोकन, रूट एलिमेंट पर हमारे मुख्य सीएसएस फ़्रेमवर्क में कस्टम प्रॉपर्टी के तौर पर तय किए गए हैं.


:root {
  --n-space-m: 16px;
  --n-space-l: 24px;
  /* ... */
  --n-color-background: rgb(255, 255, 255);
  --n-color-border: rgb(216, 222, 228);
  /* ... */
}
रूट सिलेक्टर में सीएसएस की कस्टम प्रॉपर्टी तय की जा रही है.

इसके बाद, इन टोकन वैल्यू का हमारे कॉम्पोनेंट में रेफ़रंस दिया जाता है. कुछ मामलों में, हम सीधे सीएसएस प्रॉपर्टी पर वैल्यू लागू करेंगे. वहीं, कुछ मामलों में, हम असल में नई कॉन्टेक्स्ट के हिसाब से बनाई गई कस्टम प्रॉपर्टी तय करेंगे और उस पर वैल्यू लागू करेंगे.


:host {
  --n-tab-group-padding: 0;
  --n-tab-list-background: var(--n-color-background);
  --n-tab-list-border: inset 0 -1px 0 0 var(--n-color-border);
  /* ... */
}

.n-tab-group-list {
  box-shadow: var(--n-tab-list-border);
  background-color: var(--n-tab-list-background);
  gap: var(--n-space-s);
  /* ... */
}
कस्टम प्रॉपर्टी, जिन्हें कॉम्पोनेंट के शैडो रूट पर बनाया जाता है. इसके बाद, इन्हें कॉम्पोनेंट स्टाइल में इस्तेमाल किया जाता है. डिज़ाइन टोकन की सूची में शामिल कस्टम प्रॉपर्टी का भी इस्तेमाल किया जा रहा है.

हम ऐसे कुछ वैल्यू भी ऐब्स्ट्रैक्ट करेंगे जो कॉम्पोनेंट के लिए खास हैं, लेकिन हमारे टोकन में नहीं हैं. साथ ही, उन्हें काम की कस्टम प्रॉपर्टी में बदल भी देंगे. कॉम्पोनेंट के हिसाब से बनाई गई कस्टम प्रॉपर्टी से, हमें दो मुख्य फ़ायदे मिलते हैं. सबसे पहले, इसका मतलब है कि हम अपने सीएसएस के साथ ज़्यादा "सूखा" हो सकते हैं, क्योंकि इस वैल्यू को कॉम्पोनेंट के अंदर एक से ज़्यादा प्रॉपर्टी पर लागू किया जा सकता है.


.n-tab-group-list::before {
  /* ... */
  padding-inline-start: var(--n-tab-group-padding);
}

.n-tab-group-list::after {
  /* ... */
  padding-inline-end: var(--n-tab-group-padding);
}
टैब ग्रुप पैडिंग (जगह) कस्टम प्रॉपर्टी का, कॉम्पोनेंट कोड में कई जगहों पर इस्तेमाल किया जा रहा है.

दूसरा, इससे कॉम्पोनेंट की स्थिति और अलग-अलग वर्शन में किए जाने वाले बदलावों को बेहतर बनाया जा सकता है. दरअसल, यह सिर्फ़ एक कस्टम प्रॉपर्टी है, जिसे बदलने पर सभी प्रॉपर्टी को अपडेट करना पड़ता है. उदाहरण के लिए, ऐसा तब होता है, जब किसी कर्सर को कर्सर घुमाएं या ऐक्टिव स्टेट के तौर पर या इस मामले में, कोई वैरिएशन बनाया जा रहा है.


:host([padding="l"]) {
  --n-tab-group-padding: var(--n-space-l);
}
टैब कॉम्पोनेंट का एक वैरिएशन, जिसमें पैडिंग (जगह) को कई अपडेट के बजाय, एक ही कस्टम प्रॉपर्टी अपडेट का इस्तेमाल करके बदला जा रहा है.

हालांकि, इसका सबसे बड़ा फ़ायदा यह है कि जब हम किसी कॉम्पोनेंट पर, कॉन्टेक्स्ट के हिसाब से इन कस्टम प्रॉपर्टी को तय करते हैं, तो हम अपने हर कॉम्पोनेंट के लिए एक तरह का कस्टम सीएसएस एपीआई बनाते हैं. इस कॉम्पोनेंट को इस्तेमाल करने वाला व्यक्ति उस पर टैप कर सकता है.


<nord-tab-group label="Title">
  <!-- ... -->
</nord-tab-group>

<style>
  nord-tab-group {
    --n-tab-group-padding: var(--n-space-xl);
  }
</style>
पेज पर टैब ग्रुप कॉम्पोनेंट का इस्तेमाल करना और पैडिंग (जगह) कस्टम प्रॉपर्टी को बड़े साइज़ में अपडेट करना.

पिछला उदाहरण हमारे एक वेब कॉम्पोनेंट को दिखाता है, जिसमें सिलेक्टर के ज़रिए बदली गई प्रासंगिक कस्टम प्रॉपर्टी मौजूद है. इस पूरे तरीके का नतीजा एक ऐसा कॉम्पोनेंट है जो उपयोगकर्ता को स्टाइलिंग में काफ़ी बदलाव करने की सुविधा देता है. साथ ही, ज़्यादातर असल स्टाइल पर भी नज़र बनाए रखता है. साथ ही, बोनस के तौर पर, कॉम्पोनेंट डेवलपर के तौर पर हमारे पास उपयोगकर्ता की लागू की गई स्टाइल को देखने की सुविधा होती है. अगर हमें उनमें से किसी प्रॉपर्टी में बदलाव करना है या उसे बढ़ाना है, तो उपयोगकर्ता को अपना कोई भी कोड बदलने की ज़रूरत नहीं होगी.

हमारे हिसाब से यह तरीका बहुत असरदार है, न सिर्फ़ हमारे डिज़ाइन सिस्टम कॉम्पोनेंट के क्रिएटर के तौर पर, बल्कि हमारी डेवलपमेंट टीम के लिए भी, जब वे हमारे प्रॉडक्ट में इन कॉम्पोनेंट का इस्तेमाल करते हैं.

कस्टम प्रॉपर्टी का इस्तेमाल शुरू करना

लिखते समय हम अपने दस्तावेज़ में, कॉन्टेक्स्ट के हिसाब से बनाई गई इन प्रॉपर्टी को शामिल नहीं करते. हालांकि, हमारी योजना है कि हमारी डेवलपमेंट टीम की एक बड़ी टीम, इन प्रॉपर्टी को समझ सके और इनका फ़ायदा ले सके. हमारे कॉम्पोनेंट को एनपीएम में मेनिफ़ेस्ट फ़ाइल के साथ पैकेज किया जाता है. इसमें, इनके बारे में पूरी जानकारी होती है. इसके बाद, दस्तावेज़ों की साइट डिप्लॉय करते समय, हम मेनिफ़ेस्ट फ़ाइल को डेटा के तौर पर इस्तेमाल करते हैं. ऐसा Eleventy और इसके ग्लोबल डेटा की सुविधा का इस्तेमाल करके किया जाता है. हम इस मेनिफ़ेस्ट डेटा फ़ाइल में, कॉन्टेक्स्ट के हिसाब से बनाई गई इन कस्टम प्रॉपर्टी को शामिल करने की योजना बना रहे हैं.

एक अन्य क्षेत्र में हम सुधार करना चाहते हैं. इसमें हम यह बताते हैं कि कॉन्टेक्स्ट के हिसाब से बनाई गई कस्टम प्रॉपर्टी, वैल्यू कैसे इनहेरिट करती हैं. उदाहरण के लिए, फ़िलहाल अगर आपको दो डिवाइडर कॉम्पोनेंट का रंग बदलना है, तो आपको उन दोनों कॉम्पोनेंट को खास तौर पर सिलेक्टर की मदद से टारगेट करना होगा या कस्टम प्रॉपर्टी को सीधे स्टाइल एट्रिब्यूट वाले एलिमेंट पर लागू करना होगा. यह ठीक लग सकता है, लेकिन अगर डेवलपर उन स्टाइल को कंटेन्ड एलिमेंट पर या रूट लेवल पर तय कर सके, तो ज़्यादा मददगार होगा.


<nord-divider></nord-divider>

<section>
  <nord-divider></nord-divider>
   <!-- ... -->
</section>

<style>
  nord-divider {
    --n-divider-color: var(--n-color-status-danger);
  }

  section {
    padding: var(--n-space-s);
    background: var(--n-color-surface-raised);
  }
  
  section nord-divider {
    --n-divider-color: var(--n-color-status-success);
  }
</style>
हमारे डिवाइडर कॉम्पोनेंट के दो उदाहरण, जिनके लिए दो अलग-अलग कलर ट्रीटमेंट की ज़रूरत होती है. एक विकल्प किसी सेक्शन में मौजूद होता है, जिसका इस्तेमाल हम किसी खास सिलेक्टर के लिए कर सकते हैं. हालांकि, हमें डिवाइडर को खास तौर पर टारगेट करना होता है.

आपको सीधे कॉम्पोनेंट पर कस्टम प्रॉपर्टी की वैल्यू सेट करनी पड़ सकती है, क्योंकि हम कॉम्पोनेंट होस्ट सिलेक्टर की मदद से उसी एलिमेंट की जानकारी देते हैं. हम ग्लोबल डिज़ाइन टोकन का इस्तेमाल सीधे कॉम्पोनेंट में करते हैं. ये टोकन, सीधे तौर पर दिखते हैं और इन पर इस समस्या का कोई असर नहीं पड़ता. साथ ही, इन्हें पैरंट एलिमेंट पर इंटरसेप्ट भी किया जा सकता है. हम दोनों के लिए, दुनिया की बेहतरीन सुविधाएं कैसे हासिल कर सकते हैं?

निजी और सार्वजनिक कस्टम प्रॉपर्टी

निजी कस्टम प्रॉपर्टी को Lea Verou ने बनाया है. यह कॉम्पोनेंट, कॉन्टेक्स्ट के हिसाब से "निजी" कस्टम प्रॉपर्टी है. हालांकि, इसे फ़ॉलबैक वाली "सार्वजनिक" कस्टम प्रॉपर्टी पर सेट किया जाता है.



:host {
  --_n-divider-color: var(--n-divider-color, var(--n-color-border));
  --_n-divider-size: var(--n-divider-size, 1px);
}

.n-divider {
  border-block-start: solid var(--_n-divider-size) var(--_n-divider-color);
  /* ... */
}
संदर्भ के हिसाब से कस्टम प्रॉपर्टी के साथ डिवाइडर वेब कॉम्पोनेंट सीएसएस को अडजस्ट किया गया है, ताकि अंदरूनी सीएसएस निजी कस्टम प्रॉपर्टी पर निर्भर हो सके. इस प्रॉपर्टी को फ़ॉलबैक वाली सार्वजनिक कस्टम प्रॉपर्टी पर सेट किया गया है.

अपनी ज़रूरत के हिसाब से कस्टम प्रॉपर्टी को इस तरीके से तय करने का मतलब है कि हम वे सभी काम कर सकते हैं जो हम पहले करते थे. जैसे, ग्लोबल टोकन वैल्यू को इनहेरिट करना और अपने पूरे कॉम्पोनेंट कोड में वैल्यू का फिर से इस्तेमाल करना; लेकिन कॉम्पोनेंट, उस प्रॉपर्टी की नई परिभाषाओं को अपने या किसी पैरंट एलिमेंट पर भी अच्छी तरह इनहेरिट करेगा.


<nord-divider></nord-divider>

<section>
  <nord-divider></nord-divider>
   <!-- ... -->
</section>

<style>
  nord-divider {
    --n-divider-color: var(--n-color-status-danger);
  }

  section {
    padding: var(--n-space-s);
    background: var(--n-color-surface-raised);
    --n-divider-color: var(--n-color-status-success);
  }
</style>
दोनों डिवाइडर को फिर से जोड़ दें. इस बार, सेक्शन सिलेक्टर में डिवाइडर की कॉन्टेक्स्ट के हिसाब से कस्टम प्रॉपर्टी जोड़कर डिवाइडर को फिर से रंग दिया जा सकता है. डिवाइडर इसे इनहेरिट करेगा, जिससे ज़्यादा साफ़ और ज़्यादा सुविधाजनक कोड बनेगा.

यह तर्क दिया जा सकता है कि यह तरीका असल में "निजी" नहीं है. हालांकि, हमें लगता है कि यह उस समस्या का एक शानदार समाधान है जिसके बारे में हमें चिंता थी. मौका मिलने पर, हम अपने कॉम्पोनेंट में इसका इस्तेमाल करेंगे. इससे हमारी डेवलपमेंट टीम के पास कॉम्पोनेंट के इस्तेमाल पर ज़्यादा कंट्रोल रहेगा. साथ ही, हमारी नीतियों का फ़ायदा भी मिलेगा.

हमें उम्मीद है कि आपको सीएसएस कस्टम प्रॉपर्टी के साथ वेब कॉम्पोनेंट इस्तेमाल करने के बारे में यह अहम जानकारी मिली होगी. इस बारे में हमें अपनी राय दें. अगर आपको अपने काम में इनमें से कोई तरीका इस्तेमाल करना है, तो मुझे Twitter @DavidDarnes से बताएं. Nordhealth @NordhealthHQ को Twitter पर भी देखा जा सकता है. साथ ही, मेरी टीम के बाकी सदस्यों ने भी इस डिज़ाइन सिस्टम को एक साथ लाने और इस लेख में बताए गए फ़ीचर को लागू करने के लिए कड़ी मेहनत की है: @Viljamis, @WickyNilliams, और @eric_habich.

हीरो इमेज डैन क्रिस्चियन पादुरेत की