@aurodesignsystem-dev/auro-drawer 0.0.0-pr132.0 → 0.0.0-pr134.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 +56 -12
- package/demo/auro-drawer.min.js +418 -145
- package/demo/keyboard-audit.html +766 -0
- package/dist/{auro-drawer-UEcwC42s.js → auro-drawer-DTS2mk2U.js} +25 -24
- package/dist/index.d.ts +18 -2
- package/dist/index.js +1 -1
- package/dist/registered.js +1 -1
- package/package.json +6 -2
package/demo/auro-drawer.min.js
CHANGED
|
@@ -2452,7 +2452,7 @@ class AuroFloatingUI {
|
|
|
2452
2452
|
var colorCss$1 = i$5`:host([onbackdrop]) .backdrop{background:var(--ds-auro-floater-backdrop-modal-background-color)}::slotted(*){background:var(--ds-auro-floater-container-background-color);color:var(--ds-auro-floater-container-text-color)}
|
|
2453
2453
|
`;
|
|
2454
2454
|
|
|
2455
|
-
var styleCss$1 = i$5`:host{position:absolute;z-index:var(--ds-depth-overlay, 200);display:none;flex-direction:column;opacity:0;transition:opacity .3s ease-in-out,display .3s;transition-behavior:allow-discrete;will-change:opacity}.container{display:inline-block;width:100%;height:100%}.container ::slotted(:only-child){z-index:var(--ds-depth-modal, 300);box-shadow:var(--ds-elevation-200, 0px 0px 10px rgba(0, 0, 0, .15))}:host([
|
|
2455
|
+
var styleCss$1 = i$5`:host{position:absolute;z-index:var(--ds-depth-overlay, 200);display:none;flex-direction:column;opacity:0;transition:opacity .3s ease-in-out,display .3s;transition-behavior:allow-discrete;will-change:opacity}.util_displayHiddenVisually{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}dialog.container{background-color:transparent;max-width:none;max-height:none;padding:0;border:none;margin:0;outline:none;transform:translateZ(0);display:inline-block;width:100%;height:100%}dialog.container::backdrop{background:var(--auro-drawer-backdrop-background, transparent);backdrop-filter:var(--auro-drawer-backdrop-filter, none);opacity:var(--auro-drawer-backdrop-opacity, 1);transition:var(--auro-drawer-backdrop-transition, opacity .3s ease)}dialog.container .backdrop{position:fixed;inset:0;pointer-events:none}dialog.container ::slotted(:only-child){z-index:var(--ds-depth-modal, 300);box-shadow:var(--ds-elevation-200, 0px 0px 10px rgba(0, 0, 0, .15))}:host([data-show]){display:block;opacity:1}@starting-style{:host([data-show]){opacity:0}}:host([data-show][modal]){pointer-events:initial}:host([isfullscreen]){width:100%;height:100%}:host([isfullscreen]) dialog.container{overflow:auto;width:100%;height:100%}
|
|
2456
2456
|
`;
|
|
2457
2457
|
|
|
2458
2458
|
var tokensCss$1 = i$5`:host{--ds-auro-floater-backdrop-modal-background-color: var(--ds-advanced-color-shared-scrim, rgba(0, 0, 0, .5));--ds-auro-floater-container-background-color: var(--ds-basic-color-surface-default, #ffffff);--ds-auro-floater-container-text-color: var(--ds-basic-color-texticon-default, #2a2a2a)}
|
|
@@ -2469,6 +2469,23 @@ class AuroFloaterBib extends i$2 {
|
|
|
2469
2469
|
* @private
|
|
2470
2470
|
*/
|
|
2471
2471
|
this._mobileBreakpointValue = undefined;
|
|
2472
|
+
|
|
2473
|
+
/**
|
|
2474
|
+
* @private
|
|
2475
|
+
* Bound reference to the touchmove handler so it can be removed later.
|
|
2476
|
+
*/
|
|
2477
|
+
this._boundTouchMoveHandler = undefined;
|
|
2478
|
+
}
|
|
2479
|
+
|
|
2480
|
+
static get properties() {
|
|
2481
|
+
return {
|
|
2482
|
+
/**
|
|
2483
|
+
* Text used to label the dialog for screen readers via aria-labelledby.
|
|
2484
|
+
*/
|
|
2485
|
+
bibLabel: {
|
|
2486
|
+
type: String,
|
|
2487
|
+
},
|
|
2488
|
+
};
|
|
2472
2489
|
}
|
|
2473
2490
|
|
|
2474
2491
|
static get styles() {
|
|
@@ -2481,15 +2498,150 @@ class AuroFloaterBib extends i$2 {
|
|
|
2481
2498
|
"auro-floater-bib",
|
|
2482
2499
|
);
|
|
2483
2500
|
|
|
2484
|
-
this.
|
|
2501
|
+
this.dialog = this.shadowRoot.querySelector("dialog");
|
|
2502
|
+
|
|
2503
|
+
// Always prevent native dialog close on Escape; re-dispatch as a composed
|
|
2504
|
+
// event so AuroDrawer can decide whether to honour it based on `modal`.
|
|
2505
|
+
this.dialog.addEventListener("cancel", (e) => {
|
|
2506
|
+
e.preventDefault();
|
|
2507
|
+
this.dispatchEvent(
|
|
2508
|
+
new Event("dialog-cancel", { bubbles: true, composed: true }),
|
|
2509
|
+
);
|
|
2510
|
+
});
|
|
2511
|
+
|
|
2512
|
+
// Re-dispatch keydown events that stopped at the dialog boundary so that
|
|
2513
|
+
// slotted consumer keyboard handlers outside the shadow DOM still receive them.
|
|
2514
|
+
this.dialog.addEventListener("keydown", (e) => {
|
|
2515
|
+
if (e.target !== this.dialog) {
|
|
2516
|
+
return;
|
|
2517
|
+
}
|
|
2518
|
+
this.dialog.dispatchEvent(
|
|
2519
|
+
new KeyboardEvent(e.type, { ...e, bubbles: true, composed: true }),
|
|
2520
|
+
);
|
|
2521
|
+
});
|
|
2522
|
+
|
|
2523
|
+
// Clicks on the empty dialog area (outside the drawer panel) target the
|
|
2524
|
+
// dialog element directly; clicks inside the panel bubble up from a child.
|
|
2525
|
+
this.dialog.addEventListener("click", (e) => {
|
|
2526
|
+
if (e.target === this.dialog) {
|
|
2527
|
+
this.dispatchEvent(new Event("dialog-backdrop-click", { bubbles: true, composed: true }));
|
|
2528
|
+
}
|
|
2529
|
+
});
|
|
2530
|
+
}
|
|
2531
|
+
|
|
2532
|
+
/**
|
|
2533
|
+
* Opens the dialog.
|
|
2534
|
+
* Uses showModal() for standard/modal drawers (native focus containment, top-layer).
|
|
2535
|
+
* Uses setAttribute('open') for nested drawers to keep positional CSS intact.
|
|
2536
|
+
* @param {{ nested?: boolean }} [options]
|
|
2537
|
+
*/
|
|
2538
|
+
async showDialog({ nested = false } = {}) {
|
|
2539
|
+
// firstUpdated() may not have run yet on initial render — wait for it.
|
|
2540
|
+
if (!this.dialog) {
|
|
2541
|
+
await this.updateComplete;
|
|
2542
|
+
}
|
|
2543
|
+
if (!this.dialog) {
|
|
2544
|
+
return;
|
|
2545
|
+
}
|
|
2546
|
+
|
|
2547
|
+
if (nested) {
|
|
2548
|
+
this.dialog.setAttribute("open", "");
|
|
2549
|
+
} else {
|
|
2550
|
+
// Lock page scroll for the entire duration the dialog is open.
|
|
2551
|
+
// Using position:fixed on <body> is the only reliable way to prevent
|
|
2552
|
+
// ALL scroll vectors — including VoiceOver three-finger swipe, which
|
|
2553
|
+
// bypasses both overflow:hidden and touchmove preventDefault.
|
|
2554
|
+
// We capture the current scrollY so we can restore position on close.
|
|
2555
|
+
this._savedScrollY = window.scrollY;
|
|
2556
|
+
document.body.style.position = 'fixed';
|
|
2557
|
+
document.body.style.top = `-${this._savedScrollY}px`;
|
|
2558
|
+
document.body.style.width = '100%';
|
|
2559
|
+
document.body.style.overflow = 'hidden';
|
|
2560
|
+
document.documentElement.style.overflow = 'hidden';
|
|
2561
|
+
this._scrollLocked = true;
|
|
2562
|
+
|
|
2563
|
+
this.dialog.showModal();
|
|
2564
|
+
|
|
2565
|
+
this._lockTouchScroll();
|
|
2566
|
+
}
|
|
2567
|
+
}
|
|
2568
|
+
|
|
2569
|
+
/**
|
|
2570
|
+
* Closes the dialog and releases touch-scroll lock.
|
|
2571
|
+
*/
|
|
2572
|
+
hideDialog() {
|
|
2573
|
+
// Restore scroll immediately — don't wait for dialog.close().
|
|
2574
|
+
this._restorePageScroll();
|
|
2575
|
+
this._unlockTouchScroll();
|
|
2576
|
+
|
|
2577
|
+
if (this.dialog?.open) {
|
|
2578
|
+
setTimeout(() => {
|
|
2579
|
+
this.dialog.close();
|
|
2580
|
+
}, 300);
|
|
2581
|
+
}
|
|
2582
|
+
}
|
|
2583
|
+
|
|
2584
|
+
/**
|
|
2585
|
+
* Restores page scroll that was locked during showDialog().
|
|
2586
|
+
* Safe to call multiple times — only acts when a lock is active.
|
|
2587
|
+
* @private
|
|
2588
|
+
*/
|
|
2589
|
+
_restorePageScroll() {
|
|
2590
|
+
if (this._scrollLocked) {
|
|
2591
|
+
document.body.style.position = '';
|
|
2592
|
+
document.body.style.top = '';
|
|
2593
|
+
document.body.style.width = '';
|
|
2594
|
+
document.body.style.overflow = '';
|
|
2595
|
+
document.documentElement.style.overflow = '';
|
|
2596
|
+
window.scrollTo(0, this._savedScrollY || 0);
|
|
2597
|
+
this._savedScrollY = undefined;
|
|
2598
|
+
this._scrollLocked = false;
|
|
2599
|
+
}
|
|
2600
|
+
}
|
|
2601
|
+
|
|
2602
|
+
/**
|
|
2603
|
+
* Locks page-level touch scroll while the drawer is open.
|
|
2604
|
+
* Walks composedPath() so scrollable children inside the dialog still scroll.
|
|
2605
|
+
* @private
|
|
2606
|
+
*/
|
|
2607
|
+
_lockTouchScroll() {
|
|
2608
|
+
if (this._boundTouchMoveHandler) {
|
|
2609
|
+
return;
|
|
2610
|
+
}
|
|
2611
|
+
this._boundTouchMoveHandler = (e) => {
|
|
2612
|
+
const path = e.composedPath();
|
|
2613
|
+
const insideScrollable = path.some(
|
|
2614
|
+
(el) => el !== document && el.scrollHeight > el.clientHeight,
|
|
2615
|
+
);
|
|
2616
|
+
if (!insideScrollable) {
|
|
2617
|
+
e.preventDefault();
|
|
2618
|
+
}
|
|
2619
|
+
};
|
|
2620
|
+
document.addEventListener("touchmove", this._boundTouchMoveHandler, {
|
|
2621
|
+
passive: false,
|
|
2622
|
+
});
|
|
2623
|
+
}
|
|
2624
|
+
|
|
2625
|
+
/**
|
|
2626
|
+
* Removes the touch-scroll lock.
|
|
2627
|
+
* @private
|
|
2628
|
+
*/
|
|
2629
|
+
_unlockTouchScroll() {
|
|
2630
|
+
if (this._boundTouchMoveHandler) {
|
|
2631
|
+
document.removeEventListener("touchmove", this._boundTouchMoveHandler, {
|
|
2632
|
+
passive: false,
|
|
2633
|
+
});
|
|
2634
|
+
this._boundTouchMoveHandler = undefined;
|
|
2635
|
+
}
|
|
2485
2636
|
}
|
|
2486
2637
|
|
|
2487
2638
|
render() {
|
|
2488
2639
|
return u$2`
|
|
2489
|
-
<
|
|
2640
|
+
<dialog class="container" aria-labelledby="dialogLabel">
|
|
2641
|
+
<span id="dialogLabel" class="util_displayHiddenVisually" aria-hidden="true">${this.bibLabel || ""}</span>
|
|
2490
2642
|
<div class="backdrop" part="backdrop"></div>
|
|
2491
2643
|
<slot></slot>
|
|
2492
|
-
</
|
|
2644
|
+
</dialog>
|
|
2493
2645
|
`;
|
|
2494
2646
|
}
|
|
2495
2647
|
}
|
|
@@ -2587,8 +2739,10 @@ class AuroFloater extends i$2 {
|
|
|
2587
2739
|
if (changedProperties.has("isPopoverVisible")) {
|
|
2588
2740
|
if (this.isPopoverVisible) {
|
|
2589
2741
|
this.floater.showBib();
|
|
2742
|
+
this.bib?.showDialog({ nested: this.nested });
|
|
2590
2743
|
} else {
|
|
2591
2744
|
this.floater.hideBib();
|
|
2745
|
+
this.bib?.hideDialog();
|
|
2592
2746
|
}
|
|
2593
2747
|
}
|
|
2594
2748
|
}
|
|
@@ -2704,85 +2858,209 @@ class p{registerComponent(t,a){customElements.get(t)||customElements.define(t,cl
|
|
|
2704
2858
|
</div>
|
|
2705
2859
|
`}}
|
|
2706
2860
|
|
|
2707
|
-
//
|
|
2861
|
+
// Selectors for focusable elements
|
|
2708
2862
|
const FOCUSABLE_SELECTORS = [
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2863
|
+
'a[href]',
|
|
2864
|
+
'button:not([disabled])',
|
|
2865
|
+
'textarea:not([disabled])',
|
|
2866
|
+
'input:not([disabled])',
|
|
2867
|
+
'select:not([disabled])',
|
|
2714
2868
|
'[role="tab"]:not([disabled])',
|
|
2715
2869
|
'[role="link"]:not([disabled])',
|
|
2716
2870
|
'[role="button"]:not([disabled])',
|
|
2717
2871
|
'[tabindex]:not([tabindex="-1"])',
|
|
2718
|
-
'[contenteditable]:not([contenteditable="false"])'
|
|
2872
|
+
'[contenteditable]:not([contenteditable="false"])'
|
|
2719
2873
|
];
|
|
2720
2874
|
|
|
2875
|
+
// List of custom components that are known to be focusable
|
|
2721
2876
|
const FOCUSABLE_COMPONENTS = [
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2877
|
+
'auro-checkbox',
|
|
2878
|
+
'auro-radio',
|
|
2879
|
+
'auro-dropdown',
|
|
2880
|
+
'auro-button',
|
|
2881
|
+
'auro-combobox',
|
|
2882
|
+
'auro-input',
|
|
2883
|
+
'auro-counter',
|
|
2884
|
+
'auro-menu',
|
|
2885
|
+
'auro-select',
|
|
2886
|
+
'auro-datepicker',
|
|
2887
|
+
'auro-hyperlink',
|
|
2888
|
+
'auro-accordion',
|
|
2734
2889
|
];
|
|
2735
2890
|
|
|
2891
|
+
/**
|
|
2892
|
+
* Determines if a given element is a custom focusable component.
|
|
2893
|
+
* Returns true if the element matches a known focusable component and is not disabled.
|
|
2894
|
+
*
|
|
2895
|
+
* @param {HTMLElement} element The element to check for focusability.
|
|
2896
|
+
* @returns {boolean} True if the element is a focusable custom component, false otherwise.
|
|
2897
|
+
*/
|
|
2898
|
+
function isFocusableComponent(element) {
|
|
2899
|
+
const componentName = element.tagName.toLowerCase();
|
|
2900
|
+
|
|
2901
|
+
// Guard Clause: Element is a focusable component
|
|
2902
|
+
if (!FOCUSABLE_COMPONENTS.some((name) => element.hasAttribute(name) || componentName === name)) return false;
|
|
2903
|
+
|
|
2904
|
+
// Guard Clause: Element is not disabled
|
|
2905
|
+
if (element.hasAttribute('disabled')) return false;
|
|
2906
|
+
|
|
2907
|
+
// Guard Clause: The element is a hyperlink and has no href attribute
|
|
2908
|
+
if (componentName.match("hyperlink") && !element.hasAttribute('href')) return false;
|
|
2909
|
+
|
|
2910
|
+
// If all guard clauses pass, the element is a focusable component
|
|
2911
|
+
return true;
|
|
2912
|
+
}
|
|
2913
|
+
|
|
2914
|
+
/**
|
|
2915
|
+
* Retrieves all focusable elements within the container in DOM order, including those in shadow DOM and slots.
|
|
2916
|
+
* Returns a unique, ordered array of elements that can receive focus.
|
|
2917
|
+
*
|
|
2918
|
+
* @param {HTMLElement} container The container to search within
|
|
2919
|
+
* @returns {Array<HTMLElement>} An array of focusable elements within the container.
|
|
2920
|
+
*/
|
|
2921
|
+
function getFocusableElements(container) {
|
|
2922
|
+
// Get elements in DOM order by walking the tree
|
|
2923
|
+
const orderedFocusableElements = [];
|
|
2924
|
+
|
|
2925
|
+
// Define a recursive function to collect focusable elements in DOM order
|
|
2926
|
+
const collectFocusableElements = (root) => {
|
|
2927
|
+
// Check if current element is focusable
|
|
2928
|
+
if (root.nodeType === Node.ELEMENT_NODE) {
|
|
2929
|
+
// Check if this is a custom component that is focusable
|
|
2930
|
+
const isComponentFocusable = isFocusableComponent(root);
|
|
2931
|
+
|
|
2932
|
+
if (isComponentFocusable) {
|
|
2933
|
+
// Add the component itself as a focusable element and don't traverse its shadow DOM
|
|
2934
|
+
orderedFocusableElements.push(root);
|
|
2935
|
+
return; // Skip traversing inside this component
|
|
2936
|
+
}
|
|
2937
|
+
|
|
2938
|
+
// Check if the element itself matches any selector
|
|
2939
|
+
for (const selector of FOCUSABLE_SELECTORS) {
|
|
2940
|
+
if (root.matches?.(selector)) {
|
|
2941
|
+
orderedFocusableElements.push(root);
|
|
2942
|
+
break; // Once we know it's focusable, no need to check other selectors
|
|
2943
|
+
}
|
|
2944
|
+
}
|
|
2945
|
+
|
|
2946
|
+
// Process shadow DOM only for non-Auro components
|
|
2947
|
+
if (root.shadowRoot) {
|
|
2948
|
+
// Process shadow DOM children in order
|
|
2949
|
+
if (root.shadowRoot.children) {
|
|
2950
|
+
Array.from(root.shadowRoot.children).forEach(child => {
|
|
2951
|
+
collectFocusableElements(child);
|
|
2952
|
+
});
|
|
2953
|
+
}
|
|
2954
|
+
}
|
|
2955
|
+
|
|
2956
|
+
// Process slots and their assigned nodes in order
|
|
2957
|
+
if (root.tagName === 'SLOT') {
|
|
2958
|
+
const assignedNodes = root.assignedNodes({ flatten: true });
|
|
2959
|
+
for (const node of assignedNodes) {
|
|
2960
|
+
collectFocusableElements(node);
|
|
2961
|
+
}
|
|
2962
|
+
} else {
|
|
2963
|
+
// Process light DOM children in order
|
|
2964
|
+
if (root.children) {
|
|
2965
|
+
Array.from(root.children).forEach(child => {
|
|
2966
|
+
collectFocusableElements(child);
|
|
2967
|
+
});
|
|
2968
|
+
}
|
|
2969
|
+
}
|
|
2970
|
+
}
|
|
2971
|
+
};
|
|
2972
|
+
|
|
2973
|
+
// Start the traversal from the container
|
|
2974
|
+
collectFocusableElements(container);
|
|
2975
|
+
|
|
2976
|
+
// Remove duplicates that might have been collected through different paths
|
|
2977
|
+
// while preserving order
|
|
2978
|
+
const uniqueElements = [];
|
|
2979
|
+
const seen = new Set();
|
|
2980
|
+
|
|
2981
|
+
for (const element of orderedFocusableElements) {
|
|
2982
|
+
if (!seen.has(element)) {
|
|
2983
|
+
seen.add(element);
|
|
2984
|
+
uniqueElements.push(element);
|
|
2985
|
+
}
|
|
2986
|
+
}
|
|
2987
|
+
|
|
2988
|
+
return uniqueElements;
|
|
2989
|
+
}
|
|
2990
|
+
|
|
2991
|
+
/**
|
|
2992
|
+
* FocusTrap manages keyboard focus within a specified container element, ensuring that focus does not leave the container when tabbing.
|
|
2993
|
+
* It is commonly used for modal dialogs or overlays to improve accessibility by trapping focus within interactive UI components.
|
|
2994
|
+
*/
|
|
2736
2995
|
class FocusTrap {
|
|
2996
|
+
/**
|
|
2997
|
+
* Creates a new FocusTrap instance for the given container element.
|
|
2998
|
+
* Initializes event listeners and prepares the container for focus management.
|
|
2999
|
+
*
|
|
3000
|
+
* @param {HTMLElement} container The DOM element to trap focus within.
|
|
3001
|
+
* @throws {Error} If the provided container is not a valid HTMLElement.
|
|
3002
|
+
*/
|
|
2737
3003
|
constructor(container) {
|
|
2738
3004
|
if (!container || !(container instanceof HTMLElement)) {
|
|
2739
3005
|
throw new Error("FocusTrap requires a valid HTMLElement.");
|
|
2740
3006
|
}
|
|
2741
3007
|
|
|
2742
3008
|
this.container = container;
|
|
2743
|
-
this.tabDirection =
|
|
3009
|
+
this.tabDirection = 'forward'; // or 'backward'
|
|
2744
3010
|
|
|
2745
3011
|
this._init();
|
|
2746
3012
|
}
|
|
2747
3013
|
|
|
3014
|
+
/**
|
|
3015
|
+
* Initializes the focus trap by setting up event listeners and attributes on the container.
|
|
3016
|
+
* Prepares the container for focus management, including support for shadow DOM and inert attributes.
|
|
3017
|
+
*
|
|
3018
|
+
* @private
|
|
3019
|
+
*/
|
|
2748
3020
|
_init() {
|
|
2749
|
-
// Support for shadow DOM / web components
|
|
2750
|
-
this.container.shadowRoot || this.container;
|
|
2751
3021
|
|
|
2752
3022
|
// Add inert attribute to prevent focusing programmatically as well (if supported)
|
|
2753
|
-
if (
|
|
3023
|
+
if ('inert' in HTMLElement.prototype) {
|
|
2754
3024
|
this.container.inert = false; // Ensure the container isn't inert
|
|
2755
|
-
this.container.setAttribute(
|
|
3025
|
+
this.container.setAttribute('data-focus-trap-container', true); // Mark for identification
|
|
2756
3026
|
}
|
|
2757
3027
|
|
|
2758
3028
|
// Track tab direction
|
|
2759
|
-
this.container.addEventListener(
|
|
3029
|
+
this.container.addEventListener('keydown', this._onKeydown);
|
|
2760
3030
|
}
|
|
2761
3031
|
|
|
3032
|
+
/**
|
|
3033
|
+
* Handles keydown events to manage tab navigation within the container.
|
|
3034
|
+
* Ensures that focus wraps around when reaching the first or last focusable element.
|
|
3035
|
+
*
|
|
3036
|
+
* @param {KeyboardEvent} e The keyboard event triggered by user interaction.
|
|
3037
|
+
* @private
|
|
3038
|
+
*/
|
|
2762
3039
|
_onKeydown = (e) => {
|
|
2763
|
-
|
|
3040
|
+
|
|
3041
|
+
if (e.key === 'Tab') {
|
|
3042
|
+
|
|
2764
3043
|
// Set the tab direction based on the key pressed
|
|
2765
|
-
this.tabDirection = e.shiftKey ?
|
|
3044
|
+
this.tabDirection = e.shiftKey ? 'backward' : 'forward';
|
|
2766
3045
|
|
|
2767
3046
|
// Get the active element(s) in the document and shadow root
|
|
2768
3047
|
// This will include the active element in the shadow DOM if it exists
|
|
2769
3048
|
// Active element may be inside the shadow DOM depending on delegatesFocus, so we need to check both
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
3049
|
+
let activeElement = document.activeElement;
|
|
3050
|
+
const actives = [activeElement];
|
|
3051
|
+
while (activeElement?.shadowRoot?.activeElement) {
|
|
3052
|
+
actives.push(activeElement.shadowRoot.activeElement);
|
|
3053
|
+
activeElement = activeElement.shadowRoot.activeElement;
|
|
3054
|
+
}
|
|
2776
3055
|
|
|
2777
3056
|
// Update the focusable elements
|
|
2778
3057
|
const focusables = this._getFocusableElements();
|
|
2779
3058
|
|
|
2780
3059
|
// If we're at either end of the focusable elements, wrap around to the other end
|
|
2781
3060
|
const focusIndex =
|
|
2782
|
-
actives.includes(focusables[0]) && this.tabDirection ===
|
|
3061
|
+
(actives.includes(focusables[0]) || actives.includes(this.container)) && this.tabDirection === 'backward'
|
|
2783
3062
|
? focusables.length - 1
|
|
2784
|
-
: actives.includes(focusables[focusables.length - 1]) &&
|
|
2785
|
-
this.tabDirection === "forward"
|
|
3063
|
+
: actives.includes(focusables[focusables.length - 1]) && this.tabDirection === 'forward'
|
|
2786
3064
|
? 0
|
|
2787
3065
|
: null;
|
|
2788
3066
|
|
|
@@ -2794,100 +3072,50 @@ class FocusTrap {
|
|
|
2794
3072
|
}
|
|
2795
3073
|
};
|
|
2796
3074
|
|
|
3075
|
+
/**
|
|
3076
|
+
* Retrieves all focusable elements within the container in DOM order, including those in shadow DOM and slots.
|
|
3077
|
+
* Returns a unique, ordered array of elements that can receive focus.
|
|
3078
|
+
*
|
|
3079
|
+
* @returns {Array<HTMLElement>} An array of focusable elements within the container.
|
|
3080
|
+
* @private
|
|
3081
|
+
*/
|
|
2797
3082
|
_getFocusableElements() {
|
|
2798
|
-
//
|
|
2799
|
-
const
|
|
2800
|
-
|
|
2801
|
-
//
|
|
2802
|
-
|
|
2803
|
-
// Check if current element is focusable
|
|
2804
|
-
if (root.nodeType === Node.ELEMENT_NODE) {
|
|
2805
|
-
// Check if this is one of our special Auro components
|
|
2806
|
-
const isAuroComponent = FOCUSABLE_COMPONENTS.some((component) =>
|
|
2807
|
-
root.tagName.toLowerCase()?.match(component),
|
|
2808
|
-
);
|
|
2809
|
-
|
|
2810
|
-
if (isAuroComponent) {
|
|
2811
|
-
// Add the component itself as a focusable element and don't traverse its shadow DOM
|
|
2812
|
-
orderedFocusableElements.push(root);
|
|
2813
|
-
return; // Skip traversing inside this component
|
|
2814
|
-
}
|
|
2815
|
-
|
|
2816
|
-
// Check if the element itself matches any selector
|
|
2817
|
-
for (const selector of FOCUSABLE_SELECTORS) {
|
|
2818
|
-
if (
|
|
2819
|
-
root.matches?.(selector) &&
|
|
2820
|
-
!root.classList.contains("focus-bookend")
|
|
2821
|
-
) {
|
|
2822
|
-
orderedFocusableElements.push(root);
|
|
2823
|
-
break; // Once we know it's focusable, no need to check other selectors
|
|
2824
|
-
}
|
|
2825
|
-
}
|
|
2826
|
-
|
|
2827
|
-
// Process shadow DOM only for non-Auro components
|
|
2828
|
-
if (root.shadowRoot) {
|
|
2829
|
-
// Process shadow DOM children in order
|
|
2830
|
-
if (root.shadowRoot.children) {
|
|
2831
|
-
Array.from(root.shadowRoot.children).forEach((child) => {
|
|
2832
|
-
collectFocusableElements(child);
|
|
2833
|
-
});
|
|
2834
|
-
}
|
|
2835
|
-
}
|
|
2836
|
-
|
|
2837
|
-
// Process slots and their assigned nodes in order
|
|
2838
|
-
if (root.tagName === "SLOT") {
|
|
2839
|
-
const assignedNodes = root.assignedNodes({ flatten: true });
|
|
2840
|
-
for (const node of assignedNodes) {
|
|
2841
|
-
collectFocusableElements(node);
|
|
2842
|
-
}
|
|
2843
|
-
} else {
|
|
2844
|
-
// Process light DOM children in order
|
|
2845
|
-
if (root.children) {
|
|
2846
|
-
Array.from(root.children).forEach((child) => {
|
|
2847
|
-
collectFocusableElements(child);
|
|
2848
|
-
});
|
|
2849
|
-
}
|
|
2850
|
-
}
|
|
2851
|
-
}
|
|
2852
|
-
};
|
|
2853
|
-
|
|
2854
|
-
// Start the traversal from the container
|
|
2855
|
-
collectFocusableElements(this.container);
|
|
2856
|
-
|
|
2857
|
-
// Remove duplicates that might have been collected through different paths
|
|
2858
|
-
// while preserving order
|
|
2859
|
-
const uniqueElements = [];
|
|
2860
|
-
const seen = new Set();
|
|
2861
|
-
|
|
2862
|
-
for (const element of orderedFocusableElements) {
|
|
2863
|
-
if (!seen.has(element)) {
|
|
2864
|
-
seen.add(element);
|
|
2865
|
-
uniqueElements.push(element);
|
|
2866
|
-
}
|
|
2867
|
-
}
|
|
2868
|
-
|
|
2869
|
-
return uniqueElements;
|
|
3083
|
+
// Use the imported utility function to get focusable elements
|
|
3084
|
+
const elements = getFocusableElements(this.container);
|
|
3085
|
+
|
|
3086
|
+
// Filter out any elements with the 'focus-bookend' class
|
|
3087
|
+
return elements;
|
|
2870
3088
|
}
|
|
2871
3089
|
|
|
3090
|
+
/**
|
|
3091
|
+
* Moves focus to the first focusable element within the container.
|
|
3092
|
+
* Useful for setting initial focus when activating the focus trap.
|
|
3093
|
+
*/
|
|
2872
3094
|
focusFirstElement() {
|
|
2873
3095
|
const focusables = this._getFocusableElements();
|
|
2874
3096
|
if (focusables.length) focusables[0].focus();
|
|
2875
3097
|
}
|
|
2876
3098
|
|
|
3099
|
+
/**
|
|
3100
|
+
* Moves focus to the last focusable element within the container.
|
|
3101
|
+
* Useful for setting focus when deactivating or cycling focus in reverse.
|
|
3102
|
+
*/
|
|
2877
3103
|
focusLastElement() {
|
|
2878
3104
|
const focusables = this._getFocusableElements();
|
|
2879
3105
|
if (focusables.length) focusables[focusables.length - 1].focus();
|
|
2880
3106
|
}
|
|
2881
3107
|
|
|
3108
|
+
/**
|
|
3109
|
+
* Removes event listeners and attributes added by the focus trap.
|
|
3110
|
+
* Call this method to clean up when the focus trap is no longer needed.
|
|
3111
|
+
*/
|
|
2882
3112
|
disconnect() {
|
|
2883
|
-
// Remove the tabIndex we set
|
|
2884
|
-
this.container.removeAttribute("tabIndex");
|
|
2885
3113
|
|
|
2886
|
-
if (this.container.hasAttribute(
|
|
2887
|
-
this.container.removeAttribute(
|
|
3114
|
+
if (this.container.hasAttribute('data-focus-trap-container')) {
|
|
3115
|
+
this.container.removeAttribute('data-focus-trap-container');
|
|
2888
3116
|
}
|
|
2889
3117
|
|
|
2890
|
-
this.container.removeEventListener(
|
|
3118
|
+
this.container.removeEventListener('keydown', this._onKeydown);
|
|
2891
3119
|
}
|
|
2892
3120
|
}
|
|
2893
3121
|
|
|
@@ -2898,7 +3126,7 @@ var iconVersion = '9.1.1';
|
|
|
2898
3126
|
var colorCss = i$5`.wrapper{background:var(--ds-auro-drawer-container-color)}::slotted(*){color:var(--ds-auro-drawer-text-color)}
|
|
2899
3127
|
`;
|
|
2900
3128
|
|
|
2901
|
-
var styleCss = i$5`.body-default{font-size:var(--wcss-body-default-font-size, 1rem);line-height:var(--wcss-body-default-line-height, 1.5rem)}.body-default,.body-lg{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-weight:var(--wcss-body-weight, 450);letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-lg{font-size:var(--wcss-body-lg-font-size, 1.125rem);line-height:var(--wcss-body-lg-line-height, 1.625rem)}.body-sm{font-size:var(--wcss-body-sm-font-size, .875rem);line-height:var(--wcss-body-sm-line-height, 1.25rem)}.body-sm,.body-xs{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-weight:var(--wcss-body-weight, 450);letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-xs{font-size:var(--wcss-body-xs-font-size, .75rem);line-height:var(--wcss-body-xs-line-height, 1rem)}.body-2xs{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:var(--wcss-body-2xs-font-size, .625rem);font-weight:var(--wcss-body-weight, 450);letter-spacing:var(--wcss-body-letter-spacing, 0);line-height:var(--wcss-body-2xs-line-height, .875rem)}.display-2xl{font-family:var(--wcss-display-2xl-family, "AS Circular"),var(--wcss-display-2xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-2xl-font-size, clamp(3.5rem, 6vw, 5.375rem));font-weight:var(--wcss-display-2xl-weight, 300);letter-spacing:var(--wcss-display-2xl-letter-spacing, 0);line-height:var(--wcss-display-2xl-line-height, 1.3)}.display-xl{font-family:var(--wcss-display-xl-family, "AS Circular"),var(--wcss-display-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-xl-font-size, clamp(3rem, 5.3333333333vw, 4.5rem));font-weight:var(--wcss-display-xl-weight, 300);letter-spacing:var(--wcss-display-xl-letter-spacing, 0);line-height:var(--wcss-display-xl-line-height, 1.3)}.display-lg{font-family:var(--wcss-display-lg-family, "AS Circular"),var(--wcss-display-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-lg-font-size, clamp(2.75rem, 4.6666666667vw, 4rem));font-weight:var(--wcss-display-lg-weight, 300);letter-spacing:var(--wcss-display-lg-letter-spacing, 0);line-height:var(--wcss-display-lg-line-height, 1.3)}.display-md{font-family:var(--wcss-display-md-family, "AS Circular"),var(--wcss-display-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-md-font-size, clamp(2.5rem, 4vw, 3.5rem));font-weight:var(--wcss-display-md-weight, 300);letter-spacing:var(--wcss-display-md-letter-spacing, 0);line-height:var(--wcss-display-md-line-height, 1.3)}.display-sm{font-family:var(--wcss-display-sm-family, "AS Circular"),var(--wcss-display-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-sm-font-size, clamp(2rem, 3.6666666667vw, 3rem));font-weight:var(--wcss-display-sm-weight, 300);letter-spacing:var(--wcss-display-sm-letter-spacing, 0);line-height:var(--wcss-display-sm-line-height, 1.3)}.display-xs{font-family:var(--wcss-display-xs-family, "AS Circular"),var(--wcss-display-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-xs-font-size, clamp(1.75rem, 3vw, 2.375rem));font-weight:var(--wcss-display-xs-weight, 300);letter-spacing:var(--wcss-display-xs-letter-spacing, 0);line-height:var(--wcss-display-xs-line-height, 1.3)}.heading-xl{font-family:var(--wcss-heading-xl-family, "AS Circular"),var(--wcss-heading-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-xl-font-size, clamp(2rem, 3vw, 2.5rem));font-weight:var(--wcss-heading-xl-weight, 300);letter-spacing:var(--wcss-heading-xl-letter-spacing, 0);line-height:var(--wcss-heading-xl-line-height, 1.3)}.heading-lg{font-family:var(--wcss-heading-lg-family, "AS Circular"),var(--wcss-heading-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-lg-font-size, clamp(1.75rem, 2.6666666667vw, 2.25rem));font-weight:var(--wcss-heading-lg-weight, 300);letter-spacing:var(--wcss-heading-lg-letter-spacing, 0);line-height:var(--wcss-heading-lg-line-height, 1.3)}.heading-md{font-family:var(--wcss-heading-md-family, "AS Circular"),var(--wcss-heading-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-md-font-size, clamp(1.625rem, 2.3333333333vw, 1.75rem));font-weight:var(--wcss-heading-md-weight, 300);letter-spacing:var(--wcss-heading-md-letter-spacing, 0);line-height:var(--wcss-heading-md-line-height, 1.3)}.heading-sm{font-family:var(--wcss-heading-sm-family, "AS Circular"),var(--wcss-heading-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-sm-font-size, clamp(1.375rem, 2vw, 1.5rem));font-weight:var(--wcss-heading-sm-weight, 300);letter-spacing:var(--wcss-heading-sm-letter-spacing, 0);line-height:var(--wcss-heading-sm-line-height, 1.3)}.heading-xs{font-family:var(--wcss-heading-xs-family, "AS Circular"),var(--wcss-heading-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-xs-font-size, clamp(1.25rem, 1.6666666667vw, 1.25rem));font-weight:var(--wcss-heading-xs-weight, 450);letter-spacing:var(--wcss-heading-xs-letter-spacing, 0);line-height:var(--wcss-heading-xs-line-height, 1.3)}.heading-2xs{font-family:var(--wcss-heading-2xs-family, "AS Circular"),var(--wcss-heading-2xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-2xs-font-size, clamp(1.125rem, 1.5vw, 1.125rem));font-weight:var(--wcss-heading-2xs-weight, 450);letter-spacing:var(--wcss-heading-2xs-letter-spacing, 0);line-height:var(--wcss-heading-2xs-line-height, 1.3)}.accent-2xl{font-family:var(--wcss-accent-2xl-family, "Good OT"),var(--wcss-accent-2xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-2xl-font-size, clamp(2rem, 3.1666666667vw, 2.375rem));font-weight:var(--wcss-accent-2xl-weight, 450);letter-spacing:var(--wcss-accent-2xl-letter-spacing, .05em);line-height:var(--wcss-accent-2xl-line-height, 1)}.accent-2xl,.accent-xl{text-transform:uppercase}.accent-xl{font-family:var(--wcss-accent-xl-family, "Good OT"),var(--wcss-accent-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-xl-font-size, clamp(1.625rem, 2.3333333333vw, 2rem));font-weight:var(--wcss-accent-xl-weight, 450);letter-spacing:var(--wcss-accent-xl-letter-spacing, .05em);line-height:var(--wcss-accent-xl-line-height, 1.3)}.accent-lg{font-family:var(--wcss-accent-lg-family, "Good OT"),var(--wcss-accent-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-lg-font-size, clamp(1.5rem, 2.1666666667vw, 1.75rem));font-weight:var(--wcss-accent-lg-weight, 450);letter-spacing:var(--wcss-accent-lg-letter-spacing, .05em);line-height:var(--wcss-accent-lg-line-height, 1.3)}.accent-lg,.accent-md{text-transform:uppercase}.accent-md{font-family:var(--wcss-accent-md-family, "Good OT"),var(--wcss-accent-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-md-font-size, clamp(1.375rem, 1.8333333333vw, 1.5rem));font-weight:var(--wcss-accent-md-weight, 500);letter-spacing:var(--wcss-accent-md-letter-spacing, .05em);line-height:var(--wcss-accent-md-line-height, 1.3)}.accent-sm{font-family:var(--wcss-accent-sm-family, "Good OT"),var(--wcss-accent-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-sm-font-size, clamp(1.125rem, 1.5vw, 1.25rem));font-weight:var(--wcss-accent-sm-weight, 500);letter-spacing:var(--wcss-accent-sm-letter-spacing, .05em);line-height:var(--wcss-accent-sm-line-height, 1.3)}.accent-sm,.accent-xs{text-transform:uppercase}.accent-xs{font-family:var(--wcss-accent-xs-family, "Good OT"),var(--wcss-accent-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-xs-font-size, clamp(1rem, 1.3333333333vw, 1rem));font-weight:var(--wcss-accent-xs-weight, 500);letter-spacing:var(--wcss-accent-xs-letter-spacing, .1em);line-height:var(--wcss-accent-xs-line-height, 1.3)}.accent-2xs{font-family:var(--wcss-accent-2xs-family, "Good OT"),var(--wcss-accent-2xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-2xs-font-size, clamp(.875rem, 1.1666666667vw, .875rem));font-weight:var(--wcss-accent-2xs-weight, 450);letter-spacing:var(--wcss-accent-2xs-letter-spacing, .1em);line-height:var(--wcss-accent-2xs-line-height, 1.3);text-transform:uppercase}:host{display:contents;--insetPaddingXl: var(--ds-size-400, 2rem);--insetPaddingXxl: var(--ds-size-600, 3rem);--insetPaddingXxxl: var(--ds-size-800, 4rem)}:host .wrapper{position:absolute;overflow:auto;width:100%;height:100%;box-sizing:border-box;box-shadow:var(--ds-elevation-200, 0px 0px 10px rgba(0, 0, 0, .15));transition:transform .3s ease-in-out,display .3s;transition-behavior:allow-discrete;will-change:transform}:host .header-row{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--ds-size-200, 1rem)}:host .footer{display:flex;align-items:flex-start;justify-content:flex-end;margin-top:var(--insetPaddingXl)}:host .heading{margin-block-start:0}:host(:not([unformatted])) .wrapper{padding:var(--insetPaddingXl)}@media screen and (min-width: 1024px){:host(:not([unformatted])) .wrapper{padding:var(--insetPaddingXxxl)}}#closeButton{margin-left:auto}#closeButton:hover{cursor:pointer}#closeButton .util_displayHiddenVisually{position:absolute;overflow:hidden;width:1px;height:1px;padding:0;border:0;clip:rect(1px,1px,1px,1px)}:host([placement=right]) .wrapper,:host([placement=left]) .wrapper{max-width:90%}:host([placement=right]),:host([placement=left]){overflow-x:hidden}:host([placement=top]),:host([placement=bottom]){width:100%}:host([placement=top]) .wrapper,:host([placement=bottom]) .wrapper{max-height:90%}:host([placement=right]) .wrapper{right:0;transform:translate3d(100%,0,0)}:host([placement=left]) .wrapper{transform:translate(-100%)}:host([placement=top]) .wrapper{transform:translateY(-100%)}:host([placement=bottom]) .wrapper{bottom:0;transform:translate3d(0,100%,0)}:host([visible]) .wrapper{transform:translateZ(0)}@starting-style{:host([visible][placement=right]) .wrapper{transform:translate(100%)}:host([visible][placement=left]) .wrapper{transform:translate(-100%)}:host([visible][placement=top]) .wrapper{transform:translateY(-100%)}:host([visible][placement=bottom]) .wrapper{transform:translate3d(0,100%,0)}}@media screen and (min-width: 768px){:host([size=sm][placement=left]) .wrapper,:host([size=sm][placement=right]) .wrapper{max-width:40%}}@media screen and (min-width: 1024px){:host([size=sm][placement=left]) .drawer,:host([size=sm][placement=right]) .drawer{max-width:740px}}@media screen and (min-width: 768px){:host([size=md][placement=left]) .wrapper,:host([size=md][placement=right]) .wrapper{max-width:70%}}@media screen and (min-width: 1024px){:host([size=md][placement=left]) .wrapper,:host([size=md][placement=right]) .wrapper{max-width:986px}}:host([size=sm][placement=top]:not([stretch])) .wrapper,:host([size=sm][placement=bottom]:not([stretch])) .wrapper{max-height:30%}:host([size=md][placement=top]:not([stretch])) .wrapper,:host([size=md][placement=bottom]:not([stretch])) .wrapper{max-height:50%}:host([stretch]) .wrapper{max-width:100%;max-height:100%}
|
|
3129
|
+
var styleCss = i$5`.body-default{font-size:var(--wcss-body-default-font-size, 1rem);line-height:var(--wcss-body-default-line-height, 1.5rem)}.body-default,.body-lg{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-weight:var(--wcss-body-weight, 450);letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-lg{font-size:var(--wcss-body-lg-font-size, 1.125rem);line-height:var(--wcss-body-lg-line-height, 1.625rem)}.body-sm{font-size:var(--wcss-body-sm-font-size, .875rem);line-height:var(--wcss-body-sm-line-height, 1.25rem)}.body-sm,.body-xs{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-weight:var(--wcss-body-weight, 450);letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-xs{font-size:var(--wcss-body-xs-font-size, .75rem);line-height:var(--wcss-body-xs-line-height, 1rem)}.body-2xs{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:var(--wcss-body-2xs-font-size, .625rem);font-weight:var(--wcss-body-weight, 450);letter-spacing:var(--wcss-body-letter-spacing, 0);line-height:var(--wcss-body-2xs-line-height, .875rem)}.display-2xl{font-family:var(--wcss-display-2xl-family, "AS Circular"),var(--wcss-display-2xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-2xl-font-size, clamp(3.5rem, 6vw, 5.375rem));font-weight:var(--wcss-display-2xl-weight, 300);letter-spacing:var(--wcss-display-2xl-letter-spacing, 0);line-height:var(--wcss-display-2xl-line-height, 1.3)}.display-xl{font-family:var(--wcss-display-xl-family, "AS Circular"),var(--wcss-display-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-xl-font-size, clamp(3rem, 5.3333333333vw, 4.5rem));font-weight:var(--wcss-display-xl-weight, 300);letter-spacing:var(--wcss-display-xl-letter-spacing, 0);line-height:var(--wcss-display-xl-line-height, 1.3)}.display-lg{font-family:var(--wcss-display-lg-family, "AS Circular"),var(--wcss-display-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-lg-font-size, clamp(2.75rem, 4.6666666667vw, 4rem));font-weight:var(--wcss-display-lg-weight, 300);letter-spacing:var(--wcss-display-lg-letter-spacing, 0);line-height:var(--wcss-display-lg-line-height, 1.3)}.display-md{font-family:var(--wcss-display-md-family, "AS Circular"),var(--wcss-display-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-md-font-size, clamp(2.5rem, 4vw, 3.5rem));font-weight:var(--wcss-display-md-weight, 300);letter-spacing:var(--wcss-display-md-letter-spacing, 0);line-height:var(--wcss-display-md-line-height, 1.3)}.display-sm{font-family:var(--wcss-display-sm-family, "AS Circular"),var(--wcss-display-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-sm-font-size, clamp(2rem, 3.6666666667vw, 3rem));font-weight:var(--wcss-display-sm-weight, 300);letter-spacing:var(--wcss-display-sm-letter-spacing, 0);line-height:var(--wcss-display-sm-line-height, 1.3)}.display-xs{font-family:var(--wcss-display-xs-family, "AS Circular"),var(--wcss-display-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-xs-font-size, clamp(1.75rem, 3vw, 2.375rem));font-weight:var(--wcss-display-xs-weight, 300);letter-spacing:var(--wcss-display-xs-letter-spacing, 0);line-height:var(--wcss-display-xs-line-height, 1.3)}.heading-xl{font-family:var(--wcss-heading-xl-family, "AS Circular"),var(--wcss-heading-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-xl-font-size, clamp(2rem, 3vw, 2.5rem));font-weight:var(--wcss-heading-xl-weight, 300);letter-spacing:var(--wcss-heading-xl-letter-spacing, 0);line-height:var(--wcss-heading-xl-line-height, 1.3)}.heading-lg{font-family:var(--wcss-heading-lg-family, "AS Circular"),var(--wcss-heading-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-lg-font-size, clamp(1.75rem, 2.6666666667vw, 2.25rem));font-weight:var(--wcss-heading-lg-weight, 300);letter-spacing:var(--wcss-heading-lg-letter-spacing, 0);line-height:var(--wcss-heading-lg-line-height, 1.3)}.heading-md{font-family:var(--wcss-heading-md-family, "AS Circular"),var(--wcss-heading-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-md-font-size, clamp(1.625rem, 2.3333333333vw, 1.75rem));font-weight:var(--wcss-heading-md-weight, 300);letter-spacing:var(--wcss-heading-md-letter-spacing, 0);line-height:var(--wcss-heading-md-line-height, 1.3)}.heading-sm{font-family:var(--wcss-heading-sm-family, "AS Circular"),var(--wcss-heading-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-sm-font-size, clamp(1.375rem, 2vw, 1.5rem));font-weight:var(--wcss-heading-sm-weight, 300);letter-spacing:var(--wcss-heading-sm-letter-spacing, 0);line-height:var(--wcss-heading-sm-line-height, 1.3)}.heading-xs{font-family:var(--wcss-heading-xs-family, "AS Circular"),var(--wcss-heading-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-xs-font-size, clamp(1.25rem, 1.6666666667vw, 1.25rem));font-weight:var(--wcss-heading-xs-weight, 450);letter-spacing:var(--wcss-heading-xs-letter-spacing, 0);line-height:var(--wcss-heading-xs-line-height, 1.3)}.heading-2xs{font-family:var(--wcss-heading-2xs-family, "AS Circular"),var(--wcss-heading-2xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-2xs-font-size, clamp(1.125rem, 1.5vw, 1.125rem));font-weight:var(--wcss-heading-2xs-weight, 450);letter-spacing:var(--wcss-heading-2xs-letter-spacing, 0);line-height:var(--wcss-heading-2xs-line-height, 1.3)}.accent-2xl{font-family:var(--wcss-accent-2xl-family, "Good OT"),var(--wcss-accent-2xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-2xl-font-size, clamp(2rem, 3.1666666667vw, 2.375rem));font-weight:var(--wcss-accent-2xl-weight, 450);letter-spacing:var(--wcss-accent-2xl-letter-spacing, .05em);line-height:var(--wcss-accent-2xl-line-height, 1)}.accent-2xl,.accent-xl{text-transform:uppercase}.accent-xl{font-family:var(--wcss-accent-xl-family, "Good OT"),var(--wcss-accent-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-xl-font-size, clamp(1.625rem, 2.3333333333vw, 2rem));font-weight:var(--wcss-accent-xl-weight, 450);letter-spacing:var(--wcss-accent-xl-letter-spacing, .05em);line-height:var(--wcss-accent-xl-line-height, 1.3)}.accent-lg{font-family:var(--wcss-accent-lg-family, "Good OT"),var(--wcss-accent-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-lg-font-size, clamp(1.5rem, 2.1666666667vw, 1.75rem));font-weight:var(--wcss-accent-lg-weight, 450);letter-spacing:var(--wcss-accent-lg-letter-spacing, .05em);line-height:var(--wcss-accent-lg-line-height, 1.3)}.accent-lg,.accent-md{text-transform:uppercase}.accent-md{font-family:var(--wcss-accent-md-family, "Good OT"),var(--wcss-accent-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-md-font-size, clamp(1.375rem, 1.8333333333vw, 1.5rem));font-weight:var(--wcss-accent-md-weight, 500);letter-spacing:var(--wcss-accent-md-letter-spacing, .05em);line-height:var(--wcss-accent-md-line-height, 1.3)}.accent-sm{font-family:var(--wcss-accent-sm-family, "Good OT"),var(--wcss-accent-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-sm-font-size, clamp(1.125rem, 1.5vw, 1.25rem));font-weight:var(--wcss-accent-sm-weight, 500);letter-spacing:var(--wcss-accent-sm-letter-spacing, .05em);line-height:var(--wcss-accent-sm-line-height, 1.3)}.accent-sm,.accent-xs{text-transform:uppercase}.accent-xs{font-family:var(--wcss-accent-xs-family, "Good OT"),var(--wcss-accent-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-xs-font-size, clamp(1rem, 1.3333333333vw, 1rem));font-weight:var(--wcss-accent-xs-weight, 500);letter-spacing:var(--wcss-accent-xs-letter-spacing, .1em);line-height:var(--wcss-accent-xs-line-height, 1.3)}.accent-2xs{font-family:var(--wcss-accent-2xs-family, "Good OT"),var(--wcss-accent-2xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-2xs-font-size, clamp(.875rem, 1.1666666667vw, .875rem));font-weight:var(--wcss-accent-2xs-weight, 450);letter-spacing:var(--wcss-accent-2xs-letter-spacing, .1em);line-height:var(--wcss-accent-2xs-line-height, 1.3);text-transform:uppercase}:host{display:contents;--insetPaddingXl: var(--ds-size-400, 2rem);--insetPaddingXxl: var(--ds-size-600, 3rem);--insetPaddingXxxl: var(--ds-size-800, 4rem)}:host .wrapper{position:absolute;overflow:auto;width:100%;height:100%;box-sizing:border-box;transition:transform;box-shadow:var(--ds-elevation-200, 0px 0px 10px rgba(0, 0, 0, .15));will-change:transform}:host .header-row{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--ds-size-200, 1rem)}:host .footer{display:flex;align-items:flex-start;justify-content:flex-end;margin-top:var(--insetPaddingXl)}:host .heading{margin-block-start:0}:host(:not([unformatted])) .wrapper{padding:var(--insetPaddingXl)}@media screen and (min-width: 1024px){:host(:not([unformatted])) .wrapper{padding:var(--insetPaddingXxxl)}}#closeButton{margin-left:auto}#closeButton:hover{cursor:pointer}#closeButton .util_displayHiddenVisually{position:absolute;overflow:hidden;width:1px;height:1px;padding:0;border:0;clip:rect(1px,1px,1px,1px)}:host([placement=right]) .wrapper,:host([placement=left]) .wrapper{max-width:90%}:host([placement=right]),:host([placement=left]){overflow-x:hidden}:host([placement=top]),:host([placement=bottom]){width:100%}:host([placement=top]) .wrapper,:host([placement=bottom]) .wrapper{max-height:90%}:host([placement=right]) .wrapper{right:100%}:host([visible][placement=right]) .wrapper{animation:slideInFromRight .3s forwards;animation-delay:.05s}:host([closing][placement=right]) .wrapper{animation:slideOutToRight .3s forwards}@keyframes slideInFromRight{0%{transform:translate(100%);right:0}to{transform:translateZ(0);right:0}}@keyframes slideOutToRight{0%{transform:translateZ(0);right:0}to{transform:translate(100%);right:0}}:host([placement=left]) .wrapper{left:-100%}:host([visible][placement=left]) .wrapper{animation:slideInFromLeft .3s forwards;animation-delay:.05s}:host([closing][placement=left]) .wrapper{animation:slideOutToLeft .3s forwards}@keyframes slideInFromLeft{0%{transform:translate(-100%);left:0}to{transform:translateZ(0);left:0}}@keyframes slideOutToLeft{0%{transform:translateZ(0);left:0}to{transform:translate(-100%);left:0}}:host([placement=top]) .wrapper{top:-100%}:host([visible][placement=top]) .wrapper{animation:slideInFromTop .3s forwards;animation-delay:.05s}:host([closing][placement=top]) .wrapper{animation:slideOutToTop .3s forwards}@keyframes slideInFromTop{0%{transform:translateY(-100%);top:0}to{transform:translateZ(0);top:0}}@keyframes slideOutToTop{0%{transform:translateZ(0);top:0}to{transform:translateY(-100%);top:0}}:host([placement=bottom]) .wrapper{bottom:100%}:host([visible][placement=bottom]) .wrapper{animation:slideInFromBottom .3s forwards;animation-delay:.05s}:host([closing][placement=bottom]) .wrapper{animation:slideOutToBottom .3s forwards}@keyframes slideInFromBottom{0%{transform:translateY(100%);bottom:0}to{transform:translateZ(0);bottom:0}}@keyframes slideOutToBottom{0%{transform:translateZ(0);bottom:0}to{transform:translateY(100%);bottom:0}}@media screen and (min-width: 768px){:host([size=sm][placement=left]) .wrapper,:host([size=sm][placement=right]) .wrapper{max-width:40%}}@media screen and (min-width: 1024px){:host([size=sm][placement=left]) .drawer,:host([size=sm][placement=right]) .drawer{max-width:740px}}@media screen and (min-width: 768px){:host([size=md][placement=left]) .wrapper,:host([size=md][placement=right]) .wrapper{max-width:70%}}@media screen and (min-width: 1024px){:host([size=md][placement=left]) .wrapper,:host([size=md][placement=right]) .wrapper{max-width:986px}}:host([size=sm][placement=top]:not([stretch])) .wrapper,:host([size=sm][placement=bottom]:not([stretch])) .wrapper{max-height:30%}:host([size=md][placement=top]:not([stretch])) .wrapper,:host([size=md][placement=bottom]:not([stretch])) .wrapper{max-height:50%}:host([stretch]) .wrapper{max-width:100%;max-height:100%}
|
|
2902
3130
|
`;
|
|
2903
3131
|
|
|
2904
3132
|
var tokensCss = i$5`:host{--ds-auro-drawer-container-color: var(--ds-basic-color-surface-default, #ffffff);--ds-auro-drawer-text-color: var(--ds-basic-color-texticon-default, #2a2a2a)}
|
|
@@ -2973,6 +3201,11 @@ class AuroDrawerContent extends i$2 {
|
|
|
2973
3201
|
visible: {
|
|
2974
3202
|
type: Boolean,
|
|
2975
3203
|
reflect: true
|
|
3204
|
+
},
|
|
3205
|
+
|
|
3206
|
+
closing: {
|
|
3207
|
+
type: Boolean,
|
|
3208
|
+
reflect: true
|
|
2976
3209
|
}
|
|
2977
3210
|
};
|
|
2978
3211
|
}
|
|
@@ -2985,27 +3218,33 @@ class AuroDrawerContent extends i$2 {
|
|
|
2985
3218
|
this.dispatchEvent(new CustomEvent("close-click"));
|
|
2986
3219
|
}
|
|
2987
3220
|
|
|
2988
|
-
handleWrapperTransitionEnd() {
|
|
2989
|
-
if (!this.visible) return;
|
|
2990
|
-
if (!this.focusTrap) return;
|
|
2991
|
-
this.focusTrap.focusFirstElement();
|
|
2992
|
-
}
|
|
2993
|
-
|
|
2994
3221
|
updated(changedProperties) {
|
|
2995
3222
|
if (changedProperties.has("visible")) {
|
|
2996
3223
|
if (this.visible) {
|
|
3224
|
+
// Reset CSS animation so it replays each time the drawer opens
|
|
3225
|
+
const wrapper = this.shadowRoot.querySelector('.wrapper');
|
|
3226
|
+
if (wrapper) {
|
|
3227
|
+
wrapper.style.animation = 'none';
|
|
3228
|
+
// Force reflow to restart the animation
|
|
3229
|
+
void wrapper.offsetHeight; // eslint-disable-line no-void
|
|
3230
|
+
wrapper.style.animation = '';
|
|
3231
|
+
}
|
|
3232
|
+
|
|
2997
3233
|
if (!this.focusTrap) {
|
|
2998
3234
|
this.focusTrap = new FocusTrap(this);
|
|
2999
3235
|
}
|
|
3000
|
-
this.prevActiveElement = document.activeElement;
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3236
|
+
this.prevActiveElement = this.triggerElement || document.activeElement;
|
|
3237
|
+
// Move focus to the first focusable element inside the drawer.
|
|
3238
|
+
// rAF lets showModal()'s native focus assignment settle before we override.
|
|
3239
|
+
requestAnimationFrame(() => {
|
|
3240
|
+
this.focusTrap?.focusFirstElement();
|
|
3241
|
+
});
|
|
3004
3242
|
} else {
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3243
|
+
// Native dialog.close() fires after a 300ms delay (see auro-floater-bib hideDialog).
|
|
3244
|
+
// Defer focus restoration so it runs after the dialog releases focus.
|
|
3245
|
+
const target = this.prevActiveElement;
|
|
3246
|
+
this.prevActiveElement = undefined;
|
|
3247
|
+
setTimeout(() => target?.focus(), 350);
|
|
3009
3248
|
|
|
3010
3249
|
if (this.focusTrap) {
|
|
3011
3250
|
this.focusTrap.disconnect();
|
|
@@ -3013,10 +3252,13 @@ class AuroDrawerContent extends i$2 {
|
|
|
3013
3252
|
}
|
|
3014
3253
|
}
|
|
3015
3254
|
}
|
|
3016
|
-
}
|
|
3017
3255
|
|
|
3018
|
-
|
|
3019
|
-
|
|
3256
|
+
if (changedProperties.has("closing") && this.closing) {
|
|
3257
|
+
// Reset closing state after animation completes
|
|
3258
|
+
setTimeout(() => {
|
|
3259
|
+
this.closing = false;
|
|
3260
|
+
}, 300);
|
|
3261
|
+
}
|
|
3020
3262
|
}
|
|
3021
3263
|
|
|
3022
3264
|
render() {
|
|
@@ -3024,7 +3266,7 @@ class AuroDrawerContent extends i$2 {
|
|
|
3024
3266
|
<!-- Hidden slot for close button aria-label -->
|
|
3025
3267
|
<slot name="ariaLabel.drawer.close" hidden @slotchange=${this.requestUpdate}></slot>
|
|
3026
3268
|
|
|
3027
|
-
<div class="wrapper" tabindex="-1" part="drawer-wrapper"
|
|
3269
|
+
<div class="wrapper" tabindex="-1" part="drawer-wrapper">
|
|
3028
3270
|
${
|
|
3029
3271
|
this.unformatted
|
|
3030
3272
|
? ""
|
|
@@ -3121,12 +3363,17 @@ const CONFIG = {
|
|
|
3121
3363
|
*
|
|
3122
3364
|
* @fires auroDrawer-toggled - Event fired when the drawer is toggled open or closed.
|
|
3123
3365
|
*
|
|
3124
|
-
* @csspart drawer-backdrop - to
|
|
3366
|
+
* @csspart {deprecated} drawer-backdrop - DEPRECATED - To migrate to the token approach, set `display: none` on this part and use the `--auro-drawer-backdrop-*` CSS custom properties instead.
|
|
3125
3367
|
* @csspart drawer-wrapper - to style the content wrapper.
|
|
3126
3368
|
* @csspart drawer-header - to style the header.
|
|
3127
3369
|
* @csspart drawer-content - to style the container of the drawer content.
|
|
3128
3370
|
* @csspart drawer-footer - to style the footer.
|
|
3129
3371
|
* @csspart close-button - to style the close button.
|
|
3372
|
+
*
|
|
3373
|
+
* @cssprop [--auro-drawer-backdrop-background=transparent] - Background of the `::backdrop` pseudo-element. In modal/backdrop mode the component sets this to the design-system scrim token; consumers can override it.
|
|
3374
|
+
* @cssprop [--auro-drawer-backdrop-filter=none] - `backdrop-filter` applied to the `::backdrop` pseudo-element (e.g. `blur(4px)`).
|
|
3375
|
+
* @cssprop [--auro-drawer-backdrop-opacity=1] - Opacity of the `::backdrop` pseudo-element.
|
|
3376
|
+
* @cssprop [--auro-drawer-backdrop-transition=opacity 0.3s ease] - Transition applied to the `::backdrop` pseudo-element (e.g. `opacity 0.3s ease`).
|
|
3130
3377
|
*/
|
|
3131
3378
|
class AuroDrawer extends AuroFloater {
|
|
3132
3379
|
constructor() {
|
|
@@ -3289,13 +3536,33 @@ class AuroDrawer extends AuroFloater {
|
|
|
3289
3536
|
);
|
|
3290
3537
|
|
|
3291
3538
|
this.drawerBib = document.createElement("auro-drawer-content");
|
|
3292
|
-
this.drawerBib.
|
|
3293
|
-
|
|
3294
|
-
|
|
3539
|
+
this.drawerBib.triggerElement = this.triggerElement;
|
|
3540
|
+
this.drawerBib.addEventListener("close-click", () => {
|
|
3541
|
+
this.bib?.hideDialog();
|
|
3542
|
+
this.floater.hideBib();
|
|
3543
|
+
});
|
|
3295
3544
|
this.append(this.drawerBib);
|
|
3296
3545
|
|
|
3297
3546
|
this.bib.setAttribute("exportparts", "backdrop:drawer-backdrop");
|
|
3298
3547
|
|
|
3548
|
+
// Handle Escape key via native dialog cancel event.
|
|
3549
|
+
// Always preventDefault in the bib; here we decide whether to actually close.
|
|
3550
|
+
this.bib.addEventListener("dialog-cancel", () => {
|
|
3551
|
+
if (this.modal) {
|
|
3552
|
+
return; // Modal drawers ignore Escape.
|
|
3553
|
+
}
|
|
3554
|
+
this.floater.hideBib();
|
|
3555
|
+
});
|
|
3556
|
+
|
|
3557
|
+
// Handle backdrop clicks — close unless this is a modal drawer.
|
|
3558
|
+
this.bib.addEventListener("dialog-backdrop-click", () => {
|
|
3559
|
+
if (this.modal) {
|
|
3560
|
+
return; // Modal drawers require an explicit action to close.
|
|
3561
|
+
}
|
|
3562
|
+
this.bib?.hideDialog();
|
|
3563
|
+
this.floater.hideBib();
|
|
3564
|
+
});
|
|
3565
|
+
|
|
3299
3566
|
this.setupAria();
|
|
3300
3567
|
}
|
|
3301
3568
|
|
|
@@ -3310,12 +3577,12 @@ class AuroDrawer extends AuroFloater {
|
|
|
3310
3577
|
this.bib.getAttribute("id"),
|
|
3311
3578
|
);
|
|
3312
3579
|
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
if (this.modal) {
|
|
3317
|
-
this.bib.setAttribute("aria-modal", "true");
|
|
3580
|
+
// Use bibLabel + aria-labelledby on the <dialog> instead of aria-label
|
|
3581
|
+
// directly — iOS VoiceOver does not reliably read aria-label on <dialog>.
|
|
3582
|
+
this.bib.bibLabel = this.triggerElement.textContent.trim();
|
|
3318
3583
|
}
|
|
3584
|
+
// role="dialog" and aria-modal are provided natively by the <dialog> element;
|
|
3585
|
+
// do not set them manually here.
|
|
3319
3586
|
}
|
|
3320
3587
|
|
|
3321
3588
|
/**
|
|
@@ -3353,9 +3620,15 @@ class AuroDrawer extends AuroFloater {
|
|
|
3353
3620
|
|
|
3354
3621
|
if (changedProperties.has("isPopoverVisible")) {
|
|
3355
3622
|
this.drawerBib.visible = this.isPopoverVisible;
|
|
3623
|
+
if (!this.isPopoverVisible) {
|
|
3624
|
+
this.drawerBib.closing = true;
|
|
3625
|
+
}
|
|
3356
3626
|
}
|
|
3357
3627
|
|
|
3358
3628
|
if (changedProperties.has("triggerElement")) {
|
|
3629
|
+
if (this.drawerBib) {
|
|
3630
|
+
this.drawerBib.triggerElement = this.triggerElement;
|
|
3631
|
+
}
|
|
3359
3632
|
this.setupAria();
|
|
3360
3633
|
}
|
|
3361
3634
|
}
|