w3c / aria-practices

WAI-ARIA Authoring Practices Guide (APG)
https://www.w3.org/wai/aria/apg/
Other
1.21k stars 345 forks source link

Provide custom element versions of code examples #161

Open ZoeBijl opened 7 years ago

ZoeBijl commented 7 years ago

@robdodson and I talked the other day and he asked whether we’d approve custom elements in code examples. I said that it would hide most of the ARIA stuff so wouldn’t be appropriate as the only way to present the example, but this is definitely something that we should consider for APG 2.0.

robdodson commented 7 years ago

👍

My hope is that it can still show off using ARIA but it would predominantly be in JS as the element self-applies attributes. Here's an example radio-group i've been working on:

// Define values for keycodes
const VK_LEFT       = 37;
const VK_UP         = 38;
const VK_RIGHT      = 39;
const VK_DOWN       = 40;

class RadioGroup extends HTMLElement {
  constructor() {
    super();
  }

  connectedCallback() {
    this.setAttribute('role', 'radiogroup');
    this.radios = Array.from(this.querySelectorAll('radio-button'));

    // Setup initial state
    if (this.hasAttribute('selected')) {
      let selected = this.getAttribute('selected');
      this._selected = selected;
      this.radios[selected].setAttribute('tabindex', 0);
      this.radios[selected].setAttribute('aria-checked', true);
    } else {
      this._selected = 0;
      this.radios[0].setAttribute('tabindex', 0);
    }

    this.addEventListener('keydown', this.handleKeyDown.bind(this));
    this.addEventListener('click', this.handleClick.bind(this));
  }

  handleKeyDown(e) {
    switch(e.keyCode) {

      case VK_UP:
      case VK_LEFT: {
        e.preventDefault();

        if (this.selected === 0) {
          this.selected = this.radios.length - 1;
        } else {
          this.selected--;
        }
        break;

      }

      case VK_DOWN:
      case VK_RIGHT: {
        e.preventDefault();

        if (this.selected === this.radios.length - 1) {
          this.selected = 0;
        } else {
          this.selected++;
        }
        break;
      }

    }
  }

  handleClick(e) {
    const idx = this.radios.indexOf(e.target);
    if (idx === -1) {
      return;
    }
    this.selected = idx;
  }

  set selected(idx) {
    if (isFinite(this.selected)) {
      // Set the old button to tabindex -1
      let previousSelected = this.radios[this.selected];
      previousSelected.tabIndex = -1;
      previousSelected.setAttribute('aria-checked', false);
    }

    // Set the new button to tabindex 0 and focus it
    let newSelected = this.radios[idx];
    newSelected.tabIndex = 0;
    newSelected.focus();
    newSelected.setAttribute('aria-checked', true);

    this.setAttribute('selected', idx);
    this._selected = idx;
  }

  get selected() {
    return this._selected;
  }
}

window.customElements.define('radio-group', RadioGroup);
mcking65 commented 7 years ago

Not opposed. Agree that we should not make a near term priority. Given the goals of the APG, I am curious what the primary objective or benefit would be?

ZoeBijl commented 7 years ago

@bkardell might have an opinion on this too.

bkardell commented 7 years ago

@MichielBijl I do indeed! I think perhaps we talked about "UL Listing"? I need to write a blog post I think. I'm not sure this is the right venue - would it link to?

mcking65 commented 7 years ago

Brian, Michiel,

In the Authoring Practices, we endeavor to explain and demonstrate correct application of ARIA primarily for engineers, designers, testers, and assistive technology developers. For the 1.1 guide, we agreed to do this with an emphasis on reference examples of core design patterns implemented in vanilla html/css/js (no libs). We agreed to focus on what the audience needs to know about ARIA with the base assumption that readers are experts in their various professions. Thus, we do not demonstrate every possible way of coding; we are focused on illustrating practices that directly effect the usability of UIs for people with disabilities. To the extent possible, we are avoiding diving into engineering topics like browser compatibility or design topics like when to choose a specific pattern.

Of course, we can expand scope for 2.0 if we believe it will make the guide more effective.

Nonetheless, given this, what would be the primary benefits of having additional implementations of the design patterns in custom components? Is it something more than showing another way to code? Are there accessibility advantages that can be achieved with custom components?

@bkardell, what do you mean by "UL listing"?

bkardell commented 7 years ago

@mcking65 I'll write a post explaining it soon and share back here. It's just an analogy I've been using while discussing this topic in person for the last few months.

robdodson commented 7 years ago

Nonetheless, given this, what would be the primary benefits of having additional implementations of the design patterns in custom components? Is it something more than showing another way to code?

There are a few reasons why I'm personally excited about custom elements from an accessibility standpoint.

The first is that they are entirely standards based. As you mentioned, you want examples to not be dependent on libraries but I believe a number of the current examples rely on jQuery. Custom elements, on the other hand, really are vanilla HTML, CSS, and JavaScript. The bonuses that they give are a well defined set of lifecycle callbacks, so examples can be more consistent, plus they automatically upgrade once their definitions are loaded. This means users don't have to figure out where in their application lifecycle they need to call an element constructor to activate things. So long as they load the script for the element, the parser will handle upgrading them.

Are there accessibility advantages that can be achieved with custom components?

This is just my personal opinion, but it seems like developers are headed in the direction of component first architecture. I'm basing this assumption on the popularity of libraries like React, Angular, Ember, Polymer, etc. Being able to compose an application out of components that have built-in accessibility, hopefully, makes it easier for developers to build accessible apps. While they might shy away from having to wire together their own tablist using divs, they may be perfectly happy using a <tablist> custom element that self applies the appropriate ARIA attributes and comes with proper keyboard support. Since custom elements are designed to be framework interoperable, my long term hope is that by encouraging developers to build high quality, accessible custom elements today, in a few years time there will be a number of known good implementations of the patterns that any developer can use in their app, regardless of framework or library, and just treat them as accessible native elements.

ZoeBijl commented 7 years ago

@bkardell I think we talked about something that was implemented in 700 different ways (believe it was icons) which your devs fixed with a component.

@robdodson yes, very much this!

my long term hope is that by encouraging developers to build high quality, accessible custom elements today, in a few years time there will be a number of known good implementations of the patterns that any developer can use in their app, regardless of framework or library, and just treat them as accessible native elements.

@mcking65 you make a good point in that this might be an extracurricular activity. I've been thinking about creating a general authoring practices guide that focusses on how to properly build design patterns period. In that the focus wouldn't be only on accessibility.

That said, it would be cool if that could be an extension of the APG, but maybe I'm thinking too far ahead.

ZoeBijl commented 7 years ago

Also, WebKit just announced it’ll support Custom Elements!