e
Frontend Moscow, October 2019
Léonie Watson, TetraLogical
HTML > DOM > Accessibility Tree > User Interface
<button>
element<button>Play</button>
<button>
element<button>Play</button>
<button>
element<button>
elementclass ToggleButton extends HTMLButtonElement {
constructor() {
super();
}
}
customElements.define("toggle-button", ToggleButton, { extends: "button" });
connectedCallback() {
this.setAttribute("aria-pressed", "false");
this.addEventListener("click", togglePressed);
}
<toggle-button>
elementfunction togglePressed() {
if (this.getAttribute("aria-pressed") == "false") {
this.setAttribute("aria-pressed", "true");
} else {
this.setAttribute("aria-pressed", "false");
}
}
is
attribute<button is="toggle-button">Play</button>
is
attribute<button is="toggle-button" aria-pressed="false">Play</button>
is
attributeis="custom-button"
attributeclass ToggleButton extends HTMLElement {
constructor() {
super();
}
}
customElements.define("toggle-button", ToggleButton);
connectedCallback() {
this.setAttribute("role", "button");
this.setAttribute("tabindex", "0");
this.setAttribute("aria-pressed", "false");
this.addEventListener("click", togglePressed);
this.addEventListener("keydown", function (e) {
if (e.keyCode == 13 || e.keyCode == 32) {
togglePressed();
}
});
}
<toggle-button>
element<toggle-button>Play</toggle-button>
<toggle-button>
element<toggle-button role="button" tabindex="0" aria-pressed="false">Play</toggle-button>
<toggle-button>
element<toggle-button>
elementWeb Platform Incubator Community Group (WICG)
https://wicg.github.io/aom
Will enable reflection of:
Adds two interface mixins to ARIA 1.2
connectedCallback() {
this.role = "button";
this.tabIndex = "0";
this.ariaPressed = "false";
...
}
https://w3c-test.org/wai-aria/idlharness.window.html
Chrome | Edge (Chromium beta) | Firefox | Safari |
82/106 | 82/106 | 1/106 | 86/106 |
connectedCallback() {
this.ariaDescribedByElements = [description1];
...
}
Will enable semantics to be provided in two ways:
class ToggleButton extends HTMLElement {
constructor() {
super();
}
}
customElements.define("toggle-button", ToggleButton, { role: "button", tabIndex: "0" });
class ToggleButton extends HTMLElement {
var internals = null;
constructor() {
super();
this.internals = customElements.createInternals(this);
this.internals.ariaPressed = "false";
}
}
customElements.define("toggle-button", ToggleButton, { role: "button", tabIndex: "0" });
Will enable listening for Assistive Technology (AT) events
To protect AT user privacy, AT events will trigger synthesized DOM events
New AT events will be introduced:
Will allow virtual nodes to be added to the accessibility tree
Will provide access to:
<speak-content>
element<speak-content>
<span slot="control">Speak this</span>
<div slot="speak">1 tequila... 2 tequila... 3 tequila... floor!</div>
</speak-content>
class SpeakContent extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open" });
this.shadowRoot.appendChild(template.content.cloneNode(true));
}
}
const template = document.createElement("template");
template.innerHTML = `<style> ... </style>
<button id="control">
<slot name="control"></slot>
</button>
<slot name="speak" id="speak"></slot>`;
customElements.define("speak-content", SpeakContent);
connectedCallback() {
var control = this.shadowRoot.querySelector("button");
control.setAttribute("aria-pressed", "false");
var speak = this.querySelector("div");
var speakContent = speak.textContent;
control.addEventListener("click", speakThis);
}
function speakThis(e) {
if (control.getAttribute("aria-pressed") == "false") {
control.setAttribute("aria-pressed", "true");
var utterance = new SpeechSynthesisUtterance();
utterance.text = speakContent;
window.speechSynthesis.speak(utterance);
setTimeout(resetPressedState, 500);
}
}
function resetPressedState() {
if (window.speechSynthesis.speaking === false) {
control.setAttribute("aria-pressed", "false");
}
else {
setTimeout(resetPressedState, 500);
}
}
const template = document.createElement("template");
template.innerHTML =
`<style>
...
#control[aria-pressed="true"] {
color: #fff;
padding: 11px 12px 9px 16px;
text-shadow: 0 -1px 0 #444, 0 0 5px #ffd, 0 0 8px #fff;
box-shadow: 0 1px 0 #666, 0 2px 0 #444, 0 2px 2px rgba(0, 0, 0, 0.9);
}
...
</style>`;
<speak-content>
elementLéonie Watson, TetraLogical