From 2faf487638c3383c3c7d260209d70d3a3693def3 Mon Sep 17 00:00:00 2001 From: Matt King Date: Sun, 7 Apr 2024 13:24:23 -0700 Subject: [PATCH 1/5] Refactor of content from PR 1027 --- .../live-regions/live-regions-practice.html | 375 ++++++++++++++++++ 1 file changed, 375 insertions(+) create mode 100644 content/practices/live-regions/live-regions-practice.html diff --git a/content/practices/live-regions/live-regions-practice.html b/content/practices/live-regions/live-regions-practice.html new file mode 100644 index 0000000000..46d577f025 --- /dev/null +++ b/content/practices/live-regions/live-regions-practice.html @@ -0,0 +1,375 @@ + + + + + + + Notifying Users with Live Regions (Automatic Screen Reader Announcements) + + + + + + + + + + +
+

Notifying Users with Live Regions (Automatic Screen Reader Announcements)

+
+

Introduction

+

+ Live regions are perceivable regions of a web page that are typically updated as a result of an external event when user focus might be elsewhere. + These regions are not always updated as a result of a user interaction. + By marking such elements as live regions, users of assistive technology can be informed of the updated content automatically. +

+ +

+ Examples of live regions are a chat log and an error message. + However, different kinds of live regions have different expected behavior; users might expect an error message to disrupt what they are doing, since the error is important, but want to wait with reading new chat messages until they are done typing their own message. +

+
+ +
+

Live Region States and Properties

+ +

+ ARIA has the following attributes mark up live regions. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
State/propertyDescription
aria-liveEnables a live region.
aria-atomicIndicates what content to announce.
aria-relevantIndicates which content changes are relevant.
aria-busyDefers content updates. Not specific to live regions. See the next section. +
+ +
+

Enable Live Regions with aria-live

+ +

+ The aria-live attribute indicates that an element is a live region. + Some roles implicitly set aria-live; this is discussed in a later section. +

+ +
    +
  • assertive: assistive technologies can interrupt the user to provide this information, + but will not move the current focus, so the user's work flow is not interrupted.
  • + +
  • polite: assistive technologies will provide this information after the user is done with + their current task.
  • + +
  • off: assistive technologies will not provide this information unless this region has focus. +
  • +
+ +

+ With the exception of a few roles, the default value of aria-live is off. +

+ +

+ For example, when the user types into a search field, the page could update the page with search results as + the user is typing. + To inform users of assistive technology that this has happened, a polite live region can be used. + When the user is done typing, and the search is complete, the user is informed of how many results were found, + without having to move focus away from the search field. +

+ +
<form role="search" aria-labelledby="search">
+<h2 id="search">Search</h2>
+<label>Search query: <input type="search" name="q" oninput="updateSearch(event)"></label>
+<div id="search-result-status" role="region" aria-live="polite"></div>
+</form>
+<script>
+async function updateSearch(event) {
+const statusElement = document.getElementById('search-result-status');
+const results = await getSearchResults(event.target.value);
+statusElement.textContent = `${results.length} result(s) found.`;
+showResults(results);
+}
+</script>
+
+
+ +
+

Indicate What Content to Announce with aria-atomic

+ +

+ The aria-atomic attribute takes the values "true" and "false". The attribute can also be omitted. +

+ +

+ When this attribute is set to true, assistive technologies will render the element as a whole, + and not just parts that have been changed. +

+ +

+ When this attribute is set to false, assistive technologies will only render the changes (as per + aria-relevant) to the user. +

+ +

+ When this attribute is omitted, the user agent will use the closest ancestor that has aria-atomic + set to true or false, + or if there is no such ancestor, false. +

+ +

+ For example, consider a clock that can be set to notify the user of the current time at a regular interval. + Without aria-atomic, the assistive technology might only notify the changed components, rather + than the full time. +

+ +
<div id="clock" role="region" aria-live="polite" aria-atomic="true">
+The time is
+<span>16</span>:<span>34</span>:<span>05</span>
+</div>
+
+
+ +
+

Indicate Which Content Changes are Relevant with aria-relevant

+ +

+ The aria-relevant attribute can be used to inform assistive technologies about which kinds of + changes are relevant to inform users about. + It takes a list of keywords, with the following meanings: +

+ +
    +
  • additions: Element nodes are added to the accessibility tree within the live region.
  • +
  • text: Text content or a text alternative is added to any descendant in the accessibility tree + of the live region.
  • +
  • removals: Text content, a text alternative, or an element node within the live region is + removed from the accessibility tree.
  • +
  • all: Synonym to additions removals text
  • +
+ +

+ If aria-relevant is not specified, then the value of the closest ancestor element with an + aria-relevant attribute is used. + Specifying the aria-relevant attribute on an element overrides any value specified on an ancestor + element. + If there is no ancestor element with an aria-relevant attribute, the default value + additions text is used. +

+ +

+ For example, a disappearing old message in a chat log is not significant, and users do not need to be informed + of the removal. + However, for a list of online contacts, a disappearing contact is significant (it indicates that the contact + is no longer online). + Instead of announcing the removal of something, it is often better to add new content that tells the user what + happened. + For example, "Alice is now offline" is clearer than "Alice" or "Removed, Alice". + Therefore, avoid using removals or all. +

+ +

+ For example, a list of online contacts: +

+ +
<div role="region" aria-live="polite" aria-labelledby="contacts">
+<h1 id="contacts">Contacts</h1>
+<ul>
+<li aria-atomic="true"><a href="/contacts/alice">Alice</a> is now online</li>
+</ul>
+</div>
+
+ +

+ Note that this example omits the aria-relevant attribute, leaving it as the default value + (additions text). +

+ +

+ When a contact comes online, it is added to the list, and users of assistive technology are informed of the + addition without disrupting their current task. + To communicate what happened, the text is "Alice is now online", rather than only "Alice". +

+ +

+ Similarly when a user goes offline, the text could be changed to "Alice is now offline", + and then be hidden from the list after a timeout. +

+ +

+ If a contact changes their display name, the text change would also be announced: + "Alice has changed their name to 4liz". + After a timeout, the text "Alice has changed their name to " could be removed, without causing a new + announcement. +

+
+ +
+

Triggering Live Regions

+ +

+ Additions and removals in the accessibility tree can happen due to changes to the DOM tree or changes to the + applied CSS. + For example, changing the CSS display property to none causes the element to be + removed from the accessibility tree. + See the Accessibility tree section for more details. +

+
+
+ +
+

Special Case Live Regions

+ +

+ The roles listed below implicitly set the aria-live attribute to indicate that it is a live region. + When using these roles, the aria-live attribute can be omitted, + or it can be specified to change the value from the default. +

+ +
    +
  • alert
  • +
  • log
  • +
  • status
  • +
  • timer
  • +
  • marquee
  • +
+ +
+

Live Region Role alert

+ +

+ The alert role indicates important, usually time-sensitive, information. + Use this role when focus is not moved to the message, and the user is not expected to close the message. + For an alert dialog that can be closed, the the alertdialog role instead. +

+ +

+ The default value for aria-live is assertive. + The default value for aria-atomic is true. +

+ +

+ See the Alert design pattern and the related Alert Example. +

+
+ +
+

Live Region Role log

+ +

+ The log role indicates that new information is added in meaningful order and old information + might disappear. +

+ +

+ The default value for aria-live is polite. +

+ +

+ For example, a chat log would be an appropriate use case for the log role. +

+ +
<h1 id="irc-log">IRC Log</h1>
+<div role="log" aria-labelledby="irc-log">
+<p>[10:26] &lt;Charl> ok let's test it and see if it works</p>
+<p>[10:59] &lt;hsivonen> morning</p>
+</div>
+
+
+ +
+

Live Region Role status

+ +

+ The status role indicates that content is advisory information for the user but is not important + enough to justify an alert, often but not necessarily presented as a status bar. +

+ +

+ The default value for aria-live is polite. + The default value for aria-atomic is true. +

+ +

+ Do not move focus to the element with script when the content is changed. +

+ +

+ For example, the search result summary example above could use role="status" instead of + role="region": +

+ +
<form role="search" aria-labelledby="search">
+<h2 id="search">Search</h2>
+<label>Search query: <input type="search" name="q" oninput="updateSearch(event)"></label>
+<div id="search-result-status" role="status"></div>
+</form>
+
+ +

+ The HTML output element has the status role by default. + The output element is defined to represent the result of a calculation performed by the + application, or the result of a user action. + The result of a user search is thus appropriate use of the output element: +

+ +
<form role="search" aria-labelledby="search">
+<h2 id="search">Search</h2>
+<label>Search query: <input type="search" name="q" oninput="updateSearch(event)"></label>
+<output id="search-result-status"></output>
+</form>
+
+
+ +
+

Live Region Role timer and marquee

+ +

+ Usage of the timer and marquee roles is discouraged. +

+ +

+ The timer role is a numerical counter which indicates an amount of elapsed time from a start + point, or the time remaining until an end point. + The timer role is a subclass of the status role. + The default value of aria-live value of off. +

+ +

+ The marquee role indicates non-essential information that changes frequently. + The default value of aria-live value of off. +

+ +

+ Issue 1104 for the ARIA specification proposes + deprecating these roles. +

+
+
+ + +
+ + + \ No newline at end of file From ffa37766720234c9c65756f36663d2dee66fc874 Mon Sep 17 00:00:00 2001 From: Matt King Date: Tue, 27 Aug 2024 10:00:05 -0700 Subject: [PATCH 2/5] Add link from practices page --- content/practices/practices.html | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/content/practices/practices.html b/content/practices/practices.html index 3f31e1ce80..286b80ee47 100644 --- a/content/practices/practices.html +++ b/content/practices/practices.html @@ -49,6 +49,19 @@

+
  • + +

    + Notifying Users with Live Regions (Automatic Screen Reader Announcements) +

    +
    +
    + Live regions can be used to inform assistive technology users of important changes as they happen. +
    +
  • +
  • Date: Sat, 14 Sep 2024 17:00:33 -0500 Subject: [PATCH 3/5] fixed linting errors --- .../live-regions/live-regions-practice.html | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/content/practices/live-regions/live-regions-practice.html b/content/practices/live-regions/live-regions-practice.html index 46d577f025..abefc555ff 100644 --- a/content/practices/live-regions/live-regions-practice.html +++ b/content/practices/live-regions/live-regions-practice.html @@ -98,19 +98,19 @@

    Enable Live Regions with aria-live

    without having to move focus away from the search field.

    -
    <form role="search" aria-labelledby="search">
    -<h2 id="search">Search</h2>
    -<label>Search query: <input type="search" name="q" oninput="updateSearch(event)"></label>
    -<div id="search-result-status" role="region" aria-live="polite"></div>
    -</form>
    -<script>
    +        
    <form role="search" aria-labelledby="search">
    +<h2 id="search">Search</h2>
    +<label>Search query: <input type="search" name="q" oninput="updateSearch(event)"></label>
    +<div id="search-result-status" role="region" aria-live="polite"></div>
    +</form>
    +<script>
     async function updateSearch(event) {
     const statusElement = document.getElementById('search-result-status');
     const results = await getSearchResults(event.target.value);
     statusElement.textContent = `${results.length} result(s) found.`;
     showResults(results);
     }
    -</script>
    +</script>
     
    @@ -143,10 +143,10 @@

    Indicate What Content to Announce with aria-atomic

    than the full time.

    -
    <div id="clock" role="region" aria-live="polite" aria-atomic="true">
    +        
    <div id="clock" role="region" aria-live="polite" aria-atomic="true">
     The time is
    -<span>16</span>:<span>34</span>:<span>05</span>
    -</div>
    +<span>16</span>:<span>34</span>:<span>05</span>
    +</div>
     
    @@ -192,12 +192,12 @@

    Indicate Which Content Changes are Relevant with aria-relevant< For example, a list of online contacts:

    -
    <div role="region" aria-live="polite" aria-labelledby="contacts">
    -<h1 id="contacts">Contacts</h1>
    -<ul>
    -<li aria-atomic="true"><a href="/contacts/alice">Alice</a> is now online</li>
    -</ul>
    -</div>
    +        
    <div role="region" aria-live="polite" aria-labelledby="contacts">
    +<h1 id="contacts">Contacts</h1>
    +<ul>
    +<li aria-atomic="true"><a href="/contacts/alice">Alice</a> is now online</li>
    +</ul>
    +</div>
     

    @@ -290,11 +290,11 @@

    Live Region Role log

    For example, a chat log would be an appropriate use case for the log role.

    -
    <h1 id="irc-log">IRC Log</h1>
    -<div role="log" aria-labelledby="irc-log">
    -<p>[10:26] &lt;Charl> ok let's test it and see if it works</p>
    -<p>[10:59] &lt;hsivonen> morning</p>
    -</div>
    +        
    <h1 id="irc-log">IRC Log</h1>
    +<div role="log" aria-labelledby="irc-log">
    +<p>[10:26] &lt;Charl> ok let's test it and see if it works</p>
    +<p>[10:59] &lt;hsivonen> morning</p>
    +</div>
     
    @@ -320,11 +320,11 @@

    Live Region Role status

    role="region":

    -
    <form role="search" aria-labelledby="search">
    -<h2 id="search">Search</h2>
    -<label>Search query: <input type="search" name="q" oninput="updateSearch(event)"></label>
    -<div id="search-result-status" role="status"></div>
    -</form>
    +        
    <form role="search" aria-labelledby="search">
    +<h2 id="search">Search</h2>
    +<label>Search query: <input type="search" name="q" oninput="updateSearch(event)"></label>
    +<div id="search-result-status" role="status"></div>
    +</form>
     

    @@ -334,11 +334,11 @@

    Live Region Role status

    The result of a user search is thus appropriate use of the output element:

    -
    <form role="search" aria-labelledby="search">
    -<h2 id="search">Search</h2>
    -<label>Search query: <input type="search" name="q" oninput="updateSearch(event)"></label>
    -<output id="search-result-status"></output>
    -</form>
    +        
    <form role="search" aria-labelledby="search">
    +<h2 id="search">Search</h2>
    +<label>Search query: <input type="search" name="q" oninput="updateSearch(event)"></label>
    +<output id="search-result-status"></output>
    +</form>
     
    @@ -372,4 +372,4 @@

    Live Region Role timer and marquee

    - \ No newline at end of file + From e343d5ffdde2289f4eaaed898c901470f102b09f Mon Sep 17 00:00:00 2001 From: Jon Gunderson Date: Sat, 14 Sep 2024 17:08:06 -0500 Subject: [PATCH 4/5] fixed linting errors --- .../live-regions/live-regions-practice.html | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/content/practices/live-regions/live-regions-practice.html b/content/practices/live-regions/live-regions-practice.html index abefc555ff..ef0ef5578b 100644 --- a/content/practices/live-regions/live-regions-practice.html +++ b/content/practices/live-regions/live-regions-practice.html @@ -99,9 +99,9 @@

    Enable Live Regions with aria-live

    <form role="search" aria-labelledby="search">
    -<h2 id="search">Search</h2>
    -<label>Search query: <input type="search" name="q" oninput="updateSearch(event)"></label>
    -<div id="search-result-status" role="region" aria-live="polite"></div>
    +<h2 id="search">Search</h2>
    +<label>Search query: <input type="search" name="q" oninput="updateSearch(event)"></label>
    +<div id="search-result-status" role="region" aria-live="polite"></div>
     </form>
     <script>
     async function updateSearch(event) {
    @@ -145,7 +145,7 @@ 

    Indicate What Content to Announce with aria-atomic

    <div id="clock" role="region" aria-live="polite" aria-atomic="true">
     The time is
    -<span>16</span>:<span>34</span>:<span>05</span>
    +<span>16</span>:<span>34</span>:<span>05</span>
     </div>
     
    @@ -193,7 +193,7 @@

    Indicate Which Content Changes are Relevant with aria-relevant<

    <div role="region" aria-live="polite" aria-labelledby="contacts">
    -<h1 id="contacts">Contacts</h1>
    +<h1 id="contacts">Contacts</h1>
     <ul>
     <li aria-atomic="true"><a href="/contacts/alice">Alice</a> is now online</li>
     </ul>
    @@ -321,9 +321,9 @@ 

    Live Region Role status

    <form role="search" aria-labelledby="search">
    -<h2 id="search">Search</h2>
    -<label>Search query: <input type="search" name="q" oninput="updateSearch(event)"></label>
    -<div id="search-result-status" role="status"></div>
    +<h2 id="search">Search</h2>
    +<label>Search query: <input type="search" name="q" oninput="updateSearch(event)"></label>
    +<div id="search-result-status" role="status"></div>
     </form>
     
    @@ -335,8 +335,8 @@

    Live Region Role status

    <form role="search" aria-labelledby="search">
    -<h2 id="search">Search</h2>
    -<label>Search query: <input type="search" name="q" oninput="updateSearch(event)"></label>
    +<h2 id="search">Search</h2>
    +<label>Search query: <input type="search" name="q" oninput="updateSearch(event)"></label>
     <output id="search-result-status"></output>
     </form>
     
    From bfc677e55df3fa8fea8ad040d0ce10a287992820 Mon Sep 17 00:00:00 2001 From: Jon Gunderson Date: Sat, 14 Sep 2024 17:13:32 -0500 Subject: [PATCH 5/5] fixed linting errors --- content/practices/live-regions/live-regions-practice.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/practices/live-regions/live-regions-practice.html b/content/practices/live-regions/live-regions-practice.html index ef0ef5578b..5cefbf6eca 100644 --- a/content/practices/live-regions/live-regions-practice.html +++ b/content/practices/live-regions/live-regions-practice.html @@ -292,8 +292,8 @@

    Live Region Role log

    <h1 id="irc-log">IRC Log</h1>
     <div role="log" aria-labelledby="irc-log">
    -<p>[10:26] &lt;Charl> ok let's test it and see if it works</p>
    -<p>[10:59] &lt;hsivonen> morning</p>
    +<p>[10:26] &lt;Mike> ok let's test it and see if it works</p>
    +<p>[10:59] &lt;lori> morning</p>
     </div>