@aurodesignsystem-dev/auro-formkit 0.0.0-pr1488.2 → 0.0.0-pr1489.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/components/bibtemplate/dist/auro-bibtemplate.d.ts +7 -0
- package/components/bibtemplate/dist/index.js +9 -1
- package/components/bibtemplate/dist/registered.js +9 -1
- package/components/checkbox/demo/customize.min.js +1 -1
- package/components/checkbox/demo/getting-started.min.js +1 -1
- package/components/checkbox/demo/index.min.js +1 -1
- package/components/checkbox/demo/pages.json +1 -1
- package/components/checkbox/demo/why-checkbox.html +57 -0
- package/components/checkbox/demo/why-checkbox.md +86 -0
- package/components/checkbox/dist/index.js +1 -1
- package/components/checkbox/dist/registered.js +1 -1
- package/components/combobox/demo/customize.min.js +234 -16
- package/components/combobox/demo/getting-started.min.js +234 -16
- package/components/combobox/demo/index.min.js +234 -16
- package/components/combobox/demo/pages.json +1 -1
- package/components/combobox/demo/why-combobox.html +57 -0
- package/components/combobox/demo/why-combobox.md +113 -0
- package/components/combobox/dist/index.js +234 -16
- package/components/combobox/dist/registered.js +234 -16
- package/components/counter/demo/customize.min.js +233 -15
- package/components/counter/demo/index.min.js +233 -15
- package/components/counter/demo/keyboard-behavior.md +1 -0
- package/components/counter/demo/pages.json +1 -1
- package/components/counter/demo/why-counter.html +57 -0
- package/components/counter/demo/why-counter.md +108 -0
- package/components/counter/dist/index.js +10 -2
- package/components/counter/dist/registered.js +10 -2
- package/components/datepicker/demo/accessibility.md +51 -3
- package/components/datepicker/demo/api.md +11 -2
- package/components/datepicker/demo/customize.html +2 -0
- package/components/datepicker/demo/customize.js +19 -0
- package/components/datepicker/demo/customize.md +72 -8
- package/components/datepicker/demo/customize.min.js +26029 -0
- package/components/datepicker/demo/design.md +3 -1
- package/components/datepicker/demo/index.js +5 -1
- package/components/datepicker/demo/index.md +83 -2
- package/components/datepicker/demo/index.min.js +1564 -96
- package/components/datepicker/demo/keyboard-behavior.md +201 -2
- package/components/datepicker/demo/pages.json +1 -1
- package/components/datepicker/demo/voiceover.md +19 -12
- package/components/datepicker/demo/why-datepicker.html +57 -0
- package/components/datepicker/demo/why-datepicker.md +133 -0
- package/components/datepicker/dist/index.js +1489 -97
- package/components/datepicker/dist/registered.js +1489 -97
- package/components/datepicker/dist/src/auro-calendar-cell.d.ts +66 -1
- package/components/datepicker/dist/src/auro-calendar-month.d.ts +28 -0
- package/components/datepicker/dist/src/auro-calendar.d.ts +100 -0
- package/components/datepicker/dist/src/auro-datepicker.d.ts +88 -0
- package/components/datepicker/dist/src/datepickerKeyboardStrategy.d.ts +5 -3
- package/components/dropdown/demo/accessibility.md +11 -0
- package/components/dropdown/demo/api.md +1 -0
- package/components/dropdown/demo/customize.md +3 -0
- package/components/dropdown/demo/customize.min.js +223 -13
- package/components/dropdown/demo/getting-started.min.js +223 -13
- package/components/dropdown/demo/index.min.js +223 -13
- package/components/dropdown/demo/keyboard-behavior.md +1 -0
- package/components/dropdown/demo/pages.json +1 -1
- package/components/dropdown/demo/why-dropdown.html +57 -0
- package/components/dropdown/demo/why-dropdown.md +97 -0
- package/components/dropdown/dist/auro-dropdown.d.ts +33 -1
- package/components/dropdown/dist/index.js +223 -13
- package/components/dropdown/dist/registered.js +223 -13
- package/components/form/demo/customize.min.js +2191 -145
- package/components/form/demo/getting-started.min.js +2191 -145
- package/components/form/demo/index.min.js +2191 -145
- package/components/form/demo/pages.json +1 -1
- package/components/form/demo/registerDemoDeps.min.js +2191 -145
- package/components/form/demo/why-form.html +57 -0
- package/components/form/demo/why-form.md +101 -0
- package/components/input/demo/customize.min.js +1 -1
- package/components/input/demo/getting-started.min.js +1 -1
- package/components/input/demo/index.min.js +1 -1
- package/components/input/demo/pages.json +1 -1
- package/components/input/demo/why-input.html +57 -0
- package/components/input/demo/why-input.md +121 -0
- package/components/input/dist/index.js +1 -1
- package/components/input/dist/registered.js +1 -1
- package/components/menu/demo/pages.json +1 -1
- package/components/menu/demo/why-menu.html +57 -0
- package/components/menu/demo/why-menu.md +104 -0
- package/components/radio/demo/customize.min.js +2186 -0
- package/components/radio/demo/demo-support.min.js +55807 -0
- package/components/radio/demo/getting-started.js +1 -1
- package/components/radio/demo/getting-started.md +1 -1
- package/components/radio/demo/getting-started.min.js +2205 -0
- package/components/radio/demo/index.min.js +1 -1
- package/components/radio/demo/pages.json +1 -1
- package/components/radio/demo/why-radio.html +57 -0
- package/components/radio/demo/why-radio.md +92 -0
- package/components/radio/dist/index.js +1 -1
- package/components/radio/dist/registered.js +1 -1
- package/components/select/demo/customize.min.js +233 -15
- package/components/select/demo/getting-started.min.js +233 -15
- package/components/select/demo/index.min.js +233 -15
- package/components/select/demo/keyboard-behavior.md +1 -0
- package/components/select/demo/pages.json +1 -1
- package/components/select/demo/why-select.html +57 -0
- package/components/select/demo/why-select.md +128 -0
- package/components/select/dist/index.js +233 -15
- package/components/select/dist/registered.js +233 -15
- package/custom-elements.json +745 -28
- package/package.json +2 -2
|
@@ -1521,7 +1521,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$2 {
|
|
|
1521
1521
|
}
|
|
1522
1522
|
};
|
|
1523
1523
|
|
|
1524
|
-
var formkitVersion$1 = '
|
|
1524
|
+
var formkitVersion$1 = '202606011856';
|
|
1525
1525
|
|
|
1526
1526
|
// Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
|
|
1527
1527
|
// See LICENSE in the project root for license information.
|
|
@@ -5236,7 +5236,7 @@ function applyKeyboardStrategy(component, strategy, options = {}) {
|
|
|
5236
5236
|
});
|
|
5237
5237
|
}
|
|
5238
5238
|
|
|
5239
|
-
var styleCss$2 = i$5`:host{position:fixed;z-index:var(--depth-tooltip, 400);display:none;isolation:isolate}:host dialog{width:auto;max-width:none;height:auto;max-height:none;padding:0;border:none;margin:0;outline:none;transform:translateZ(0)}:host dialog::backdrop{background:transparent}:host(:not([isfullscreen])) dialog{position:relative;inset:unset}:host(:not([isfullscreen])) .container.shape-box{border-radius:unset}:host(:not([isfullscreen])) .container[class*=shape-pill],:host(:not([isfullscreen])) .container[class*=shape-snowflake]{border-radius:30px}:host(:not([isfullscreen])) .container[class*=shape-rounded]{border-radius:16px}:host(:not([matchWidth])) .container{min-width:fit-content}:host([isfullscreen]){position:fixed;top:0;left:0}:host([isfullscreen]) .container{width:100dvw;max-width:none;height:100dvh;max-height:none;border-radius:unset;margin-top:0;box-shadow:unset;overscroll-behavior:contain}:host([isfullscreen]) .container::backdrop{background:var(--ds-color-background-primary, #fff)}:host(:popover-open){position:fixed;overflow:visible;padding:0;border:none;margin:0;background:transparent;inset:unset;outline:none}:host([data-show]){display:flex}:host([common]:not([isfullscreen])) .container,:host([rounded]:not([isfullscreen])) .container{border-radius:var(--ds-border-radius, 0.375rem)}:host([common][isfullscreen]) .container,:host([rounded][isfullscreen]) .container{border-radius:unset;box-shadow:unset}.container{display:inline-block;overflow:auto;box-sizing:border-box;border-radius:var(--ds-border-radius, 0.375rem);margin:var(--ds-size-50, 0.25rem) 0}.util_displayHiddenVisually{position:absolute;overflow:hidden;width:1px;height:1px;padding:0;border:0;margin:-1px;clip-path:inset(50%);white-space:nowrap}`;
|
|
5239
|
+
var styleCss$2 = i$5`:host{position:fixed;z-index:var(--depth-tooltip, 400);display:none;isolation:isolate}:host dialog{width:auto;max-width:none;height:auto;max-height:none;padding:0;border:none;margin:0;outline:none;transform:translateZ(0)}:host dialog::backdrop{background:transparent}:host(:not([isfullscreen])) dialog{position:relative;inset:unset}:host(:not([isfullscreen])) .container.shape-box{border-radius:unset}:host(:not([isfullscreen])) .container[class*=shape-pill],:host(:not([isfullscreen])) .container[class*=shape-snowflake]{border-radius:30px}:host(:not([isfullscreen])) .container[class*=shape-rounded]{border-radius:16px}:host([desktopmodal]:popover-open)::backdrop{background:transparent}:host(:not([matchWidth])) .container{min-width:fit-content}:host([isfullscreen]){position:fixed;top:0;left:0}:host([isfullscreen]) .container{width:100dvw;max-width:none;height:100dvh;max-height:none;border-radius:unset;margin-top:0;box-shadow:unset;overscroll-behavior:contain}:host([isfullscreen]) .container::backdrop{background:var(--ds-color-background-primary, #fff)}:host(:popover-open){position:fixed;overflow:visible;padding:0;border:none;margin:0;background:transparent;inset:unset;outline:none}:host([data-show]){display:flex}:host([common]:not([isfullscreen])) .container,:host([rounded]:not([isfullscreen])) .container{border-radius:var(--ds-border-radius, 0.375rem)}:host([common][isfullscreen]) .container,:host([rounded][isfullscreen]) .container{border-radius:unset;box-shadow:unset}.container{display:inline-block;overflow:auto;box-sizing:border-box;border-radius:var(--ds-border-radius, 0.375rem);margin:var(--ds-size-50, 0.25rem) 0}.util_displayHiddenVisually{position:absolute;overflow:hidden;width:1px;height:1px;padding:0;border:0;margin:-1px;clip-path:inset(50%);white-space:nowrap}`;
|
|
5240
5240
|
|
|
5241
5241
|
var colorCss$2 = i$5`.container{background-color:var(--ds-auro-dropdownbib-container-color);box-shadow:var(--ds-auro-dropdownbib-boxshadow-color);color:var(--ds-auro-dropdownbib-text-color)}`;
|
|
5242
5242
|
|
|
@@ -5867,7 +5867,7 @@ class AuroHelpText extends i$2 {
|
|
|
5867
5867
|
}
|
|
5868
5868
|
}
|
|
5869
5869
|
|
|
5870
|
-
var formkitVersion = '
|
|
5870
|
+
var formkitVersion = '202606011856';
|
|
5871
5871
|
|
|
5872
5872
|
let AuroElement$1 = class AuroElement extends i$2 {
|
|
5873
5873
|
static get properties() {
|
|
@@ -6047,6 +6047,7 @@ class AuroDropdown extends AuroElement$1 {
|
|
|
6047
6047
|
_intializeDefaults() {
|
|
6048
6048
|
this.appearance = 'default';
|
|
6049
6049
|
this.chevron = false;
|
|
6050
|
+
this.desktopModal = false;
|
|
6050
6051
|
this.disabled = false;
|
|
6051
6052
|
this.disableKeyboardHandling = false;
|
|
6052
6053
|
this.error = false;
|
|
@@ -6227,6 +6228,14 @@ class AuroDropdown extends AuroElement$1 {
|
|
|
6227
6228
|
reflect: true
|
|
6228
6229
|
},
|
|
6229
6230
|
|
|
6231
|
+
/**
|
|
6232
|
+
* If declared, the dropdown will behave as a modal dialog when in a desktop viewport size.
|
|
6233
|
+
*/
|
|
6234
|
+
desktopModal: {
|
|
6235
|
+
type: Boolean,
|
|
6236
|
+
reflect: true
|
|
6237
|
+
},
|
|
6238
|
+
|
|
6230
6239
|
/**
|
|
6231
6240
|
* If declared, the dropdown will only show by calling the API .show() public method.
|
|
6232
6241
|
*/
|
|
@@ -6514,6 +6523,15 @@ class AuroDropdown extends AuroElement$1 {
|
|
|
6514
6523
|
|
|
6515
6524
|
disconnectedCallback() {
|
|
6516
6525
|
super.disconnectedCallback();
|
|
6526
|
+
this._clearPageInert();
|
|
6527
|
+
if (this._bibTabHandler) {
|
|
6528
|
+
this.removeEventListener('keydown', this._bibTabHandler);
|
|
6529
|
+
this._bibTabHandler = undefined;
|
|
6530
|
+
}
|
|
6531
|
+
if (this.focusTrap) {
|
|
6532
|
+
this.focusTrap.disconnect();
|
|
6533
|
+
this.focusTrap = undefined;
|
|
6534
|
+
}
|
|
6517
6535
|
if (this.floater) {
|
|
6518
6536
|
this.floater.hideBib('disconnect');
|
|
6519
6537
|
this.floater.disconnect();
|
|
@@ -6541,19 +6559,45 @@ class AuroDropdown extends AuroElement$1 {
|
|
|
6541
6559
|
if (this.isPopoverVisible) {
|
|
6542
6560
|
// Fullscreen: use showModal() for native accessibility (inert outside, focus trap)
|
|
6543
6561
|
// Desktop: use show() for Floating UI positioning + FocusTrap for focus management
|
|
6544
|
-
|
|
6545
|
-
this.
|
|
6562
|
+
this.bibElement.value.open(this.isBibFullscreen);
|
|
6563
|
+
this.updateFocusTrap();
|
|
6564
|
+
|
|
6565
|
+
// Desktop modal: make siblings inert so content outside is not interactive
|
|
6566
|
+
if (this.desktopModal && !this.isBibFullscreen) {
|
|
6567
|
+
this._setPageInert();
|
|
6568
|
+
}
|
|
6546
6569
|
} else {
|
|
6547
6570
|
this.bibElement.value.close();
|
|
6571
|
+
this._clearPageInert();
|
|
6548
6572
|
}
|
|
6549
6573
|
}
|
|
6550
6574
|
|
|
6551
6575
|
// When fullscreen strategy changes while open, re-open dialog with correct mode
|
|
6552
6576
|
// (e.g. resizing from desktop → mobile while dropdown is open)
|
|
6553
6577
|
if (changedProperties.has('isBibFullscreen') && this.isPopoverVisible && this.bibElement.value) {
|
|
6554
|
-
const useModal = this.isBibFullscreen;
|
|
6555
6578
|
this.bibElement.value.close();
|
|
6556
|
-
this.bibElement.value.open(
|
|
6579
|
+
this.bibElement.value.open(this.isBibFullscreen);
|
|
6580
|
+
|
|
6581
|
+
// Re-initialize focus management for the new strategy
|
|
6582
|
+
this.updateFocusTrap();
|
|
6583
|
+
|
|
6584
|
+
// Toggle inert: desktop modal needs it, fullscreen showModal() handles it natively
|
|
6585
|
+
if (this.desktopModal && !this.isBibFullscreen) {
|
|
6586
|
+
this._setPageInert();
|
|
6587
|
+
} else {
|
|
6588
|
+
this._clearPageInert();
|
|
6589
|
+
}
|
|
6590
|
+
}
|
|
6591
|
+
|
|
6592
|
+
// Handle desktopModal toggled while the dropdown is already open.
|
|
6593
|
+
// Re-initialize focus trapping and page inert state to match the new mode.
|
|
6594
|
+
if (changedProperties.has('desktopModal') && this.isPopoverVisible && !this.isBibFullscreen) {
|
|
6595
|
+
this.updateFocusTrap();
|
|
6596
|
+
if (this.desktopModal) {
|
|
6597
|
+
this._setPageInert();
|
|
6598
|
+
} else {
|
|
6599
|
+
this._clearPageInert();
|
|
6600
|
+
}
|
|
6557
6601
|
}
|
|
6558
6602
|
}
|
|
6559
6603
|
|
|
@@ -6563,8 +6607,14 @@ class AuroDropdown extends AuroElement$1 {
|
|
|
6563
6607
|
* @param {CustomEvent} event - The custom event that contains the dropdown toggle information.
|
|
6564
6608
|
*/
|
|
6565
6609
|
handleDropdownToggle(event) {
|
|
6566
|
-
this.updateFocusTrap();
|
|
6567
6610
|
this.isPopoverVisible = event.detail.expanded;
|
|
6611
|
+
|
|
6612
|
+
// Tear down FocusTrap when closing. Creation happens in updated()
|
|
6613
|
+
// after the dialog is open so getFocusableElements can find content.
|
|
6614
|
+
if (!this.isPopoverVisible) {
|
|
6615
|
+
this.updateFocusTrap();
|
|
6616
|
+
}
|
|
6617
|
+
|
|
6568
6618
|
const eventType = event.detail.eventType || "unknown";
|
|
6569
6619
|
if (!this.isPopoverVisible && this.hasFocus && eventType === "keydown") {
|
|
6570
6620
|
this.trigger.focus();
|
|
@@ -6663,19 +6713,178 @@ class AuroDropdown extends AuroElement$1 {
|
|
|
6663
6713
|
* @private
|
|
6664
6714
|
*/
|
|
6665
6715
|
updateFocusTrap() {
|
|
6716
|
+
// Always clean up existing handlers/traps before setting up new ones
|
|
6717
|
+
// to prevent duplicate listeners on repeated calls.
|
|
6718
|
+
if (this._bibTabHandler) {
|
|
6719
|
+
this.removeEventListener('keydown', this._bibTabHandler);
|
|
6720
|
+
this._bibTabHandler = undefined;
|
|
6721
|
+
}
|
|
6722
|
+
|
|
6723
|
+
if (this.focusTrap) {
|
|
6724
|
+
this.focusTrap.disconnect();
|
|
6725
|
+
this.focusTrap = undefined;
|
|
6726
|
+
}
|
|
6727
|
+
|
|
6666
6728
|
if (this.isPopoverVisible) {
|
|
6667
6729
|
if (!this.isBibFullscreen) {
|
|
6668
|
-
|
|
6669
|
-
|
|
6670
|
-
|
|
6730
|
+
if (this.desktopModal) {
|
|
6731
|
+
// Desktop modal: trap focus only within the bib content.
|
|
6732
|
+
// Can't use FocusTrap on the bib element because keydown events
|
|
6733
|
+
// from slotted content bubble through the dropdown host (light DOM),
|
|
6734
|
+
// not through the bib (shadow projection target). Using FocusTrap
|
|
6735
|
+
// on the dropdown would include the trigger in the tab cycle.
|
|
6736
|
+
// Instead, listen for Tab on the dropdown and manually wrap focus
|
|
6737
|
+
// within the bib's focusable elements.
|
|
6738
|
+
this._bibTabHandler = (event) => {
|
|
6739
|
+
if (event.key !== 'Tab') {
|
|
6740
|
+
return;
|
|
6741
|
+
}
|
|
6742
|
+
|
|
6743
|
+
// Collect focusable elements from the bib content.
|
|
6744
|
+
const focusables = getFocusableElements(this.bibContent);
|
|
6745
|
+
|
|
6746
|
+
// Fallback: try from slotted content directly
|
|
6747
|
+
if (!focusables.length) {
|
|
6748
|
+
const slot = this.shadowRoot.querySelector('.slotContent slot');
|
|
6749
|
+
const assignedNodes = slot ? slot.assignedNodes({ flatten: true }) : [];
|
|
6750
|
+
|
|
6751
|
+
for (const node of assignedNodes) {
|
|
6752
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
6753
|
+
focusables.push(...getFocusableElements(node));
|
|
6754
|
+
}
|
|
6755
|
+
}
|
|
6756
|
+
}
|
|
6757
|
+
|
|
6758
|
+
if (!focusables.length) {
|
|
6759
|
+
return;
|
|
6760
|
+
}
|
|
6761
|
+
|
|
6762
|
+
event.preventDefault();
|
|
6763
|
+
|
|
6764
|
+
const direction = event.shiftKey ? -1 : 1; // eslint-disable-line no-magic-numbers
|
|
6765
|
+
|
|
6766
|
+
// Walk the active element chain through shadow roots
|
|
6767
|
+
const actives = this._getActiveElements();
|
|
6768
|
+
|
|
6769
|
+
let idx = focusables.findIndex((el) => actives.includes(el));
|
|
6770
|
+
|
|
6771
|
+
if (idx === -1) { // eslint-disable-line no-magic-numbers
|
|
6772
|
+
// Focus is not on a known element — move to first/last
|
|
6773
|
+
idx = direction === 1 ? -1 : focusables.length; // eslint-disable-line no-magic-numbers
|
|
6774
|
+
}
|
|
6775
|
+
|
|
6776
|
+
// Try each element in order, skipping any that can't receive focus
|
|
6777
|
+
// (e.g. hidden elements, elements in collapsed sections)
|
|
6778
|
+
for (let index = 0; index < focusables.length; index++) { // eslint-disable-line no-plusplus
|
|
6779
|
+
let nextIdx = idx + direction;
|
|
6780
|
+
|
|
6781
|
+
// Wrap around
|
|
6782
|
+
if (nextIdx < 0) {
|
|
6783
|
+
nextIdx = focusables.length - 1;
|
|
6784
|
+
} else if (nextIdx >= focusables.length) {
|
|
6785
|
+
nextIdx = 0;
|
|
6786
|
+
}
|
|
6787
|
+
|
|
6788
|
+
focusables[nextIdx].focus();
|
|
6789
|
+
|
|
6790
|
+
// Verify focus actually moved to the target
|
|
6791
|
+
const newActives = this._getActiveElements();
|
|
6792
|
+
|
|
6793
|
+
if (newActives.includes(focusables[nextIdx])) {
|
|
6794
|
+
return;
|
|
6795
|
+
}
|
|
6796
|
+
|
|
6797
|
+
// Focus didn't stick — skip this element and try the next
|
|
6798
|
+
idx = nextIdx;
|
|
6799
|
+
}
|
|
6800
|
+
};
|
|
6801
|
+
this.addEventListener('keydown', this._bibTabHandler);
|
|
6802
|
+
|
|
6803
|
+
// Move initial focus into the bib content, matching FocusTrap behavior
|
|
6804
|
+
requestAnimationFrame(() => {
|
|
6805
|
+
const focusables = getFocusableElements(this.bibContent);
|
|
6806
|
+
if (focusables.length) {
|
|
6807
|
+
focusables[0].focus();
|
|
6808
|
+
}
|
|
6809
|
+
});
|
|
6810
|
+
} else {
|
|
6811
|
+
// Normal desktop: use FocusTrap on the bib element
|
|
6812
|
+
this.focusTrap = new FocusTrap(this.bibContent);
|
|
6813
|
+
this.focusTrap.focusFirstElement();
|
|
6814
|
+
}
|
|
6671
6815
|
}
|
|
6672
6816
|
// Fullscreen: showModal() provides native focus trapping
|
|
6817
|
+
}
|
|
6818
|
+
}
|
|
6819
|
+
|
|
6820
|
+
/**
|
|
6821
|
+
* Returns the chain of active (focused) elements through shadow roots.
|
|
6822
|
+
* @private
|
|
6823
|
+
* @returns {Array<HTMLElement>}
|
|
6824
|
+
*/
|
|
6825
|
+
_getActiveElements() {
|
|
6826
|
+
let { activeElement } = document;
|
|
6827
|
+
const actives = [activeElement];
|
|
6828
|
+
|
|
6829
|
+
while (activeElement?.shadowRoot?.activeElement) {
|
|
6830
|
+
activeElement = activeElement.shadowRoot.activeElement;
|
|
6831
|
+
actives.push(activeElement);
|
|
6832
|
+
}
|
|
6833
|
+
|
|
6834
|
+
return actives;
|
|
6835
|
+
}
|
|
6836
|
+
|
|
6837
|
+
/**
|
|
6838
|
+
* Sets `inert` on sibling elements of the dropdown's top-level host
|
|
6839
|
+
* so that content outside the dropdown is not interactive while the modal is open.
|
|
6840
|
+
* Walks up through shadow DOM boundaries to find the outermost host element
|
|
6841
|
+
* in the light DOM, then sets `inert` on siblings at each ancestor level
|
|
6842
|
+
* to ensure all page content outside the host subtree is inert.
|
|
6843
|
+
* @private
|
|
6844
|
+
*/
|
|
6845
|
+
_setPageInert() {
|
|
6846
|
+
if (this._inertSiblings) {
|
|
6673
6847
|
return;
|
|
6674
6848
|
}
|
|
6675
6849
|
|
|
6676
|
-
|
|
6677
|
-
|
|
6678
|
-
|
|
6850
|
+
this._inertSiblings = [];
|
|
6851
|
+
|
|
6852
|
+
// Walk up through shadow DOM boundaries to find the topmost host
|
|
6853
|
+
// element in the light DOM. For example, if this dropdown is inside
|
|
6854
|
+
// auro-datepicker's shadow DOM, we walk up to the datepicker element
|
|
6855
|
+
// so we set inert on its siblings — not on the datepicker itself.
|
|
6856
|
+
let host = this;
|
|
6857
|
+
while (host.getRootNode() instanceof ShadowRoot) {
|
|
6858
|
+
host = host.getRootNode().host;
|
|
6859
|
+
}
|
|
6860
|
+
|
|
6861
|
+
// Walk up the ancestor chain, inerting siblings at each level
|
|
6862
|
+
// to ensure the entire page outside the host subtree is inert.
|
|
6863
|
+
let current = host;
|
|
6864
|
+
while (current.parentElement) {
|
|
6865
|
+
const parent = current.parentElement;
|
|
6866
|
+
for (const sibling of parent.children) {
|
|
6867
|
+
if (sibling !== current) {
|
|
6868
|
+
this._inertSiblings.push({ element: sibling, wasInert: sibling.inert });
|
|
6869
|
+
sibling.inert = true;
|
|
6870
|
+
}
|
|
6871
|
+
}
|
|
6872
|
+
current = parent;
|
|
6873
|
+
}
|
|
6874
|
+
}
|
|
6875
|
+
|
|
6876
|
+
/**
|
|
6877
|
+
* Restores `inert` state on siblings that were tracked by `_setPageInert`.
|
|
6878
|
+
* Preserves the previous inert state so externally-inerted elements are
|
|
6879
|
+
* not inadvertently re-enabled.
|
|
6880
|
+
* @private
|
|
6881
|
+
*/
|
|
6882
|
+
_clearPageInert() {
|
|
6883
|
+
if (this._inertSiblings) {
|
|
6884
|
+
for (const entry of this._inertSiblings) {
|
|
6885
|
+
entry.element.inert = entry.wasInert;
|
|
6886
|
+
}
|
|
6887
|
+
this._inertSiblings = undefined;
|
|
6679
6888
|
}
|
|
6680
6889
|
}
|
|
6681
6890
|
|
|
@@ -6914,6 +7123,7 @@ class AuroDropdown extends AuroElement$1 {
|
|
|
6914
7123
|
shape="${this.shape}"
|
|
6915
7124
|
?data-show="${this.isPopoverVisible}"
|
|
6916
7125
|
?isfullscreen="${this.isBibFullscreen}"
|
|
7126
|
+
?desktopmodal="${this.desktopModal}"
|
|
6917
7127
|
.dialogLabel="${this.bibDialogLabel}"
|
|
6918
7128
|
${n$1(this.bibElement)}
|
|
6919
7129
|
>
|
|
@@ -7281,6 +7491,14 @@ class AuroBibtemplate extends i$2 {
|
|
|
7281
7491
|
large: {
|
|
7282
7492
|
type: Boolean,
|
|
7283
7493
|
reflect: true
|
|
7494
|
+
},
|
|
7495
|
+
|
|
7496
|
+
/**
|
|
7497
|
+
* If declared, the footer slot will be rendered even when not in fullscreen mode.
|
|
7498
|
+
*/
|
|
7499
|
+
showFooter: {
|
|
7500
|
+
type: Boolean,
|
|
7501
|
+
reflect: true
|
|
7284
7502
|
}
|
|
7285
7503
|
};
|
|
7286
7504
|
}
|
|
@@ -7383,7 +7601,7 @@ class AuroBibtemplate extends i$2 {
|
|
|
7383
7601
|
<slot></slot>
|
|
7384
7602
|
</div>
|
|
7385
7603
|
|
|
7386
|
-
${this.isFullscreen ? u$5`
|
|
7604
|
+
${this.isFullscreen || this.showFooter ? u$5`
|
|
7387
7605
|
<div id="footerContainer">
|
|
7388
7606
|
<slot name="footer"></slot>
|
|
7389
7607
|
</div>` : null}
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
<p>The trigger is a focusable element and participates in the standard tab order, responding to <code>Tab</code> and <code>Shift+Tab</code> key events per <auro-hyperlink href="https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/tabindex">native browser behavior</auro-hyperlink>, i.e., these keys step through the browser tabindex sequence.</p>
|
|
13
13
|
<p>When the component is <code>disabled</code> it is removed from the <code>tabindex</code> sequence. VoiceOver's virtual cursor <em>(swipe navigation)</em> can still encounter the component, but standard keyboard <code>Tab</code> navigation skips it.</p>
|
|
14
14
|
<p>When the bib is collapsed, the bib content is excluded from the tab sequence. When <strong>expanded</strong>, focusable elements within the bib content are included in the natural tab order. In fullscreen mode, focus is trapped within the bib, and the tab sequence cycles through the bib content focusable elements until the bib is closed or the viewport no longer meets the fullscreen condition and is rendered as a popover.</p>
|
|
15
|
+
<p>When the <code>desktopModal</code> attribute is set, focus is also trapped within the bib on desktop viewports. All sibling elements on the page are marked <code>inert</code>, preventing interaction with content outside the dropdown until it is closed.</p>
|
|
15
16
|
<!-- AURO-GENERATED-CONTENT:END -->
|
|
16
17
|
<auro-header level="2" id="keyEvents">Key Events</auro-header>
|
|
17
18
|
<auro-header level="3" id="keyEventsCounter">Counter</auro-header>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
["accessibility.md","api.md","customize.md","design.md","getting-started.md","index.md","keyboard-behavior.md","voiceover.md","readme.md"]
|
|
1
|
+
["accessibility.md","api.md","customize.md","design.md","getting-started.md","index.md","keyboard-behavior.md","voiceover.md","why-counter.md","readme.md"]
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
|
|
3
|
+
See LICENSE in the project root for license information.
|
|
4
|
+
|
|
5
|
+
HTML in this document is standardized and NOT to be edited.
|
|
6
|
+
All demo code should be added/edited in ./demo/why-counter.md
|
|
7
|
+
|
|
8
|
+
With the exception of adding custom elements if needed for the demo.
|
|
9
|
+
|
|
10
|
+
----------------------- DO NOT EDIT -----------------------------
|
|
11
|
+
|
|
12
|
+
-->
|
|
13
|
+
|
|
14
|
+
<!DOCTYPE html>
|
|
15
|
+
<html lang="en">
|
|
16
|
+
<head>
|
|
17
|
+
<meta charset="UTF-8" />
|
|
18
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
19
|
+
<title>Auro Web Component Demo | auro-counter | Why auro-counter</title>
|
|
20
|
+
|
|
21
|
+
<!-- highlight.js Stylesheet -->
|
|
22
|
+
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/styles/github.min.css"/>
|
|
23
|
+
|
|
24
|
+
<!-- Legacy reference is still needed to support auro-counter's use of legacy token values at this time -->
|
|
25
|
+
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/@aurodesignsystem/design-tokens@latest/dist/legacy/auro-classic/CSSCustomProperties.css"/>
|
|
26
|
+
|
|
27
|
+
<!-- Design Token Alaska Theme -->
|
|
28
|
+
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/@aurodesignsystem/design-tokens@latest/dist/themes/alaska/CSSCustomProperties--alaska.min.css"/>
|
|
29
|
+
|
|
30
|
+
<!-- Webcore Stylesheet Alaska Theme -->
|
|
31
|
+
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/@aurodesignsystem/webcorestylesheets@latest/dist/bundled/themes/alaska.global.min.css" />
|
|
32
|
+
|
|
33
|
+
<!-- Demo Specific Styles -->
|
|
34
|
+
<link rel="stylesheet" type="text/css" href="./styles.min.css" />
|
|
35
|
+
<style>
|
|
36
|
+
table {
|
|
37
|
+
--ds-color-container-secondary-default: transparent;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
tr:not(:last-of-type) {
|
|
41
|
+
border-bottom: 1px solid var(--ds-color-border-tertiary-default);
|
|
42
|
+
}
|
|
43
|
+
</style>
|
|
44
|
+
</head>
|
|
45
|
+
<body class="auro-markdown">
|
|
46
|
+
<main></main>
|
|
47
|
+
|
|
48
|
+
<script type="module">
|
|
49
|
+
import { renderPage } from './demo-support.min.js';
|
|
50
|
+
await renderPage('./why-counter.md');
|
|
51
|
+
</script>
|
|
52
|
+
|
|
53
|
+
<!-- If additional elements are needed for the demo, add them here. -->
|
|
54
|
+
<script src="https://cdn.jsdelivr.net/npm/@aurodesignsystem/auro-header@latest/+esm" type="module"></script>
|
|
55
|
+
<script src="https://cdn.jsdelivr.net/npm/@aurodesignsystem/auro-hyperlink@latest/+esm" type="module"></script>
|
|
56
|
+
</body>
|
|
57
|
+
</html>
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
<auro-header level="1" id="overview">Why auro-counter?</auro-header>
|
|
2
|
+
<p>The native <code><input type="number"></code> provides a basic numeric input, but it lacks the spinbutton accessibility pattern, has no concept of grouped counters with shared constraints, and renders inconsistently across browsers. <code>auro-counter</code> and <code>auro-counter-group</code> provide an accessible, feature-rich alternative.</p>
|
|
3
|
+
<auro-header level="2" id="accessibility">Accessibility</auro-header>
|
|
4
|
+
<p>Native number inputs have limited screen reader support. The browser-rendered increment/decrement buttons are often small, difficult to interact with, and announced inconsistently.</p>
|
|
5
|
+
<p><code>auro-counter</code> provides:</p>
|
|
6
|
+
<ul>
|
|
7
|
+
<li><strong>ARIA spinbutton pattern</strong> — The component uses <code>role="spinbutton"</code> with <code>aria-valuemin</code>, <code>aria-valuemax</code>, <code>aria-valuenow</code>, and <code>aria-valuetext</code> for complete screen reader semantics.</li>
|
|
8
|
+
<li><strong>Labeled controls</strong> — Increment and decrement buttons have customizable ARIA labels via <code>ariaLabel.plus</code> and <code>ariaLabel.minus</code> slots.</li>
|
|
9
|
+
<li><strong>Keyboard shortcuts</strong> — Arrow Up/Down, Ctrl+Arrow, and +/- keys all increment and decrement the value. These shortcuts go beyond what native number inputs provide.</li>
|
|
10
|
+
<li><strong>Focus delegation</strong> — <code>delegatesFocus</code> ensures focus reaches the interactive control regardless of where the user clicks.</li>
|
|
11
|
+
<li><strong>Description binding</strong> — The <code>description</code> slot content is linked via <code>aria-describedByElements</code> for additional context.</li>
|
|
12
|
+
</ul>
|
|
13
|
+
<auro-header level="2" id="smartButtonState">Smart button state</auro-header>
|
|
14
|
+
<p>Native number inputs allow the user to type or spin past the min/max bounds, then rely on validation to catch the error.</p>
|
|
15
|
+
<p><code>auro-counter</code> takes a proactive approach:</p>
|
|
16
|
+
<ul>
|
|
17
|
+
<li>The decrement button disables automatically at <code>min</code></li>
|
|
18
|
+
<li>The increment button disables automatically at <code>max</code></li>
|
|
19
|
+
<li>In a group, buttons disable based on the aggregate total, preventing any individual counter from pushing the group past its constraints</li>
|
|
20
|
+
</ul>
|
|
21
|
+
<auro-header level="2" id="counterGroups">Counter groups</auro-header>
|
|
22
|
+
<p>HTML has no concept of related numeric inputs with a shared constraint. For example, a passenger selector with "Adults", "Children", and "Infants" that must total no more than 9 requires custom JavaScript.</p>
|
|
23
|
+
<p><code>auro-counter-group</code> handles this with:</p>
|
|
24
|
+
<ul>
|
|
25
|
+
<li>An aggregate <code>total</code> computed from all child counters</li>
|
|
26
|
+
<li>Group-level <code>min</code> and <code>max</code> constraints applied across all children</li>
|
|
27
|
+
<li>A <code>value</code> object with named entries (e.g., <code>{ adults: 2, children: 1 }</code>)</li>
|
|
28
|
+
<li>Dynamic button disabling — when the group total reaches max, all increment buttons disable; when it reaches min, all decrement buttons disable</li>
|
|
29
|
+
<li>Group-level validation that aggregates individual counter errors</li>
|
|
30
|
+
<li>Optional dropdown presentation with <code>isDropdown</code> for compact UI</li>
|
|
31
|
+
</ul>
|
|
32
|
+
<auro-header level="2" id="responsiveLayout">Responsive layout</auro-header>
|
|
33
|
+
<p>Native number inputs have no concept of responsive presentation.</p>
|
|
34
|
+
<p><code>auro-counter-group</code> in dropdown mode adapts to the viewport:</p>
|
|
35
|
+
<ul>
|
|
36
|
+
<li><strong>Desktop</strong> — Counters appear in a positioned dropdown panel</li>
|
|
37
|
+
<li><strong>Mobile</strong> — Counters open in a fullscreen dialog with a configurable breakpoint</li>
|
|
38
|
+
<li>Layout options (classic, snowflake) control visual presentation</li>
|
|
39
|
+
</ul>
|
|
40
|
+
<auro-header level="2" id="validation">Validation</auro-header>
|
|
41
|
+
<p>Native number input validation is limited to <code>min</code>, <code>max</code>, <code>step</code>, and <code>required</code>.</p>
|
|
42
|
+
<p><code>auro-counter</code> integrates with the Auro form validation system:</p>
|
|
43
|
+
<ul>
|
|
44
|
+
<li>Group-level validation aggregates errors from all child counters</li>
|
|
45
|
+
<li><code>touched</code> tracking ensures errors appear only after interaction</li>
|
|
46
|
+
<li>Dispatches <code>auroFormElement-validated</code> events for parent form coordination</li>
|
|
47
|
+
</ul>
|
|
48
|
+
<auro-header level="2" id="designSystemIntegration">Design system integration</auro-header>
|
|
49
|
+
<p>Native number inputs render browser-specific controls that cannot be styled consistently.</p>
|
|
50
|
+
<p><code>auro-counter</code> is built with the Auro Design System:</p>
|
|
51
|
+
<ul>
|
|
52
|
+
<li>Consistent visual language with clearly labeled +/- buttons</li>
|
|
53
|
+
<li>Light and dark theme support (<code>appearance</code>)</li>
|
|
54
|
+
<li>CSS <code>::part()</code> selectors (<code>counterControl</code>, <code>controlPlus</code>, <code>controlMinus</code>, <code>helpText</code>)</li>
|
|
55
|
+
<li>Design token integration for sizing and spacing</li>
|
|
56
|
+
</ul>
|
|
57
|
+
<auro-header level="2" id="summary">Summary</auro-header>
|
|
58
|
+
<table>
|
|
59
|
+
<thead>
|
|
60
|
+
<tr>
|
|
61
|
+
<th>Capability</th>
|
|
62
|
+
<th><code><input type="number"></code></th>
|
|
63
|
+
<th><code>auro-counter</code></th>
|
|
64
|
+
</tr>
|
|
65
|
+
</thead>
|
|
66
|
+
<tbody>
|
|
67
|
+
<tr>
|
|
68
|
+
<td>ARIA spinbutton semantics</td>
|
|
69
|
+
<td>No</td>
|
|
70
|
+
<td>Full implementation</td>
|
|
71
|
+
</tr>
|
|
72
|
+
<tr>
|
|
73
|
+
<td>Auto-disable at min/max</td>
|
|
74
|
+
<td>No</td>
|
|
75
|
+
<td>Yes</td>
|
|
76
|
+
</tr>
|
|
77
|
+
<tr>
|
|
78
|
+
<td>Grouped counters with shared max</td>
|
|
79
|
+
<td>Not supported</td>
|
|
80
|
+
<td>Built-in with <code>auro-counter-group</code></td>
|
|
81
|
+
</tr>
|
|
82
|
+
<tr>
|
|
83
|
+
<td>Aggregate value object</td>
|
|
84
|
+
<td>Not supported</td>
|
|
85
|
+
<td><code>{ name: value }</code> pairs</td>
|
|
86
|
+
</tr>
|
|
87
|
+
<tr>
|
|
88
|
+
<td>Keyboard shortcuts</td>
|
|
89
|
+
<td>Arrow keys only</td>
|
|
90
|
+
<td>Arrows, Ctrl+Arrows, +/-</td>
|
|
91
|
+
</tr>
|
|
92
|
+
<tr>
|
|
93
|
+
<td>Mobile fullscreen (group)</td>
|
|
94
|
+
<td>No</td>
|
|
95
|
+
<td>Automatic at breakpoint</td>
|
|
96
|
+
</tr>
|
|
97
|
+
<tr>
|
|
98
|
+
<td>Consistent cross-browser UI</td>
|
|
99
|
+
<td>No</td>
|
|
100
|
+
<td>Yes</td>
|
|
101
|
+
</tr>
|
|
102
|
+
<tr>
|
|
103
|
+
<td>Theming</td>
|
|
104
|
+
<td>Browser-dependent</td>
|
|
105
|
+
<td>Full design system integration</td>
|
|
106
|
+
</tr>
|
|
107
|
+
</tbody>
|
|
108
|
+
</table>
|
|
@@ -1471,7 +1471,7 @@ class AuroHelpText extends LitElement {
|
|
|
1471
1471
|
}
|
|
1472
1472
|
}
|
|
1473
1473
|
|
|
1474
|
-
var formkitVersion = '
|
|
1474
|
+
var formkitVersion = '202606011856';
|
|
1475
1475
|
|
|
1476
1476
|
// Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
|
|
1477
1477
|
// See LICENSE in the project root for license information.
|
|
@@ -2209,6 +2209,14 @@ class AuroBibtemplate extends LitElement {
|
|
|
2209
2209
|
large: {
|
|
2210
2210
|
type: Boolean,
|
|
2211
2211
|
reflect: true
|
|
2212
|
+
},
|
|
2213
|
+
|
|
2214
|
+
/**
|
|
2215
|
+
* If declared, the footer slot will be rendered even when not in fullscreen mode.
|
|
2216
|
+
*/
|
|
2217
|
+
showFooter: {
|
|
2218
|
+
type: Boolean,
|
|
2219
|
+
reflect: true
|
|
2212
2220
|
}
|
|
2213
2221
|
};
|
|
2214
2222
|
}
|
|
@@ -2311,7 +2319,7 @@ class AuroBibtemplate extends LitElement {
|
|
|
2311
2319
|
<slot></slot>
|
|
2312
2320
|
</div>
|
|
2313
2321
|
|
|
2314
|
-
${this.isFullscreen ? html`
|
|
2322
|
+
${this.isFullscreen || this.showFooter ? html`
|
|
2315
2323
|
<div id="footerContainer">
|
|
2316
2324
|
<slot name="footer"></slot>
|
|
2317
2325
|
</div>` : null}
|
|
@@ -1471,7 +1471,7 @@ class AuroHelpText extends LitElement {
|
|
|
1471
1471
|
}
|
|
1472
1472
|
}
|
|
1473
1473
|
|
|
1474
|
-
var formkitVersion = '
|
|
1474
|
+
var formkitVersion = '202606011856';
|
|
1475
1475
|
|
|
1476
1476
|
// Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
|
|
1477
1477
|
// See LICENSE in the project root for license information.
|
|
@@ -2209,6 +2209,14 @@ class AuroBibtemplate extends LitElement {
|
|
|
2209
2209
|
large: {
|
|
2210
2210
|
type: Boolean,
|
|
2211
2211
|
reflect: true
|
|
2212
|
+
},
|
|
2213
|
+
|
|
2214
|
+
/**
|
|
2215
|
+
* If declared, the footer slot will be rendered even when not in fullscreen mode.
|
|
2216
|
+
*/
|
|
2217
|
+
showFooter: {
|
|
2218
|
+
type: Boolean,
|
|
2219
|
+
reflect: true
|
|
2212
2220
|
}
|
|
2213
2221
|
};
|
|
2214
2222
|
}
|
|
@@ -2311,7 +2319,7 @@ class AuroBibtemplate extends LitElement {
|
|
|
2311
2319
|
<slot></slot>
|
|
2312
2320
|
</div>
|
|
2313
2321
|
|
|
2314
|
-
${this.isFullscreen ? html`
|
|
2322
|
+
${this.isFullscreen || this.showFooter ? html`
|
|
2315
2323
|
<div id="footerContainer">
|
|
2316
2324
|
<slot name="footer"></slot>
|
|
2317
2325
|
</div>` : null}
|