Skip to content

Commit 92daafe

Browse files
Merge pull request #1 from geospatialem/kelly-describedby-update
feat: add demo app that uses describedby and live regions
2 parents 20b616c + d0b226a commit 92daafe

File tree

8 files changed

+348
-0
lines changed

8 files changed

+348
-0
lines changed

demos/description-region/README.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Esri Developer & Technology Summit Template - Map Description
2+
3+
## Project Description
4+
5+
This application demonstrates how to enhance accessibility by setting the `aria-describedby` attribute for the map element. Additionally, it showcases the use of `aria-live` regions to provide dynamic updates for assistive technologies. Note: Some assistive technologies such as [Narrator](https://a11ysupport.io/tech/aria/aria-describedby_attribute) may not support aria-describedby
6+
7+
## Testing `aria-describedby`
8+
9+
### Using Chrome Developer Tools
10+
11+
1. Open your application in Google Chrome.
12+
2. Right-click on the map element and select "Inspect" to open the Developer Tools.
13+
3. In the Elements panel, ensure the map element has the `aria-describedby` attribute set.
14+
4. Verify that the value of `aria-describedby` corresponds to the ID of the element containing the description.
15+
16+
### Using a Screen Reader
17+
18+
1. Open your application in a web browser.
19+
2. Activate your screen reader (e.g., NVDA, JAWS, VoiceOver).
20+
3. Navigate to the map element using the screen reader's navigation commands.
21+
4. Listen to the description read by the screen reader, ensuring it matches the content of the element referenced by `aria-describedby`.
22+
23+
## Accessibility Information
24+
25+
The `aria-describedby` attribute is used to provide additional descriptive information for an element, which can be especially useful for users of assistive technologies. By linking the element to another element that contains the description, screen readers can convey more context and details to users, enhancing their understanding and interaction with the web content. This is particularly important for complex elements like maps, where visual information needs to be translated into meaningful text descriptions.
26+
27+
### Why Use `aria-describedby` Instead of `aria-label`
28+
29+
While both `aria-describedby` and `aria-label` are used to provide accessible descriptions, they serve different purposes. The `aria-label` attribute is used to provide a concise, accessible name for an element, which is typically short and to the point. In contrast, `aria-describedby` is used to link an element to another element that contains a more detailed description. This is particularly useful for complex elements like maps, where a brief label would not suffice to convey all necessary information. By using `aria-describedby`, we can provide users with assistive technologies a richer, more informative description that enhances their understanding and interaction with the map.
30+
31+
For more information on how to use `aria-describedby`, refer to the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-describedby).
32+
33+
## Understanding `aria-live`
34+
35+
The `aria-live` attribute is used to indicate that an element will be updated dynamically, and that those updates should be communicated to assistive technologies. This is particularly useful for content that changes frequently or asynchronously, such as notifications, chat messages, or live sports scores.
36+
37+
### How `aria-live` Works
38+
39+
When an element has the `aria-live` attribute, screen readers will monitor changes to the content of that element and announce those changes to the user. The `aria-live` attribute can take several values:
40+
41+
- **off**: Default value. Updates are not announced.
42+
- **polite**: Updates are announced at the next available opportunity, allowing the user to finish their current task without interruption.
43+
-- **assertive**: Updates are announced immediately, interrupting the current task. This should be used sparingly and only for critical updates.
44+
+- **assertive**: Updates are announced immediately, interrupting the current task. **This should be used sparingly and only for critical updates.**
45+
46+
### When to Use `aria-live`
47+
48+
Use `aria-live` in scenarios where dynamic content updates need to be communicated to users of assistive technologies. Examples include:
49+
50+
- **Notifications**: Announcing new messages or alerts.
51+
- **Form Validation**: Informing users of errors or successful submissions.
52+
- **Live Data**: Updating users with real-time information, such as stock prices or sports scores.
53+
54+
By appropriately using `aria-live`, developers can ensure that dynamic content is accessible and that users are kept informed of important updates without unnecessary interruptions.
55+
56+
For more information on how to use `aria-live`, refer to the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions).
57+
58+
## WCAG Requirements for `aria-describedby`
59+
60+
The Web Content Accessibility Guidelines (WCAG) provide recommendations for making web content more accessible. The use of the `aria-describedby` attribute aligns with several WCAG success criteria, including:
61+
62+
- **1.1.1 Non-text Content**: Ensures that all non-text content that is presented to the user has a text alternative that serves the equivalent purpose.
63+
- **1.3.1 Info and Relationships**: Ensures that information, structure, and relationships conveyed through presentation can be programmatically determined or are available in text.
64+
- **4.1.2 Name, Role, Value**: Ensures that for all user interface components, the name and role can be programmatically determined, and states, properties, and values that can be set by the user can be programmatically set and notified to the user agents, including assistive technologies.
65+
66+
By using `aria-describedby`, developers can provide additional context and descriptions for elements, which helps meet these WCAG criteria and improves the overall accessibility of web applications.
67+
68+
For more detailed information on WCAG, visit the [W3C Web Accessibility Initiative (WAI) website](https://www.w3.org/WAI/standards-guidelines/wcag/).

demos/description-region/app.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
const toggleModeEl = document.getElementById("toggle-mode");
2+
const mapEl = document.querySelector("arcgis-map");
3+
const darkModeCss = document.getElementById("jsapi-mode-dark");
4+
const lightModeCss = document.getElementById("jsapi-mode-light");
5+
const liveRegion = document.getElementById("liveRegion");
6+
7+
let mode = "light";
8+
9+
toggleModeEl.addEventListener("click", handleModeChange);
10+
mapEl.addEventListener("arcgisViewReadyChange", handleArcgisViewReadyChange);
11+
12+
function handleArcgisViewReadyChange(event) {
13+
const mapDescription = document.getElementById("map-description");
14+
const { portalItem } = event.target.map;
15+
liveRegion.innerText = `${portalItem.title} map has loaded.`;
16+
mapDescription.innerText = portalItem.snippet;
17+
document.querySelectorAll(".esri-view-surface").forEach(el =>
18+
el.setAttribute("aria-describedby", "map-description")
19+
);
20+
}
21+
22+
function handleModeChange() {
23+
mode = mode === "dark" ? "light" : "dark";
24+
const isDarkMode = mode === "dark";
25+
darkModeCss.disabled = !isDarkMode;
26+
lightModeCss.disabled = isDarkMode;
27+
toggleModeEl.icon = isDarkMode ? "moon" : "brightness";
28+
document.body.className = isDarkMode ? "calcite-mode-dark" : "";
29+
30+
document.querySelectorAll(`.calcite-mode-${isDarkMode ? "light" : "dark"}`).forEach(node =>
31+
node.classList.replace(`calcite-mode-${isDarkMode ? "light" : "dark"}`, `calcite-mode-${mode}`)
32+
);
33+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<html lang="en">
2+
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" />
6+
<title>2025 Esri Developer & Technology Summit - Map Description and Live Updates</title>
7+
8+
<!-- Calcite imports -->
9+
<script type="module" src="https://js.arcgis.com/calcite-components/3.0.3/calcite.esm.js"></script>
10+
11+
12+
<!-- ArcGIS Maps SDK for JavaScript imports -->
13+
<script src="https://js.arcgis.com/4.32/"></script>
14+
<link id="jsapi-mode-light" rel="stylesheet" href="https://js.arcgis.com/4.32/esri/themes/light/main.css" />
15+
<link disabled id="jsapi-mode-dark" rel="stylesheet" href="https://js.arcgis.com/4.32/esri/themes/dark/main.css" />
16+
<script type="module" src="https://js.arcgis.com/map-components/4.32/arcgis-map-components.esm.js"></script>
17+
18+
<!-- Demo imports -->
19+
<script src="./app.js" defer></script>
20+
<link rel="stylesheet" href="./style.css" />
21+
</head>
22+
23+
<body>
24+
<calcite-shell content-behind>
25+
<calcite-navigation slot="header" id="nav">
26+
<calcite-navigation-logo href="#" icon="accessibility" alt="Application logo" slot="logo"
27+
heading="Map Description and Live Regions"
28+
description="Esri Developer & Technology Summit 2025"></calcite-navigation-logo>
29+
<calcite-action-pad layout="horizontal" expand-disabled slot="content-end">
30+
<calcite-action id="toggle-mode" text="Toggle mode" icon="brightness"></calcite-action>
31+
</calcite-action-pad>
32+
33+
<calcite-tooltip placement="bottom" reference-element="toggle-mode" slot="content-end">Toggle
34+
mode</calcite-tooltip>
35+
</calcite-navigation>
36+
<arcgis-map item-id="05e015c5f0314db9a487a9b46cb37eca">
37+
<div id="liveRegion" aria-live="polite" class="sr-only"></div>
38+
<p id="map-description" class="sr-only"></p>
39+
</arcgis-map>
40+
</calcite-shell>
41+
42+
</body>
43+
44+
</html>

demos/description-region/style.css

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/* Esri Developer & Technology Summit Demo Template */
2+
/* Demo template theming example */
3+
4+
body calcite-navigation-logo{
5+
--calcite-color-text-2:#737373;
6+
}
7+
body.calcite-mode-dark calcite-navigation-logo{
8+
--calcite-icon-color:#8FD0FF;
9+
--calcite-color-text-2:#C7C7C7;
10+
}
11+
12+
13+
html,
14+
body,
15+
arcgis-map {
16+
padding: 0;
17+
margin: 0;
18+
height: 100%;
19+
width: 100%;
20+
}
21+
22+
calcite-shell-panel[slot="panel-start"] calcite-panel {
23+
border-top: 0;
24+
}
25+
26+
.sr-only {
27+
position: absolute;
28+
width: 1px;
29+
height: 1px;
30+
padding: 0;
31+
margin: -1px;
32+
overflow: hidden;
33+
clip: rect(0,0,0,0);
34+
border: 0;
35+
}

demos/reduced-motion/README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Esri Developer & Technology Summit - Prefers Reduced Motion
2+
3+
## Project Description
4+
5+
This demo app demonstrates how to respect the `prefers-reduced-motion` settings in CSS. It showcases how to read the CSS setting for `prefers-reduced-motion` and disables animations accordingly. Additionally, the app provides a play/pause button so users can re-enable animations if they prefer.
6+
7+
## How to Test `prefers-reduced-motion` with Chrome Developer Tools
8+
9+
To test the `prefers-reduced-motion` setting in Chrome Developer Tools, follow these steps:
10+
11+
1. Open Chrome Developer Tools (F12 or right-click on the page and select "Inspect").
12+
2. Go to the "Rendering" tab.
13+
3. Under the "Emulate CSS media feature prefers-reduced-motion" section, select "Reduce".
14+
15+
For more detailed instructions, refer to the [Chrome Developer Tools Documentation](https://developer.chrome.com/docs/devtools/).
16+
17+
## Accessibility Information
18+
19+
The `prefers-reduced-motion` media query is an important accessibility feature that allows users to reduce or eliminate animations and transitions that can cause motion sickness, distraction, or other issues. For more information on `prefers-reduced-motion` and its impact, visit the following resources:
20+
21+
- [MDN Web Docs: prefers-reduced-motion](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion)
22+
- [WebAIM: Animation and Accessibility](https://webaim.org/techniques/css/#animation)
23+
24+
## WCAG Requirements for Reduced Motion
25+
26+
The Web Content Accessibility Guidelines (WCAG) include specific criteria related to motion and animations to ensure web content is accessible to all users, including those with vestibular disorders. The relevant WCAG criterion is:
27+
28+
### WCAG 2.1 - Guideline 2.3: Seizures and Physical Reactions
29+
30+
**Success Criterion 2.3.3: Animation from Interactions (Level AAA)**
31+
32+
- Motion animation triggered by interaction can be disabled unless the animation is essential to the functionality or the information being conveyed.
33+
34+
For more information on WCAG requirements related to reduced motion, refer to the following resources:
35+
36+
- [WCAG 2.1 Guideline 2.3: Seizures and Physical Reactions](https://www.w3.org/WAI/WCAG21/quickref/#seizures-and-physical-reactions)
37+
- [Understanding Success Criterion 2.3.3: Animation from Interactions](https://www.w3.org/WAI/WCAG21/Understanding/animation-from-interactions.html)
38+
39+
By adhering to these guidelines, this app helps to provide a more accessible experience for users who may be adversely affected by motion and animations.

demos/reduced-motion/app.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
const navigationEl = document.getElementById("nav");
3+
4+
const arcgisMap = document.querySelector("arcgis-map");
5+
6+

demos/reduced-motion/index.html

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<html lang="en">
2+
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
6+
<title>2025 Esri Developer & Technology Summit - Reduced Motion</title>
7+
8+
<!-- Calcite import -->
9+
<script type="module" src="https://js.arcgis.com/calcite-components/3.0.3/calcite.esm.js"></script>
10+
11+
<!-- ArcGIS Maps SDK for JavaScript imports -->
12+
<script src="https://js.arcgis.com/4.32/"></script>
13+
<link id="jsapi-mode-light" rel="stylesheet" href="https://js.arcgis.com/4.32/esri/themes/light/main.css" />
14+
<link disabled id="jsapi-mode-dark" rel="stylesheet" href="https://js.arcgis.com/4.32/esri/themes/dark/main.css" />
15+
<script type="module" src="https://js.arcgis.com/map-components/4.32/arcgis-map-components.esm.js"></script>
16+
17+
<!-- Demo imports -->
18+
<script src="./app.js" defer></script>
19+
<link rel="stylesheet" href="./style.css" />
20+
</head>
21+
22+
<body>
23+
<calcite-shell content-behind>
24+
<calcite-navigation slot="header" id="nav">
25+
<calcite-navigation-logo href="#" icon="accessibility" alt="Application logo" slot="logo" heading="Reduced Motion"
26+
description="Esri Developer & Technology Summit 2025"></calcite-navigation-logo>
27+
28+
</calcite-navigation>
29+
30+
<calcite-shell-panel slot="panel-end" display-mode="float">
31+
<calcite-panel heading="Maps SDK for JavaScript" description="Showcased product">
32+
<calcite-action id="toggle-instructions" text="Instructions" icon="lightbulb"
33+
slot="header-actions-end"></calcite-action>
34+
<calcite-tooltip placement="bottom" reference-element="toggle-instructions" slot="header-actions-end">A quick
35+
get-going hint about this demo</calcite-tooltip>
36+
<calcite-block collapsible heading="Layer effects" description="Adjust blur, highlight, and order">
37+
<calcite-icon scale="s" slot="icon" icon="effects"></calcite-icon>
38+
<calcite-notice open>
39+
<div slot="message">Use layer effects sparingly, for emphasis</div>
40+
</calcite-notice>
41+
</calcite-block>
42+
43+
<calcite-block collapsible heading="Symbology" description="Select type, color, and transparency">
44+
<calcite-icon scale="s" slot="icon" icon="map-pin"></calcite-icon>
45+
<calcite-label>
46+
Effect type
47+
<calcite-segmented-control width="full">
48+
<calcite-segmented-control-item value="Blur">Blur</calcite-segmented-control-item>
49+
<calcite-segmented-control-item checked value="Highlight">Highlight</calcite-segmented-control-item>
50+
</calcite-segmented-control>
51+
</calcite-label>
52+
53+
<calcite-label>
54+
Something
55+
<calcite-input placeholder="A great placeholder"></calcite-input>
56+
</calcite-label>
57+
<calcite-label>
58+
Something numerical<calcite-input-number value="25" placeholder="--" suffix-text="%"
59+
alignment="end"></calcite-input-number>
60+
</calcite-label>
61+
</calcite-block>
62+
63+
<calcite-fab slot="fab" text="Add something" text-enabled></calcite-fab>
64+
65+
66+
</calcite-panel>
67+
</calcite-shell-panel>
68+
69+
<arcgis-map item-id="05e015c5f0314db9a487a9b46cb37eca"> </arcgis-map>
70+
</calcite-shell>
71+
72+
73+
</body>
74+
75+
</html>

demos/reduced-motion/style.css

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
body calcite-navigation-logo{
2+
--calcite-color-text-2:#737373;
3+
}
4+
body.calcite-mode-dark calcite-navigation-logo{
5+
--calcite-icon-color:#8FD0FF;
6+
--calcite-color-text-2:#C7C7C7;
7+
}
8+
9+
10+
11+
html,
12+
body,
13+
arcgis-map {
14+
padding: 0;
15+
margin: 0;
16+
height: 100%;
17+
width: 100%;
18+
}
19+
20+
calcite-menu-item {
21+
--calcite-menu-background-color: var(--calcite-color-background);
22+
}
23+
24+
calcite-navigation-logo {
25+
--calcite-navigation-logo-heading-color: var(--calcite-color-brand);
26+
}
27+
28+
calcite-shell-panel[slot="panel-start"] calcite-panel {
29+
border-top: 0;
30+
}
31+
32+
calcite-action-pad {
33+
margin-inline-end: 0.5rem;
34+
}
35+
36+
#modal hr {
37+
margin: 1rem 0;
38+
border: 0;
39+
border-bottom: 1px solid var(--calcite-color-border-3);
40+
}
41+
42+
#modal ul li {
43+
margin-bottom: 0.5rem;
44+
}
45+
46+
#modal calcite-notice {
47+
margin-bottom: 1.25rem;
48+
}

0 commit comments

Comments
 (0)