@aurodesignsystem-dev/auro-drawer 0.0.0-pr172.0 → 0.0.0-pr173.0
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/demo/api.md +5 -5
- package/demo/api.min.js +262 -44
- package/demo/index.min.js +262 -44
- package/dist/{auro-drawer-Bsw9JkHh.js → auro-drawer-DdDsuo_W.js} +10 -10
- package/dist/index.d.ts +4 -1
- package/dist/index.js +1 -1
- package/dist/registered.js +1 -1
- package/package.json +2 -2
package/demo/index.min.js
CHANGED
|
@@ -1797,6 +1797,48 @@ const computePosition = (reference, floating, options) => {
|
|
|
1797
1797
|
});
|
|
1798
1798
|
};
|
|
1799
1799
|
|
|
1800
|
+
/**
|
|
1801
|
+
* Generates a v4 UUID with a three-tier fallback for insecure contexts.
|
|
1802
|
+
*
|
|
1803
|
+
* Tier 1 (secure contexts): crypto.randomUUID() — native, fully random.
|
|
1804
|
+
* Tier 2 (insecure contexts): crypto.getRandomValues() — available on all
|
|
1805
|
+
* modern browsers regardless of secure-context status.
|
|
1806
|
+
* Tier 3 (last resort, no crypto API): new Date().getTime() — lower entropy,
|
|
1807
|
+
* but sufficient for element IDs where collision risk is negligible.
|
|
1808
|
+
*
|
|
1809
|
+
* See: https://w3c.github.io/webcrypto/#dom-crypto-randomuuid (secure-context restriction)
|
|
1810
|
+
*/
|
|
1811
|
+
function generateUUID() {
|
|
1812
|
+
let uuid;
|
|
1813
|
+
|
|
1814
|
+
if (
|
|
1815
|
+
typeof crypto !== "undefined" &&
|
|
1816
|
+
typeof crypto.randomUUID === "function"
|
|
1817
|
+
) {
|
|
1818
|
+
uuid = crypto.randomUUID();
|
|
1819
|
+
} else if (
|
|
1820
|
+
typeof crypto !== "undefined" &&
|
|
1821
|
+
typeof crypto.getRandomValues === "function"
|
|
1822
|
+
) {
|
|
1823
|
+
const bytes = new Uint8Array(16);
|
|
1824
|
+
crypto.getRandomValues(bytes);
|
|
1825
|
+
bytes[6] = (bytes[6] & 0x0f) | 0x40;
|
|
1826
|
+
bytes[8] = (bytes[8] & 0x3f) | 0x80;
|
|
1827
|
+
const hex = Array.from(bytes).map((b) => b.toString(16).padStart(2, "0"));
|
|
1828
|
+
uuid = `${hex.slice(0, 4).join("")}-${hex.slice(4, 6).join("")}-${hex.slice(6, 8).join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10).join("")}`;
|
|
1829
|
+
} else {
|
|
1830
|
+
let d = new Date().getTime();
|
|
1831
|
+
uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
1832
|
+
const r = (d % 16) | 0;
|
|
1833
|
+
d = (d - r) / 16 || new Date().getTime();
|
|
1834
|
+
return (c === "x" ? r : (r & 0x3) | 0x8).toString(16);
|
|
1835
|
+
});
|
|
1836
|
+
}
|
|
1837
|
+
|
|
1838
|
+
// CSS selectors require IDs starting with a letter; replace a leading digit with 'a'.
|
|
1839
|
+
return /^[0-9]/.test(uuid) ? `a${uuid.slice(1)}` : uuid;
|
|
1840
|
+
}
|
|
1841
|
+
|
|
1800
1842
|
/* eslint-disable line-comment-position, no-inline-comments */
|
|
1801
1843
|
|
|
1802
1844
|
|
|
@@ -2084,30 +2126,61 @@ class AuroFloatingUI {
|
|
|
2084
2126
|
|
|
2085
2127
|
/**
|
|
2086
2128
|
* @private
|
|
2087
|
-
*
|
|
2088
|
-
*
|
|
2129
|
+
* Mirrors `aria-modal` onto the `<dialog>` inside the bib, tracking the page
|
|
2130
|
+
* scroll lock: an overlay that holds the page hides it from assistive tech.
|
|
2131
|
+
*
|
|
2132
|
+
* The removal is called only from inside lockScroll()'s ownership guard: run
|
|
2133
|
+
* outside it, it fired on every autoUpdate tick of every NON-owning instance,
|
|
2134
|
+
* and a repositioning dropdown stripped `aria-modal` off an open modal dialog
|
|
2135
|
+
* it had nothing to do with. The write is unguarded by design — see the call
|
|
2136
|
+
* site — but is skipped when the attribute already reads correctly, so the
|
|
2137
|
+
* repeat costs no mutation record.
|
|
2138
|
+
* @param {Boolean} modal - True to mark the dialog modal; false to unmark it.
|
|
2089
2139
|
*/
|
|
2090
|
-
|
|
2140
|
+
mirrorAriaModal(modal) {
|
|
2091
2141
|
const element = this.element;
|
|
2142
|
+
const dialog = element?.bib
|
|
2143
|
+
? (element.bib?.shadowRoot || element.bib || element).querySelector(
|
|
2144
|
+
"dialog",
|
|
2145
|
+
)
|
|
2146
|
+
: undefined;
|
|
2092
2147
|
|
|
2093
|
-
if (!
|
|
2148
|
+
if (!dialog) {
|
|
2094
2149
|
return;
|
|
2095
2150
|
}
|
|
2096
2151
|
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
element.bib ||
|
|
2100
|
-
element
|
|
2101
|
-
).querySelector("dialog");
|
|
2102
|
-
if (dialog) {
|
|
2103
|
-
if (lock) {
|
|
2152
|
+
if (modal) {
|
|
2153
|
+
if (dialog.getAttribute("aria-modal") !== "true") {
|
|
2104
2154
|
dialog.setAttribute("aria-modal", "true");
|
|
2105
|
-
} else {
|
|
2106
|
-
dialog.removeAttribute("aria-modal");
|
|
2107
2155
|
}
|
|
2156
|
+
} else {
|
|
2157
|
+
dialog.removeAttribute("aria-modal");
|
|
2158
|
+
}
|
|
2159
|
+
}
|
|
2160
|
+
|
|
2161
|
+
/**
|
|
2162
|
+
* @private
|
|
2163
|
+
* Controls whether to lock the scrolling for the document's body.
|
|
2164
|
+
* @param {Boolean} lock - If true, locks the body's scrolling functionlity; otherwise, unlock.
|
|
2165
|
+
*/
|
|
2166
|
+
lockScroll(lock = true) {
|
|
2167
|
+
const element = this.element;
|
|
2168
|
+
|
|
2169
|
+
// Locking needs a bib to lock around; unlocking must not, or a bib that has
|
|
2170
|
+
// already been detached would leave the page frozen with no way back.
|
|
2171
|
+
if (lock && !element?.bib) {
|
|
2172
|
+
return;
|
|
2108
2173
|
}
|
|
2109
2174
|
|
|
2110
2175
|
if (lock) {
|
|
2176
|
+
// Re-asserted on every lock call rather than only on the unlocked ->
|
|
2177
|
+
// locked transition. If the bib's inner <dialog> is replaced while this
|
|
2178
|
+
// instance still holds the lock, the replacement would otherwise go
|
|
2179
|
+
// unmarked until a full unlock/lock cycle. Safe to repeat: it targets
|
|
2180
|
+
// this instance's own element, so it cannot reach another overlay's
|
|
2181
|
+
// dialog, and mirrorAriaModal() skips the write when already correct.
|
|
2182
|
+
this.mirrorAriaModal(true);
|
|
2183
|
+
|
|
2111
2184
|
if (!this._scrollLocked) {
|
|
2112
2185
|
this._scrollLocked = true;
|
|
2113
2186
|
this._savedScrollY = window.scrollY;
|
|
@@ -2165,6 +2238,8 @@ class AuroFloatingUI {
|
|
|
2165
2238
|
}
|
|
2166
2239
|
} else {
|
|
2167
2240
|
if (this._scrollLocked) {
|
|
2241
|
+
this.mirrorAriaModal(false);
|
|
2242
|
+
|
|
2168
2243
|
if (this._viewportHandler && window.visualViewport) {
|
|
2169
2244
|
window.visualViewport.removeEventListener(
|
|
2170
2245
|
"resize",
|
|
@@ -2277,15 +2352,47 @@ class AuroFloatingUI {
|
|
|
2277
2352
|
} else if (this.configureTrial < MAX_CONFIGURATION_COUNT) {
|
|
2278
2353
|
this.configureTrial += 1;
|
|
2279
2354
|
|
|
2280
|
-
|
|
2355
|
+
// The id is retained so disconnect() can cancel it. A retry that fires
|
|
2356
|
+
// after teardown re-enters this method with isPopoverVisible still true
|
|
2357
|
+
// — nothing clears it on the teardown path — and takes the page scroll
|
|
2358
|
+
// lock back, with no owner left to release it.
|
|
2359
|
+
//
|
|
2360
|
+
// This is not the rare timing race it reads as: the lookup above wants
|
|
2361
|
+
// a `.container` inside the BIB's own shadow root, which only a bib
|
|
2362
|
+
// that is itself a custom element has. A consumer whose bib is a plain
|
|
2363
|
+
// element (auro-dialog's `#bib` is a div, with its `.container` a
|
|
2364
|
+
// sibling in the host's shadow root) can never satisfy it, so it
|
|
2365
|
+
// retries the full MAX_CONFIGURATION_COUNT every time. Correcting the
|
|
2366
|
+
// lookup would change bib sizing for those consumers and is tracked
|
|
2367
|
+
// separately; cancelling the timer is what keeps it from freezing the
|
|
2368
|
+
// page.
|
|
2369
|
+
this._configureRetryId = setTimeout(() => {
|
|
2370
|
+
this._configureRetryId = undefined;
|
|
2281
2371
|
this.configureBibStrategy(value);
|
|
2282
2372
|
}, 0);
|
|
2283
2373
|
}
|
|
2284
2374
|
|
|
2285
2375
|
if (element.isPopoverVisible) {
|
|
2286
|
-
|
|
2376
|
+
// Positioning strategy is not scroll ownership. Both "fullscreen" and
|
|
2377
|
+
// "dialog" lay the bib over the page and trap focus inside it, so both
|
|
2378
|
+
// must freeze the page behind them (AB#1647843). Gating this on
|
|
2379
|
+
// "fullscreen" alone left dismissible desktop dialogs and drawers
|
|
2380
|
+
// scrollable, and actively released the lock on every reposition
|
|
2381
|
+
// (AB#1625424, AB#1625435). The nested "cover" strategy takes the else
|
|
2382
|
+
// branch and stays scrollable by design — it sits inside its parent
|
|
2383
|
+
// rather than over the page.
|
|
2384
|
+
this.lockScroll(true);
|
|
2287
2385
|
}
|
|
2288
2386
|
} else {
|
|
2387
|
+
// The mirror of the lock above: a strategy that does not own the page must
|
|
2388
|
+
// hand the lock back, not merely decline to take it. autoUpdate re-runs
|
|
2389
|
+
// this method on every resize tick, and getPositioningStrategy() flips
|
|
2390
|
+
// "fullscreen" -> "floating" across the breakpoint for dropdown behavior —
|
|
2391
|
+
// so an overlay that locked while narrow can land here while still open.
|
|
2392
|
+
// Without this, the page stays frozen behind a small floating bib until
|
|
2393
|
+
// hideBib() happens to run.
|
|
2394
|
+
this.lockScroll(false);
|
|
2395
|
+
|
|
2289
2396
|
element.bib.style.position = "";
|
|
2290
2397
|
element.bib.removeAttribute("isfullscreen");
|
|
2291
2398
|
element.isBibFullscreen = false;
|
|
@@ -2395,6 +2502,46 @@ class AuroFloatingUI {
|
|
|
2395
2502
|
this.hideBib("focusloss");
|
|
2396
2503
|
}
|
|
2397
2504
|
|
|
2505
|
+
/**
|
|
2506
|
+
* @private
|
|
2507
|
+
* Installs the handlers that dismiss an open overlay.
|
|
2508
|
+
*
|
|
2509
|
+
* Shared by showBib(), which opens the overlay, and configure(), which has to
|
|
2510
|
+
* put these back after a rewire tore them down under an overlay that is still
|
|
2511
|
+
* open. A non-modal overlay dismisses on outside click, focus loss and
|
|
2512
|
+
* Escape; a modal one instead swallows Escape so the native dialog's
|
|
2513
|
+
* CloseWatcher never sees it (AB#1613688).
|
|
2514
|
+
*/
|
|
2515
|
+
setupDismissHandlers() {
|
|
2516
|
+
const element = this.element;
|
|
2517
|
+
if (!element) {
|
|
2518
|
+
return;
|
|
2519
|
+
}
|
|
2520
|
+
|
|
2521
|
+
if (!element.modal) {
|
|
2522
|
+
this.setupHideHandlers();
|
|
2523
|
+
return;
|
|
2524
|
+
}
|
|
2525
|
+
|
|
2526
|
+
if (this.keyDownHandler) {
|
|
2527
|
+
document.removeEventListener("keydown", this.keyDownHandler);
|
|
2528
|
+
}
|
|
2529
|
+
this.keyDownHandler = (evt) => {
|
|
2530
|
+
if (evt.key === "Escape" && element.isPopoverVisible) {
|
|
2531
|
+
// Intercept at keydown so CloseWatcher never sees the keystroke.
|
|
2532
|
+
// Canceling `cancel` alone is insufficient — a second Esc with no
|
|
2533
|
+
// intervening user activation triggers the anti-trap and fires `close`
|
|
2534
|
+
// directly, bypassing any `cancel` preventDefault (AB#1613688).
|
|
2535
|
+
// stopImmediatePropagation is intentional: it prevents other document
|
|
2536
|
+
// keydown handlers (e.g. consumer code, auro-dialog) from also acting
|
|
2537
|
+
// on Escape while the modal owns the key.
|
|
2538
|
+
evt.preventDefault();
|
|
2539
|
+
evt.stopImmediatePropagation();
|
|
2540
|
+
}
|
|
2541
|
+
};
|
|
2542
|
+
document.addEventListener("keydown", this.keyDownHandler);
|
|
2543
|
+
}
|
|
2544
|
+
|
|
2398
2545
|
setupHideHandlers() {
|
|
2399
2546
|
const element = this.element;
|
|
2400
2547
|
if (!element) {
|
|
@@ -2567,27 +2714,7 @@ class AuroFloatingUI {
|
|
|
2567
2714
|
|
|
2568
2715
|
// prevent double showing: isPopovervisible gets first and showBib gets called later
|
|
2569
2716
|
if (!this.showing) {
|
|
2570
|
-
|
|
2571
|
-
this.setupHideHandlers();
|
|
2572
|
-
} else {
|
|
2573
|
-
if (this.keyDownHandler) {
|
|
2574
|
-
document.removeEventListener("keydown", this.keyDownHandler);
|
|
2575
|
-
}
|
|
2576
|
-
this.keyDownHandler = (evt) => {
|
|
2577
|
-
if (evt.key === "Escape" && element.isPopoverVisible) {
|
|
2578
|
-
// Intercept at keydown so CloseWatcher never sees the keystroke.
|
|
2579
|
-
// Canceling `cancel` alone is insufficient — a second Esc with no
|
|
2580
|
-
// intervening user activation triggers the anti-trap and fires `close`
|
|
2581
|
-
// directly, bypassing any `cancel` preventDefault (AB#1613688).
|
|
2582
|
-
// stopImmediatePropagation is intentional: it prevents other document
|
|
2583
|
-
// keydown handlers (e.g. consumer code, auro-dialog) from also acting
|
|
2584
|
-
// on Escape while the modal owns the key.
|
|
2585
|
-
evt.preventDefault();
|
|
2586
|
-
evt.stopImmediatePropagation();
|
|
2587
|
-
}
|
|
2588
|
-
};
|
|
2589
|
-
document.addEventListener("keydown", this.keyDownHandler);
|
|
2590
|
-
}
|
|
2717
|
+
this.setupDismissHandlers();
|
|
2591
2718
|
this.showing = true;
|
|
2592
2719
|
element.isPopoverVisible = true;
|
|
2593
2720
|
this.position();
|
|
@@ -2815,7 +2942,7 @@ class AuroFloatingUI {
|
|
|
2815
2942
|
|
|
2816
2943
|
this.id = element.getAttribute("id");
|
|
2817
2944
|
if (!this.id) {
|
|
2818
|
-
this.id =
|
|
2945
|
+
this.id = generateUUID();
|
|
2819
2946
|
element.setAttribute("id", this.id);
|
|
2820
2947
|
}
|
|
2821
2948
|
|
|
@@ -2827,7 +2954,35 @@ class AuroFloatingUI {
|
|
|
2827
2954
|
this.enableKeyboardHandling = enableKeyboardHandling;
|
|
2828
2955
|
|
|
2829
2956
|
this.eventPrefix = eventPrefix;
|
|
2830
|
-
|
|
2957
|
+
|
|
2958
|
+
// A retained scroll lock's saved body styles were captured for whichever
|
|
2959
|
+
// element held it, so only a same-element rewire may keep it. An actual
|
|
2960
|
+
// element swap has to take the full teardown, or this instance is left
|
|
2961
|
+
// holding a lock that no longer describes the page it points at — with no
|
|
2962
|
+
// owner able to release it (AB#1647843).
|
|
2963
|
+
const rewiringSameElement = this.element === elem;
|
|
2964
|
+
|
|
2965
|
+
if (!rewiringSameElement) {
|
|
2966
|
+
// Tear down against the outgoing element, before this.element is
|
|
2967
|
+
// repointed. Everything disconnect() releases is element-scoped:
|
|
2968
|
+
// aria-modal on that element's inner dialog, the bib transform saved for
|
|
2969
|
+
// it, its autoUpdate loop and its trigger listeners. Repointing first
|
|
2970
|
+
// aimed all of it at the incoming element — the outgoing dialog kept
|
|
2971
|
+
// aria-modal="true" for good, its bib stayed transformed, and the
|
|
2972
|
+
// incoming bib had the outgoing element's saved transform written onto
|
|
2973
|
+
// it. The trigger gate below read the incoming element's trigger, which
|
|
2974
|
+
// is not assigned until later in this method, so on a swap teardown was
|
|
2975
|
+
// usually skipped outright and the page stayed locked with no owner.
|
|
2976
|
+
if (this.element?.trigger) {
|
|
2977
|
+
this.disconnect({ teardown: true });
|
|
2978
|
+
}
|
|
2979
|
+
|
|
2980
|
+
// disconnect() does not clear this.showing, and the rewire block at the
|
|
2981
|
+
// end of this method only runs for a same-element rewire. Left true, the
|
|
2982
|
+
// incoming element's first showBib() is silently dropped by its
|
|
2983
|
+
// `!this.showing` guard and the overlay never opens.
|
|
2984
|
+
this.showing = false;
|
|
2985
|
+
|
|
2831
2986
|
this.element = elem;
|
|
2832
2987
|
}
|
|
2833
2988
|
|
|
@@ -2840,8 +2995,10 @@ class AuroFloatingUI {
|
|
|
2840
2995
|
this.behavior = element.behavior;
|
|
2841
2996
|
}
|
|
2842
2997
|
|
|
2843
|
-
if (element.trigger) {
|
|
2844
|
-
|
|
2998
|
+
if (rewiringSameElement && element.trigger) {
|
|
2999
|
+
// Rewiring, not tearing down — an overlay that is open right now keeps
|
|
3000
|
+
// its page scroll lock across a trigger change.
|
|
3001
|
+
this.disconnect({ teardown: false });
|
|
2845
3002
|
}
|
|
2846
3003
|
element.trigger =
|
|
2847
3004
|
element.triggerElement ||
|
|
@@ -2870,11 +3027,61 @@ class AuroFloatingUI {
|
|
|
2870
3027
|
element.trigger.addEventListener("focus", this.handleEvent);
|
|
2871
3028
|
element.trigger.addEventListener("blur", this.handleEvent);
|
|
2872
3029
|
}
|
|
3030
|
+
|
|
3031
|
+
// disconnect() above stripped the dismissal handlers and killed the
|
|
3032
|
+
// autoUpdate loop; the trigger listeners re-registered here replace
|
|
3033
|
+
// neither. An overlay that is open right now would otherwise be left on
|
|
3034
|
+
// screen with outside-click, focus-loss and Escape all dead and its
|
|
3035
|
+
// position frozen — and, since the lock is deliberately retained, holding
|
|
3036
|
+
// the page with only its original trigger able to give it back.
|
|
3037
|
+
if (rewiringSameElement && this.showing) {
|
|
3038
|
+
this.setupDismissHandlers();
|
|
3039
|
+
|
|
3040
|
+
if (element.bib && (element.trigger || element.parentNode)) {
|
|
3041
|
+
element.cleanup = autoUpdate(
|
|
3042
|
+
element.trigger || element.parentNode,
|
|
3043
|
+
element.bib,
|
|
3044
|
+
() => {
|
|
3045
|
+
this.position();
|
|
3046
|
+
},
|
|
3047
|
+
);
|
|
3048
|
+
}
|
|
3049
|
+
}
|
|
2873
3050
|
}
|
|
2874
3051
|
|
|
2875
|
-
|
|
3052
|
+
/**
|
|
3053
|
+
* Tears the floater's connections down.
|
|
3054
|
+
*
|
|
3055
|
+
* Two callers with different intent share this: a real teardown, which must
|
|
3056
|
+
* release the page scroll lock, and configure(), which re-runs it purely to
|
|
3057
|
+
* rewire a changed trigger and must leave an open overlay's lock alone.
|
|
3058
|
+
* @param {Object} [options] - Teardown options.
|
|
3059
|
+
* @param {Boolean} [options.teardown] - False when only rewiring; keeps the
|
|
3060
|
+
* page scroll lock held for an overlay that is still open.
|
|
3061
|
+
* @returns {void}
|
|
3062
|
+
*/
|
|
3063
|
+
disconnect({ teardown = true } = {}) {
|
|
2876
3064
|
this.cleanupHideHandlers();
|
|
2877
3065
|
|
|
3066
|
+
// Cancel any pending configureBibStrategy() retry. It would otherwise fire
|
|
3067
|
+
// a macrotask after the unlock below, re-lock the page, and leave it frozen
|
|
3068
|
+
// with the floater already gone. Cancelled on a rewire too: configure()
|
|
3069
|
+
// re-runs position() itself, so a stale retry has nothing to contribute.
|
|
3070
|
+
if (this._configureRetryId !== undefined) {
|
|
3071
|
+
clearTimeout(this._configureRetryId);
|
|
3072
|
+
this._configureRetryId = undefined;
|
|
3073
|
+
}
|
|
3074
|
+
|
|
3075
|
+
// Tearing down while the bib is still open would otherwise strand
|
|
3076
|
+
// body{position:fixed} and leave the page permanently unscrollable —
|
|
3077
|
+
// hideBib() is the only other unlock, and it never runs in this path.
|
|
3078
|
+
// Skipped when merely rewiring: configure() routes through here on every
|
|
3079
|
+
// triggerElement change, and releasing the lock there would unlock the page
|
|
3080
|
+
// behind an overlay that is still open (AB#1625424, AB#1625435).
|
|
3081
|
+
if (teardown) {
|
|
3082
|
+
this.lockScroll(false);
|
|
3083
|
+
}
|
|
3084
|
+
|
|
2878
3085
|
const element = this.element;
|
|
2879
3086
|
if (!element) {
|
|
2880
3087
|
return;
|
|
@@ -3118,7 +3325,10 @@ class AuroFloater extends i$1 {
|
|
|
3118
3325
|
*
|
|
3119
3326
|
* - `nested`: `setAttribute("open", "")` to anchor within the parent container.
|
|
3120
3327
|
* - `!modal && !nested`: `showPopover()` to keep positional CSS intact
|
|
3121
|
-
*
|
|
3328
|
+
* without taking on `showModal()`'s native modal semantics — `dialog.open`
|
|
3329
|
+
* is never set and the background is never made inert. Focus is still
|
|
3330
|
+
* contained: auro-drawer-content installs a `FocusTrap` on every path, not
|
|
3331
|
+
* just the `showModal()` one.
|
|
3122
3332
|
* - `modal && !nested`: `showModal()` for native focus containment and top-layer rendering.
|
|
3123
3333
|
*/
|
|
3124
3334
|
async show() {
|
|
@@ -4147,8 +4357,16 @@ class AuroDrawer extends AuroFloater {
|
|
|
4147
4357
|
this.bib.getAttribute("id"),
|
|
4148
4358
|
);
|
|
4149
4359
|
}
|
|
4150
|
-
// role="dialog"
|
|
4151
|
-
//
|
|
4360
|
+
// role="dialog" is provided natively by the <dialog> element — do not set it here.
|
|
4361
|
+
//
|
|
4362
|
+
// aria-modal is NOT, and the distinction matters: native modal semantics come
|
|
4363
|
+
// from how the dialog is opened, not from the element. Only `modal && !nested`
|
|
4364
|
+
// uses showModal(); `!modal && !nested` uses showPopover() (dialog.open is never
|
|
4365
|
+
// even set) and `nested` uses setAttribute("open"), neither of which is exposed
|
|
4366
|
+
// as modal. auro-library's lockScroll() therefore sets aria-modal on the inner
|
|
4367
|
+
// <dialog> for any presentation that takes the page scroll lock, which is what
|
|
4368
|
+
// makes the dismissible drawer report its modality correctly. See auro-floater.js
|
|
4369
|
+
// show() for the three open paths.
|
|
4152
4370
|
}
|
|
4153
4371
|
|
|
4154
4372
|
/**
|