Skip to content

Commit

Permalink
Allow setting default accessibility semantics for custom elements
Browse files Browse the repository at this point in the history
  • Loading branch information
domenic committed Jun 14, 2019
1 parent 4d63c4e commit c18ef3c
Showing 1 changed file with 158 additions and 6 deletions.
164 changes: 158 additions & 6 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -4015,6 +4015,9 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute

<ul class="brief">
<li><dfn data-x-href="https://w3c.github.io/aria/#dfn-accessible-name" data-x="concept-accessible-name">accessible name</dfn></li>
<li>The <dfn data-x-href="https://w3c.github.io/aria/#AccessibilityMixin"><code>AccessibilityMixin</code></dfn> interface, with its associated
<dfn data-x-href="https://w3c.github.io/aria/#dfn-get-the-accessibility-idl-attribute">get the accessibility IDL attribute</dfn> and
<dfn data-x-href="https://w3c.github.io/aria/#dfn-set-the-accessibility-idl-attribute">set the accessibility IDL attribute</dfn> hooks</li>
</ul>

</dd>
Expand Down Expand Up @@ -12833,8 +12836,38 @@ interface <dfn>DOMStringMap</dfn> {
<h4 id="wai-aria">Requirements related to ARIA and to platform accessibility APIs</h4>

<p>User agent requirements for implementing Accessibility API semantics on <span>HTML
elements</span> are defined in <cite>HTML Accessibility API Mappings</cite>. <ref
spec=HTMLAAM></p>
elements</span> are defined in <cite>HTML Accessibility API Mappings</cite>. In addition to the
rules there, for a <span>custom element</span> <var>element</var>, the default WAI-ARIA role
semantics are determined as follows: <ref spec=HTMLAAM></p>

<ol>
<li><p>Let <var>map</var> be <var>element</var>'s <span>native accessibility semantics
map</span>.</p></li>

<li><p>If <var>map</var>["<code data-x="">role</code>"] <span data-x="map exists">exists</span>,
then return it.</p></li>

<li><p>Otherwise, return no role.</p></li>
</ol>

<p>Similarly, for a <span>custom element</span> <var>element</var>, the default WAI-ARIA state and
property semantics, for a state or property named <var>stateOrProperty</var>, are determined as
follows:</p>

<ol>
<li><p>Let <var>map</var> be <var>element</var>'s <span>native accessibility semantics
map</span>.</p></li>

<li><p>If <var>map</var>[<var>stateOrProperty</var>] <span data-x="map exists">exists</span>,
then return it.</p></li>

<li><p>Otherwise, return the default value for <var>stateOrProperty</var>.</p></li>
</ol>

<p>For an example of this in action, see <a href="#custom-elements-accessibility-example">the
custom elements section</a>.</p>

<hr>

<p>Conformance checker requirements for checking use of ARIA <code
data-x="attr-aria-role">role</code> and <code data-x="attr-aria-*">aria-*</code> attributes on
Expand Down Expand Up @@ -66449,6 +66482,61 @@ customElements.define('my-checkbox', MyCheckbox);</code></pre>
&lt;/form>
</code></pre>

<h5 id="custom-elements-accessibility-example">Creating a custom element with default accessible roles, states, and properties</h5>

<!-- NON-NORMATIVE SECTION -->

<p>By using the appropriate properties of <code>ElementInternals</code>, your custom element can
have default accessibility semantics. The following code expands our form-associated checkbox from
the previous section to properly set its default role and checkedness, as viewed by accessibility
technology:</p>

<pre><code class="js" data-x="">class MyCheckbox extends HTMLElement {
static get formAssociated() { return true; }

constructor() {
super();
this._internals = this.attachInternals();
this._checked = false;
this.addEventListener('click', this._onClick.bind(this));

<mark> this._internals.role = "checkbox";
this._internals.ariaChecked = false;</mark>
}

get form() { return this._internals.form; }
get name() { return this.getAttribute('name'); }
get type() { return this.localName; }

get checked() { return this._checked; }
set checked(flag) {
this._checked = !!flag;
this._internals.setFormValue(this._checked ? 'on' : null);
<mark> this._internals.ariaChecked = this._checked;</mark>
}

_onClick(event) {
this.checked = !this._checked;
}
}
customElements.define('my-checkbox', MyCheckbox);</code></pre>

<p>Note that, like for built-in elements, these are only defaults, and can be overridden by the
page author using the <code data-x="attr-aria-role">role</code> and <code
data-x="attr-aria-*">aria-*</code> attributes:</p>

<pre class="bad"><code class="html" data-x="">&lt;!-- This markup is non-conforming -->
&lt;input type="checkbox" checked role="button" aria-checked="false">

&lt;my-checkbox role="button" aria-checked="false">
&lt;script>
document.querySelector('my-checkbox').checked = true;
&lt;/script></code></pre>

<p>Custom element authors are encouraged to state what aspects of their accessibility semantics
are strong native semantics, i.e., should not be overriden by users of the custom element. In our
example, the author of the <code data-x="">my-checkbox</code> element would state that its role
and aria-checked values are strong native semantics, thus discouraging code such as the above.</p>

<h5 id="custom-elements-customized-builtin-example">Creating a customized built-in element</h5>

Expand Down Expand Up @@ -67995,6 +68083,8 @@ interface <dfn>ElementInternals</dfn> {
readonly attribute <span>NodeList</span> <span data-x="dom-ElementInternals-labels">labels</span>;
};

ElementInternals includes <span>AccessibilityMixin</span>;

dictionary <dfn>ValidityStateFlags</dfn> {
boolean valueMissing = false;
boolean typeMismatch = false;
Expand Down Expand Up @@ -68066,8 +68156,8 @@ dictionary <dfn>ValidityStateFlags</dfn> {
<code data-x="dom-ElementInternals-checkValidity">checkValidity()</code></dt>
<dd><p>Returns true if <var>internals</var>'s
<span data-x="internals-target">target element</span> has no validity problems; false otherwise.
Fires an <code data-x="event-invalid">invalid</code> event at the element in the latter case.
</p></dd>
Fires an <code data-x="event-invalid">invalid</code> event at the element in the latter
case.</p></dd>

<dt><var>valid</var> = <var>internals</var> .
<code data-x="dom-ElementInternals-reportValidity">reportValidity()</code></dt>
Expand All @@ -68078,8 +68168,19 @@ dictionary <dfn>ValidityStateFlags</dfn> {

<dt><var>internals</var> . <code data-x="dom-ElementInternals-labels">labels</code></dt>
<dd><p>Returns a <code>NodeList</code> of all the <code>label</code> elements that
<var>internals</var>'s <span data-x="internals-target">target element</span> is associated with.
</p></dd>
<var>internals</var>'s <span data-x="internals-target">target element</span> is associated
with.</p></dd>

<dt><var>internals</var> . <a href="#dom-ElementInternals-accessibility-idl-get"><code>role</code></a> [ = <var>value</var> ]</dt>
<dd><p>Sets or retrieves the default ARIA role for <var>internals</var>'s <span
data-x="internals-target">target element</span>, which will be used unless the page author
overrides it using the <code data-x="attr-aria-role">role</code> attribute.</p></dd>

<dt><var>internals</var> . <a href="#dom-ElementInternals-accessibility-idl-get"><code>aria*</code></a> [ = <var>value</var> ]</dt>
<dd><p>Sets or retrieves various default ARIA states or property values for
<var>internals</var>'s <span data-x="internals-target">target element</span>, which will be used
unless the page author overrides them using the <code data-x="attr-aria-*">aria-*</code>
attributes.</p></dd>

</dl>

Expand Down Expand Up @@ -68290,6 +68391,57 @@ dictionary <dfn>ValidityStateFlags</dfn> {

</div>

<hr>

<p w-nohtml>By using the <code data-x="">role</code> and <code data-x="">aria*</code> properties
of <code>ElementInternals</code>, custom element can set default accessibile roles, states, and
property values for their custom element, similar to how native elements behave. See <a
href="#custom-elements-accessibility-example">the example above</a> for more details.</p>

<div w-nodev>

<p>Each <span>custom element</span> has a <dfn>native accessibility semantics map</dfn>, which is
a <span>map</span>. See the <a href="#wai-aria">Requirements related to ARIA and to platform
accessibility APIs</a> section for information on how this impacts platform accessibility
APIs.</p>

<p><code>ElementInternals</code> includes the <code>AccessibilityMixin</code> mixin. The IDL
attributes provided by this mixin are used to manipulate the <span
data-x="internals-target">target element</span>'s <span>native accessibility semantics
map</span>, as follows:</p>

<p id="dom-ElementInternals-accessibility-idl">To <span>get the accessibility IDL attribute</span>
for <code>ElementInternals</code>, given <var>internals</var>, <var>idlAttribute</var>, and
<var>contentAttribute</var>:</p>

<ol>
<li><p>Let <var>map</var> be this <code>ElementInternals</code>'s <span
data-x="internals-target">target element</span>'s <span>native accessibility semantics
map</span>.</p></li>

<li><p>If <var>map</var>[<var>contentAttribute</var>] <span data-x="map exists">exists</span>,
then return it.</p></li>

<li><p>Return null.</p></li>
</ol>

<p>To <span>set the accessibility IDL attribute</span> for <code>ElementInternals</code>, given
<var>internals</var>, <var>idlAttribute</var>, <var>contentAttribute</var>, and
<var>value</var>:</p>

<ol>
<li><p>Let <var>map</var> be this <code>ElementInternals</code>'s <span
data-x="internals-target">target element</span>'s <span>native accessibility semantics
map</span>.</p></li>

<li><p>If <var>value</var> is null, then <span data-x="map remove">remove</span>
<var>map</var>[<var>contentAttribute</var>].</p></li>

<li><p>Otherwise, set <var>map</var>[<var>contentAttribute</var>] to <var>value</var>.</p></li>
</ol>

</div>

<h3 split-filename="semantics-other" id="common-idioms">Common idioms without dedicated elements</h3>

<h4 id="rel-up">Bread crumb navigation</h4>
Expand Down

0 comments on commit c18ef3c

Please sign in to comment.