مكوّنات ويب تسهّل الاستخدام

ميزات الويب: انعكاس سمة ARIA Shadow DOM

يغيّر حدّ الظل طريقة عمل الدلالات وARIA. هناك نوعان من حالات الإخفاق السائدة: دلالات مفقودة داخل شجرة الظل، ومراجع ARIA التي تتعطل بصمت لأنها لا يمكنها عبور جذور الظل.

ابدأ من الترميز الدلالي: استخدِم عناصر <button> و<nav> و<ul> حقيقية داخل النموذج لكي تظهر معظم الدلالات مجانًا، واحتفِظ بـ ElementInternals/ARIA للفجوات.

الدلالات التلقائية من خلال مزيج ElementInternals ARIA

يمكنك ضبط دور عنصر مخصّص وحالة ARIA في JS من خلال ElementInternals، بدلاً من كتابة سمات ARIA على المضيف. يؤدي ذلك إلى الحفاظ على الدلالات كإعدادات تلقائية يملكها المكوّن، مع السماح للمستهلك بإلغائها باستخدام السمات في Light DOM.

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);

يؤدي ذلك إلى تجنُّب ملء نموذج DOM بسمات 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 في جذور الظل

  • إلزامي: يتم حلّ id المُشار إليه بواسطة aria-labelledby وaria-describedby وaria-controls وما إلى ذلك فقط ضمن شجرة العنصر المُشير نفسه. لا يمكن لسمة مستندة إلى id في Light DOM أن تشير إلى id داخل شجرة ظل، والعكس صحيح، ويتم تجاهل المرجع بدون إشعار.
  • لتجاوز الحدود، استخدِم سمات العناصر في ARIA المنعكسة (مثل ariaLabelledByElements وariaDescribedByElements وما إلى ذلك)، والتي تستخدم مراجع عناصر JS مباشرةً بدلاً من أرقام التعريف. يتم حلّها خارجيًا: يمكن لعنصر داخل شجرة ظل أن يشير إلى هدف في Light DOM أو أي شجرة أصل (بما في ذلك المحتوى المضاف)، ما يتيح لك تصنيف عنصر تحكّم داخلي في الظل من محتوى Light DOM، وهو أمر لا يمكن لمراجع id التعبير عنه.
  • لا يتم حلّها داخليًا: لا يمكن لعنصر أن يشير إلى شجرة ظل تابعة (على سبيل المثال، لا يمكن تصنيف مضيف من خلال محتوى الظل الخاص به). لهذا الغرض، تُعدّ آلية Reference Target الناشئة هي الاتجاه المعتمد، ولكنّها غير متاحة على نطاق واسع بعد.
  • عندما يتعذّر التعبير عن علاقة بأي من الطريقتين، احتفِظ بها ضمن شجرة واحدة (اعرض التصنيف في الشجرة نفسها) أو استخدِم نص aria-label بدلاً من مرجع id.

استراتيجيات احتياطية

في حال عدم توفّر مزيج ARIA‏ ElementInternals، اضبط الدور وحالة ARIA كسمات على المضيف بدلاً من ذلك (this.setAttribute('role', 'switch')). يعمل هذا الإجراء في كل مكان، ولكنّه يضع سمات في نموذج DOM يمكن للمستهلك إلغاؤها.

في حال عدم توفّر سمات عناصر ARIA المنعكسة، استخدِم سمة aria-* مستندة إلى id للعلاقات في الشجرة نفسها. لا تتوفّر سمة مكافئة مستندة إلى id للتصنيفات التي تتجاوز الحدود، لذا يمكنك استخدام نص aria-label كحل بديل.