सुलभ वेब कॉम्पोनेंट

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

सिमेंटिक मार्कअप से शुरुआत करें: टेंप्लेट में असली <button>, <nav>, <ul> का इस्तेमाल करें, ताकि ज़्यादातर सिमेंटिक बिना किसी शुल्क के मिल सकें. साथ ही, गैप के लिए ElementInternals/एआरआईए को रिज़र्व करें.

ElementInternals ARIA मिक्सिन की मदद से डिफ़ॉल्ट सिमैंटिक

होस्ट पर ARIA एट्रिब्यूट लिखने के बजाय, ElementInternals का इस्तेमाल करके JS में कस्टम एलिमेंट की भूमिका और ARIA की स्थिति सेट करें. इससे सिमैंटिक, कॉम्पोनेंट के मालिकाना हक वाले डिफ़ॉल्ट के तौर पर बने रहते हैं. हालांकि, उपभोक्ता लाइट डीओएम में एट्रिब्यूट की मदद से उन्हें बदल सकता है.

class ToggleSwitch extends HTMLElement {
  #internals;
  constructor() {
    super();
    this.#internals = this.attachInternals();
    this.#internals.role = 'switch';          // default role, no host attribute needed
    this.#internals.ariaChecked = 'false';    // exposed to the accessibility tree
    this.addEventListener('click', () => this.toggle());
    this.addEventListener('keydown', (e) => {
      if (e.key === ' ') { e.preventDefault(); this.toggle(); }
    });
  }
  connectedCallback() {
    // Put the host in the tab order on connect (setting tabIndex in the constructor throws on createElement).
    if (!this.hasAttribute('tabindex')) this.tabIndex = 0;
  }
  toggle() {
    const on = this.#internals.ariaChecked !== 'true';
    this.#internals.ariaChecked = String(on);
  }
}
customElements.define('toggle-switch', ToggleSwitch);

इससे डीओएम को ARIA एट्रिब्यूट से भरने से बचा जा सकता है. साथ ही, उपभोक्ताओं को गलती से उन्हें बदलने से रोका जा सकता है. हालांकि, सुलभता ट्री अब भी सही भूमिका और स्टेट देखता है.

फ़ोकस मैनेजमेंट और delegatesFocus

  • जब होस्ट एलिमेंट खुद इंटरैक्टिव कंट्रोल होता है और ElementInternals (जैसे कि ऊपर ToggleSwitch) के ज़रिए भूमिका और स्थिति को दिखाता है, तो होस्ट को connectedCallback (if (!this.hasAttribute('tabindex')) this.tabIndex = 0 — कंस्ट्रक्टर में कभी नहीं, जो document.createElement पर थ्रो करता है) के अंदर टैब ऑर्डर में रखें, ताकि फ़ोकस होस्ट पर हो और सहायक टेक्नोलॉजी इसकी भूमिका और स्थिति की जानकारी दे. स्टैटिक और नॉन-इंटरैक्टिव कॉम्पोनेंट (जैसे, कॉलआउट या कार्ड) के लिए, होस्ट पर tabindex सेट न करें.
  • जब कॉम्पोनेंट किसी ऐसे इंटरनल फ़ोकस किए जा सकने वाले कंट्रोल को रैप करता है जिसके पास सिमैंटिक होते हैं, तो शैडो रूट को delegatesFocus: true के साथ अटैच करें. इसके अलावा, फ़ॉर्म से जुड़े कस्टम एलिमेंट पर static formAssociated = true के साथ अटैच करें. इसके बाद, होस्ट पर फ़ोकस करने (और फ़ॉर्म से जुड़े एलिमेंट के लिए, उससे जुड़े <label> पर क्लिक करने) से, फ़ोकस पहले फ़ोकस किए जा सकने वाले चाइल्ड एलिमेंट पर चला जाता है. साथ ही, :focus होस्ट से मैच करता है. delegatesFocus: true को होस्ट पर किसी भूमिका/स्थिति के साथ न जोड़ें. ऐसा करने पर, फ़ोकस अंदरूनी एलिमेंट पर चला जाएगा और होस्ट की स्थिति को छोड़ देगा.
  • रोविंग फ़ोकस या नए सेक्शन पर फ़ोकस ले जाने के लिए, टारगेट को tabindex="-1" दें और .focus() को कॉल करें. प्रोग्राम के हिसाब से फ़ोकस किए जा सकने वाले टारगेट को साफ़ तौर पर बताएं. इसके लिए, टैब के क्रम पर भरोसा न करें.

शैडो रूट में एआरआईए रिलेशनशिप

  • ज़रूरी: aria-labelledby, aria-describedby, aria-controls वगैरह से रेफ़र किया गया id, सिर्फ़ रेफ़रंस देने वाले एलिमेंट के अपने ट्री में रिज़ॉल्व होता है. लाइट डीओएम में मौजूद id-आधारित एट्रिब्यूट, शैडो ट्री में मौजूद id पर ले जाने वाला नहीं हो सकता. इसी तरह, शैडो ट्री में मौजूद -आधारित एट्रिब्यूट, लाइट डीओएम में मौजूद पर ले जाने वाला नहीं हो सकता. ऐसा होने पर, रेफ़रंस को अनदेखा कर दिया जाता है.
  • बाउंड्री को पार करने के लिए, रिफ़्लेक्ट की गई ARIA एलिमेंट प्रॉपर्टी (जैसे, ariaLabelledByElements, ariaDescribedByElements वगैरह) का इस्तेमाल करें. ये प्रॉपर्टी, आईडी के बजाय सीधे JS एलिमेंट के रेफ़रंस लेती हैं. ये बाहर की ओर रिज़ॉल्व होते हैं: शैडो ट्री के अंदर मौजूद कोई एलिमेंट, लाइट डीओएम या किसी भी ऐंसेस्टर ट्री (इसमें स्लॉट किया गया कॉन्टेंट शामिल है) में मौजूद टारगेट पर ले जा सकता है. इसलिए, लाइट डीओएम कॉन्टेंट से शैडो-इंटरनल कंट्रोल को लेबल किया जा सकता है. id रेफ़रंस ऐसा नहीं कर सकते.
  • वे इनवर्ड रिज़ॉल्व नहीं होते: कोई एलिमेंट, डिसेंडेंट शैडो ट्री में रेफ़रंस नहीं दे सकता. उदाहरण के लिए, किसी होस्ट को उसके शैडो कॉन्टेंट से लेबल नहीं किया जा सकता. इस दिशा में, उभरता हुआ रेफ़रंस टारगेट मैकेनिज़्म, स्टैंडर्ड दिशा है. हालांकि, यह अभी बड़े पैमाने पर उपलब्ध नहीं है.
  • जब किसी संबंध को दोनों में से किसी भी तरीके से नहीं दिखाया जा सकता, तो उसे एक ही ट्री में रखें (लेबल को उसी ट्री में रेंडर करें) या id रेफ़रंस के बजाय aria-label टेक्स्ट का इस्तेमाल करें.

फ़ॉलबैक रणनीतियां

जहां ElementInternals ARIA मिक्सिन उपलब्ध नहीं है वहां होस्ट पर एट्रिब्यूट के तौर पर, रोल और ARIA स्टेट सेट करें (this.setAttribute('role', 'switch')). यह हर जगह काम करता है. हालांकि, इसके लिए डीओएम में ऐसे एट्रिब्यूट डालने पड़ते हैं जिन्हें उपभोक्ता बदल सकता है.

अगर ARIA एलिमेंट की प्रॉपर्टी उपलब्ध नहीं हैं, तो एक ही ट्री रिलेशनशिप के लिए id-आधारित aria-* एट्रिब्यूट का इस्तेमाल करें. क्रॉस-बाउंड्री लेबल में id-आधारित कोई विकल्प नहीं होता है. इसलिए, aria-label टेक्स्ट का इस्तेमाल करें.