@remit/web-client 0.0.213 → 0.0.214
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remit/web-client",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.214",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Remit web client, published as composable primitives — the app shell, auth shells, and runtime config. A distributor imports what it composes and bundles it.",
|
|
6
6
|
"exports": {
|
|
@@ -206,6 +206,39 @@ describe("Drawer's ring is what a reader can reach", () => {
|
|
|
206
206
|
|
|
207
207
|
assert.equal(document.activeElement, named("Cancel"));
|
|
208
208
|
});
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* The pane renders that dialog without moving focus into it, so focus sits
|
|
212
|
+
* on the drawer control that opened it — now behind the dialog's backdrop.
|
|
213
|
+
* Tab has to enter the dialog's ring rather than walk the controls the
|
|
214
|
+
* backdrop covers.
|
|
215
|
+
*/
|
|
216
|
+
it("pulls focus behind a nested dialog's backdrop into its ring", () => {
|
|
217
|
+
const nestedDialog = createElement(
|
|
218
|
+
"div",
|
|
219
|
+
{
|
|
220
|
+
key: "nested",
|
|
221
|
+
role: "dialog",
|
|
222
|
+
"aria-modal": "true",
|
|
223
|
+
"aria-label": "Reclassify sender",
|
|
224
|
+
},
|
|
225
|
+
button("automated"),
|
|
226
|
+
button("Cancel"),
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
open(createElement(Fragment, null, button("trigger"), nestedDialog));
|
|
230
|
+
named("trigger").focus();
|
|
231
|
+
|
|
232
|
+
press("Tab");
|
|
233
|
+
|
|
234
|
+
assert.equal(document.activeElement, named("automated"));
|
|
235
|
+
|
|
236
|
+
named("trigger").focus();
|
|
237
|
+
|
|
238
|
+
press("Tab", true);
|
|
239
|
+
|
|
240
|
+
assert.equal(document.activeElement, named("Cancel"));
|
|
241
|
+
});
|
|
209
242
|
});
|
|
210
243
|
|
|
211
244
|
describe("Drawer gives focus back on the way out", () => {
|
|
@@ -73,25 +73,29 @@ export const Drawer = ({
|
|
|
73
73
|
onClose();
|
|
74
74
|
return;
|
|
75
75
|
}
|
|
76
|
-
//
|
|
77
|
-
//
|
|
78
|
-
//
|
|
79
|
-
//
|
|
80
|
-
//
|
|
76
|
+
// Trap Tab inside the drawer's ring: walking off either end cycles
|
|
77
|
+
// round, and focus that is in the drawer but outside the ring — a
|
|
78
|
+
// control behind a nested dialog's backdrop — is pulled in, so Tab
|
|
79
|
+
// never lands where a pointer cannot reach (#747). The trap only
|
|
80
|
+
// applies while the drawer already holds focus; an error banner or
|
|
81
|
+
// the fatal-error overlay above it keeps its own Tab (#970).
|
|
81
82
|
if (event.key !== "Tab" || !drawerRef.current) return;
|
|
83
|
+
const active = document.activeElement;
|
|
84
|
+
if (!(active instanceof HTMLElement)) return;
|
|
85
|
+
if (!drawerRef.current.contains(active)) return;
|
|
82
86
|
const ring = tabRing(drawerRef.current);
|
|
83
87
|
if (ring.length === 0) return;
|
|
84
88
|
const first = ring[0];
|
|
85
89
|
const last = ring[ring.length - 1];
|
|
86
|
-
const
|
|
90
|
+
const inside = ring.includes(active);
|
|
87
91
|
if (event.shiftKey) {
|
|
88
|
-
if (active === first) {
|
|
92
|
+
if (!inside || active === first) {
|
|
89
93
|
event.preventDefault();
|
|
90
94
|
last.focus();
|
|
91
95
|
}
|
|
92
96
|
return;
|
|
93
97
|
}
|
|
94
|
-
if (active === last) {
|
|
98
|
+
if (!inside || active === last) {
|
|
95
99
|
event.preventDefault();
|
|
96
100
|
first.focus();
|
|
97
101
|
}
|