@brightspace-ui/core 3.73.0 → 3.73.1
Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
|
|
1
1
|
# Backdrops
|
2
2
|
|
3
|
-
The `d2l-backdrop` element
|
3
|
+
The `d2l-backdrop` element displays a semi-transparent backdrop behind a specified sibling target element. It also hides elements other than the target from assistive technologies by applying `aria-hidden="true"`.
|
4
4
|
|
5
5
|
## Backdrop [d2l-backdrop]
|
6
6
|
|
@@ -9,7 +9,6 @@ The `d2l-backdrop` element is a web component to display a semi-transparent back
|
|
9
9
|
<script type="module">
|
10
10
|
import '@brightspace-ui/core/components/button/button.js';
|
11
11
|
import '@brightspace-ui/core/components/backdrop/backdrop.js';
|
12
|
-
import '@brightspace-ui/core/components/switch/switch.js';
|
13
12
|
|
14
13
|
const backdrop = document.querySelector('d2l-backdrop');
|
15
14
|
document.querySelector('#target > d2l-button').addEventListener('click', () => {
|
@@ -36,3 +35,11 @@ The `d2l-backdrop` element is a web component to display a semi-transparent back
|
|
36
35
|
| `shown` | Boolean | Used to control whether the backdrop is shown |
|
37
36
|
| `slow-transition` | Boolean | Increases the fade transition time to 1200ms (default is 200ms) |
|
38
37
|
<!-- docs: end hidden content -->
|
38
|
+
|
39
|
+
### Focus Management
|
40
|
+
|
41
|
+
Elements with `aria-hidden` applied (as well as their descendants) are completely hidden from assistive technologies. It's therefore very important that the element with active focus be within the backdrop target.
|
42
|
+
|
43
|
+
**When showing a backdrop**: first move focus inside the target, then set the `shown` attribute on the backdrop.
|
44
|
+
|
45
|
+
**When hiding a backdrop**: first remove the `shown` attribute on the backdrop, then if appropriate move focus outside the target.
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import '../colors/colors.js';
|
2
2
|
import { css, html, LitElement } from 'lit';
|
3
|
-
import { cssEscape, getComposedChildren, getComposedParent, isVisible } from '../../helpers/dom.js';
|
3
|
+
import { cssEscape, getComposedChildren, getComposedParent, isComposedAncestor, isVisible } from '../../helpers/dom.js';
|
4
|
+
import { getComposedActiveElement } from '../../helpers/focus.js';
|
4
5
|
|
5
6
|
const BACKDROP_HIDDEN = 'data-d2l-backdrop-hidden';
|
6
7
|
const BACKDROP_ARIA_HIDDEN = 'data-d2l-backdrop-aria-hidden';
|
@@ -12,7 +13,7 @@ const modals = new Set();
|
|
12
13
|
let scrollOverflow = null;
|
13
14
|
|
14
15
|
/**
|
15
|
-
* A component for displaying a semi-transparent backdrop behind a specified sibling element. It also hides elements other than the target from assistive technologies by applying '
|
16
|
+
* A component for displaying a semi-transparent backdrop behind a specified sibling element. It also hides elements other than the target from assistive technologies by applying 'aria-hidden="true"'.
|
16
17
|
*/
|
17
18
|
class Backdrop extends LitElement {
|
18
19
|
|
@@ -85,10 +86,8 @@ class Backdrop extends LitElement {
|
|
85
86
|
disconnectedCallback() {
|
86
87
|
// allow body scrolling, show hidden elements, if backdrop is removed from the DOM
|
87
88
|
allowBodyScroll(this);
|
88
|
-
|
89
|
-
|
90
|
-
this._hiddenElements = null;
|
91
|
-
}
|
89
|
+
showAccessible(this._hiddenElements);
|
90
|
+
this._hiddenElements = null;
|
92
91
|
this._state = null;
|
93
92
|
super.disconnectedCallback();
|
94
93
|
}
|
@@ -106,7 +105,12 @@ class Backdrop extends LitElement {
|
|
106
105
|
|
107
106
|
if (this._state === null) {
|
108
107
|
preventBodyScroll(this);
|
109
|
-
|
108
|
+
const target = this.parentNode.querySelector(`#${cssEscape(this.forTarget)}`);
|
109
|
+
// aria-hidden elements cannot have focus, so wait for focus to be within target
|
110
|
+
waitForFocusWithinTarget(target, Date.now() + 200).then(() => {
|
111
|
+
if (!this.shown || this._state !== 'showing') return;
|
112
|
+
this._hiddenElements = hideAccessible(target);
|
113
|
+
});
|
110
114
|
}
|
111
115
|
this._state = 'showing';
|
112
116
|
|
@@ -188,6 +192,7 @@ function hideAccessible(target) {
|
|
188
192
|
}
|
189
193
|
|
190
194
|
function showAccessible(elems) {
|
195
|
+
if (!elems) return;
|
191
196
|
for (let i = 0; i < elems.length; i++) {
|
192
197
|
const elem = elems[i];
|
193
198
|
if (elem.hasAttribute(BACKDROP_ARIA_HIDDEN)) {
|
@@ -200,4 +205,18 @@ function showAccessible(elems) {
|
|
200
205
|
}
|
201
206
|
}
|
202
207
|
|
208
|
+
async function waitForFocusWithinTarget(target, expireTime) {
|
209
|
+
|
210
|
+
if (Date.now() > expireTime) return;
|
211
|
+
|
212
|
+
const activeElem = getComposedActiveElement();
|
213
|
+
const targetIsAncestor = isComposedAncestor(target, activeElem);
|
214
|
+
|
215
|
+
if (targetIsAncestor) return;
|
216
|
+
|
217
|
+
await new Promise(resolve => requestAnimationFrame(resolve));
|
218
|
+
return waitForFocusWithinTarget(target, expireTime);
|
219
|
+
|
220
|
+
}
|
221
|
+
|
203
222
|
customElements.define('d2l-backdrop', Backdrop);
|
package/custom-elements.json
CHANGED
@@ -189,7 +189,7 @@
|
|
189
189
|
{
|
190
190
|
"name": "d2l-backdrop",
|
191
191
|
"path": "./components/backdrop/backdrop.js",
|
192
|
-
"description": "A component for displaying a semi-transparent backdrop behind a specified sibling element. It also hides elements other than the target from assistive technologies by applying '
|
192
|
+
"description": "A component for displaying a semi-transparent backdrop behind a specified sibling element. It also hides elements other than the target from assistive technologies by applying 'aria-hidden=\"true\"'.",
|
193
193
|
"attributes": [
|
194
194
|
{
|
195
195
|
"name": "for-target",
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@brightspace-ui/core",
|
3
|
-
"version": "3.73.
|
3
|
+
"version": "3.73.1",
|
4
4
|
"description": "A collection of accessible, free, open-source web components for building Brightspace applications",
|
5
5
|
"type": "module",
|
6
6
|
"repository": "https://github.com/BrightspaceUI/core.git",
|