Skip to content

Commit 6347136

Browse files
committed
Allow setting default accessibility semantics for custom elements
1 parent 6773932 commit 6347136

File tree

1 file changed

+159
-7
lines changed

1 file changed

+159
-7
lines changed

source

+159-7
Original file line numberDiff line numberDiff line change
@@ -4015,10 +4015,13 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
40154015
<li><dfn data-x-href="https://w3c.github.io/aria/#aria-label"><code data-x="attr-aria-label">aria-label</code></dfn></li>
40164016
</ul>
40174017

4018-
<p>Finally, the following terms are defined in the ARIA specification: <ref spec=ARIA></p>
4018+
<p>The following terms are defined in the ARIA specification: <ref spec=ARIA></p>
40194019

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

40244027
</dd>
@@ -12840,8 +12843,38 @@ interface <dfn>DOMStringMap</dfn> {
1284012843
<h4 id="wai-aria">Requirements related to ARIA and to platform accessibility APIs</h4>
1284112844

1284212845
<p>User agent requirements for implementing Accessibility API semantics on <span>HTML
12843-
elements</span> are defined in <cite>HTML Accessibility API Mappings</cite>. <ref
12844-
spec=HTMLAAM></p>
12846+
elements</span> are defined in <cite>HTML Accessibility API Mappings</cite>. In addition to the
12847+
rules there, for a <span>custom element</span> <var>element</var>, the default WAI-ARIA role
12848+
semantics are determined as follows: <ref spec=HTMLAAM></p>
12849+
12850+
<ol>
12851+
<li><p>Let <var>map</var> be <var>element</var>'s <span>native accessibility semantics
12852+
map</span>.</p></li>
12853+
12854+
<li><p>If <var>map</var>["<code data-x="">role</code>"] <span data-x="map exists">exists</span>,
12855+
then return it.</p></li>
12856+
12857+
<li><p>Otherwise, return no role.</p></li>
12858+
</ol>
12859+
12860+
<p>Similarly, for a <span>custom element</span> <var>element</var>, the default WAI-ARIA state and
12861+
property semantics, for a state or property named <var>stateOrProperty</var>, are determined as
12862+
follows:</p>
12863+
12864+
<ol>
12865+
<li><p>Let <var>map</var> be <var>element</var>'s <span>native accessibility semantics
12866+
map</span>.</p></li>
12867+
12868+
<li><p>If <var>map</var>[<var>stateOrProperty</var>] <span data-x="map exists">exists</span>,
12869+
then return it.</p></li>
12870+
12871+
<li><p>Otherwise, return the default value for <var>stateOrProperty</var>.</p></li>
12872+
</ol>
12873+
12874+
<p>For an example of this in action, see <a href="#custom-elements-accessibility-example">the
12875+
custom elements section</a>.</p>
12876+
12877+
<hr>
1284512878

1284612879
<p>Conformance checker requirements for checking use of ARIA <code
1284712880
data-x="attr-aria-role">role</code> and <code data-x="attr-aria-*">aria-*</code> attributes on
@@ -66455,6 +66488,61 @@ customElements.define('my-checkbox', MyCheckbox);</code></pre>
6645566488
&lt;/form>
6645666489
</code></pre>
6645766490

66491+
<h5 id="custom-elements-accessibility-example">Creating a custom element with default accessible roles, states, and properties</h5>
66492+
66493+
<!-- NON-NORMATIVE SECTION -->
66494+
66495+
<p>By using the appropriate properties of <code>ElementInternals</code>, your custom element can
66496+
have default accessibility semantics. The following code expands our form-associated checkbox from
66497+
the previous section to properly set its default role and checkedness, as viewed by accessibility
66498+
technology:</p>
66499+
66500+
<pre><code class="js" data-x="">class MyCheckbox extends HTMLElement {
66501+
static get formAssociated() { return true; }
66502+
66503+
constructor() {
66504+
super();
66505+
this._internals = this.attachInternals();
66506+
this._checked = false;
66507+
this.addEventListener('click', this._onClick.bind(this));
66508+
66509+
<mark> this._internals.role = "checkbox";
66510+
this._internals.ariaChecked = false;</mark>
66511+
}
66512+
66513+
get form() { return this._internals.form; }
66514+
get name() { return this.getAttribute('name'); }
66515+
get type() { return this.localName; }
66516+
66517+
get checked() { return this._checked; }
66518+
set checked(flag) {
66519+
this._checked = !!flag;
66520+
this._internals.setFormValue(this._checked ? 'on' : null);
66521+
<mark> this._internals.ariaChecked = this._checked;</mark>
66522+
}
66523+
66524+
_onClick(event) {
66525+
this.checked = !this._checked;
66526+
}
66527+
}
66528+
customElements.define('my-checkbox', MyCheckbox);</code></pre>
66529+
66530+
<p>Note that, like for built-in elements, these are only defaults, and can be overridden by the
66531+
page author using the <code data-x="attr-aria-role">role</code> and <code
66532+
data-x="attr-aria-*">aria-*</code> attributes:</p>
66533+
66534+
<pre class="bad"><code class="html" data-x="">&lt;!-- This markup is non-conforming -->
66535+
&lt;input type="checkbox" checked role="button" aria-checked="false">
66536+
66537+
&lt;my-checkbox role="button" aria-checked="false">
66538+
&lt;script>
66539+
document.querySelector('my-checkbox').checked = true;
66540+
&lt;/script></code></pre>
66541+
66542+
<p>Custom element authors are encouraged to state what aspects of their accessibility semantics
66543+
are strong native semantics, i.e., should not be overriden by users of the custom element. In our
66544+
example, the author of the <code data-x="">my-checkbox</code> element would state that its role
66545+
and aria-checked values are strong native semantics, thus discouraging code such as the above.</p>
6645866546

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

@@ -67987,6 +68075,8 @@ interface <dfn>ElementInternals</dfn> {
6798768075
readonly attribute <span>NodeList</span> <span data-x="dom-ElementInternals-labels">labels</span>;
6798868076
};
6798968077

68078+
ElementInternals includes <span>AccessibilityMixin</span>;
68079+
6799068080
dictionary <dfn>ValidityStateFlags</dfn> {
6799168081
boolean valueMissing = false;
6799268082
boolean typeMismatch = false;
@@ -68058,8 +68148,8 @@ dictionary <dfn>ValidityStateFlags</dfn> {
6805868148
<code data-x="dom-ElementInternals-checkValidity">checkValidity()</code></dt>
6805968149
<dd><p>Returns true if <var>internals</var>'s
6806068150
<span data-x="internals-target">target element</span> has no validity problems; false otherwise.
68061-
Fires an <code data-x="event-invalid">invalid</code> event at the element in the latter case.
68062-
</p></dd>
68151+
Fires an <code data-x="event-invalid">invalid</code> event at the element in the latter
68152+
case.</p></dd>
6806368153

6806468154
<dt><var>valid</var> = <var>internals</var> .
6806568155
<code data-x="dom-ElementInternals-reportValidity">reportValidity()</code></dt>
@@ -68070,8 +68160,19 @@ dictionary <dfn>ValidityStateFlags</dfn> {
6807068160

6807168161
<dt><var>internals</var> . <code data-x="dom-ElementInternals-labels">labels</code></dt>
6807268162
<dd><p>Returns a <code>NodeList</code> of all the <code>label</code> elements that
68073-
<var>internals</var>'s <span data-x="internals-target">target element</span> is associated with.
68074-
</p></dd>
68163+
<var>internals</var>'s <span data-x="internals-target">target element</span> is associated
68164+
with.</p></dd>
68165+
68166+
<dt><var>internals</var> . <a href="#dom-ElementInternals-accessibility-idl-get"><code>role</code></a> [ = <var>value</var> ]</dt>
68167+
<dd><p>Sets or retrieves the default ARIA role for <var>internals</var>'s <span
68168+
data-x="internals-target">target element</span>, which will be used unless the page author
68169+
overrides it using the <code data-x="attr-aria-role">role</code> attribute.</p></dd>
68170+
68171+
<dt><var>internals</var> . <a href="#dom-ElementInternals-accessibility-idl-get"><code>aria*</code></a> [ = <var>value</var> ]</dt>
68172+
<dd><p>Sets or retrieves various default ARIA states or property values for
68173+
<var>internals</var>'s <span data-x="internals-target">target element</span>, which will be used
68174+
unless the page author overrides them using the <code data-x="attr-aria-*">aria-*</code>
68175+
attributes.</p></dd>
6807568176

6807668177
</dl>
6807768178

@@ -68282,6 +68383,57 @@ dictionary <dfn>ValidityStateFlags</dfn> {
6828268383

6828368384
</div>
6828468385

68386+
<hr>
68387+
68388+
<p w-nohtml>By using the <code data-x="">role</code> and <code data-x="">aria*</code> properties
68389+
of <code>ElementInternals</code>, custom element can set default accessibile roles, states, and
68390+
property values for their custom element, similar to how native elements behave. See <a
68391+
href="#custom-elements-accessibility-example">the example above</a> for more details.</p>
68392+
68393+
<div w-nodev>
68394+
68395+
<p>Each <span>custom element</span> has a <dfn>native accessibility semantics map</dfn>, which is
68396+
a <span>map</span>. See the <a href="#wai-aria">Requirements related to ARIA and to platform
68397+
accessibility APIs</a> section for information on how this impacts platform accessibility
68398+
APIs.</p>
68399+
68400+
<p><code>ElementInternals</code> includes the <code>AccessibilityMixin</code> mixin. The IDL
68401+
attributes provided by this mixin are used to manipulate the <span
68402+
data-x="internals-target">target element</span>'s <span>native accessibility semantics
68403+
map</span>, as follows:</p>
68404+
68405+
<p id="dom-ElementInternals-accessibility-idl">To <span>get the accessibility IDL attribute</span>
68406+
for <code>ElementInternals</code>, given <var>internals</var>, <var>idlAttribute</var>, and
68407+
<var>contentAttribute</var>:</p>
68408+
68409+
<ol>
68410+
<li><p>Let <var>map</var> be this <code>ElementInternals</code>'s <span
68411+
data-x="internals-target">target element</span>'s <span>native accessibility semantics
68412+
map</span>.</p></li>
68413+
68414+
<li><p>If <var>map</var>[<var>contentAttribute</var>] <span data-x="map exists">exists</span>,
68415+
then return it.</p></li>
68416+
68417+
<li><p>Return null.</p></li>
68418+
</ol>
68419+
68420+
<p>To <span>set the accessibility IDL attribute</span> for <code>ElementInternals</code>, given
68421+
<var>internals</var>, <var>idlAttribute</var>, <var>contentAttribute</var>, and
68422+
<var>value</var>:</p>
68423+
68424+
<ol>
68425+
<li><p>Let <var>map</var> be this <code>ElementInternals</code>'s <span
68426+
data-x="internals-target">target element</span>'s <span>native accessibility semantics
68427+
map</span>.</p></li>
68428+
68429+
<li><p>If <var>value</var> is null, then <span data-x="map remove">remove</span>
68430+
<var>map</var>[<var>contentAttribute</var>].</p></li>
68431+
68432+
<li><p>Otherwise, set <var>map</var>[<var>contentAttribute</var>] to <var>value</var>.</p></li>
68433+
</ol>
68434+
68435+
</div>
68436+
6828568437
<h3 split-filename="semantics-other" id="common-idioms">Common idioms without dedicated elements</h3>
6828668438

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

0 commit comments

Comments
 (0)