Erişilebilir Web Bileşenleri

Gölge sınırı, semantiğin ve ARIA'nın işleyiş şeklini değiştirir. İki hata öne çıkıyor: Gölge ağacında eksik semantikler ve gölge köklerini geçemedikleri için sessizce bozulan ARIA referansları.

Semantik işaretlemeden başlayın: Şablonda gerçek <button>, <nav>, <ul> kullanın. Böylece çoğu semantik ücretsiz olarak sunulur ve boşluklar için ElementInternals/ARIA'yı ayırın.

ElementInternals ARIA mixin aracılığıyla varsayılan semantikler

Özel bir öğenin rolünü ve ARIA durumunu, ARIA özelliklerini ana makineye yazmak yerine ElementInternals aracılığıyla JS'de ayarlayın. Bu sayede, bileşenin sahip olduğu varsayılan semantikler korunurken tüketicinin Light DOM'daki özelliklerle bunları geçersiz kılmasına olanak tanınır.

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

Bu, DOM'un ARIA özellikleriyle kirlenmesini önler ve tüketicilerin bunları yanlışlıkla bozmasını engeller. Erişilebilirlik ağacı ise doğru rolü ve durumu görmeye devam eder.

Odak yönetimi ve delegatesFocus

  • Ana öğenin kendisi etkileşimli kontrol olduğunda ve rol ile durumu ElementInternals aracılığıyla taşıdığında (yukarıdaki ToggleSwitch gibi), ana öğeyi connectedCallback (if (!this.hasAttribute('tabindex')) this.tabIndex = 0) içindeki sekme sırasına yerleştirin (document.createElement üzerinde hata veren oluşturucuya hiçbir zaman yerleştirmeyin). Böylece odak ana öğeye yönlendirilir ve yardımcı teknoloji, rolünü ve durumunu duyurur. Statik, etkileşimli olmayan bileşenler (ör. açıklama metni veya kart) için ana makinede tabindex değerini ayarlamayın.
  • Bileşen, semantiğe sahip dahili bir odaklanılabilir denetimi sarmaladığında (veya static formAssociated = true içeren formla ilişkili özel bir öğede) gölge kökünü delegatesFocus: true ile ekleyin. Ana makineye odaklanıldığında (ve formla ilişkili öğeler için ilişkili bir <label> tıklandığında) odak, odaklanılabilir ilk alt öğeye yönlendirilir ve :focus, ana makineyle eşleşir. delegatesFocus: true öğesini ana makinedeki bir rol/durum ile birleştirmeyin. Aksi takdirde odak, iç öğeye yönlendirilir ve ana makinenin durumu atlanır.
  • Gezici odaklama veya odağı yeni gösterilen bir bölgeye taşımak için hedefe tabindex="-1" verin ve .focus() yöntemini çağırın. Sekme sırasına güvenmek yerine programatik olarak odaklanılabilir hedefleri açıkça belirtin.

Gölge kökler arasında ARIA ilişkileri

  • ZORUNLU: aria-labelledby, aria-describedby, aria-controls vb. tarafından referans verilen bir id, yalnızca referans veren öğenin kendi ağacında çözümlenir. Light DOM'daki id tabanlı bir özellik, gölge ağacındaki bir id öğesini işaret edemez ve bunun tersi de geçerlidir. Referans sessizce yoksayılır.
  • Sınırı aşmak için kimlikler yerine doğrudan JS öğesi referanslarını alan yansıtılmış ARIA öğe özelliklerini (ör. ariaLabelledByElements, ariaDescribedByElements vb.) kullanın. Dışa doğru çözümlenirler: Gölge ağacındaki bir öğe, Light DOM'daki bir hedefi veya herhangi bir üst ağacı (yuvalı içerik dahil) işaret edebilir. Böylece, Light DOM içeriğinden gölge içi bir denetimi etiketleyebilirsiniz. Bu, id referanslarının ifade edemediği bir şeydir.
  • İçe doğru çözümlenmezler: Bir öğe, alt gölge ağacına referans veremez (ör. bir ana makine kendi gölge içeriğiyle etiketlenemez). Bu yönde, yeni ortaya çıkan Referans Hedef mekanizması standartlar yönüdür ancak henüz geniş çapta kullanıma sunulmamıştır.
  • Bir ilişki her iki şekilde de ifade edilemiyorsa ilişkiyi tek bir ağaçta tutun (etiketi aynı ağaçta oluşturun) veya id referansı yerine aria-label metni kullanın.

Yedek stratejiler

ElementInternals ARIA mixin'inin kullanılamadığı durumlarda, rolü ve ARIA durumunu ana makinede özellik olarak ayarlayın (this.setAttribute('role', 'switch')). Bu yöntem her yerde çalışır ancak tüketicinin geçersiz kılabileceği özellikleri DOM'a yerleştirir.

Yansıtılan ARIA öğe özellikleri kullanılamıyorsa aynı ağaç ilişkileri için id tabanlı bir aria-* özelliği kullanın. Sınır ötesi etiketlerin id tabanlı bir eşdeğeri olmadığından aria-label metnine geri dönün.