@momentum-design/components 0.53.3 → 0.53.5

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.
@@ -1,6 +1,7 @@
1
1
  import type { PropertyValues } from 'lit';
2
2
  import { CSSResult } from 'lit';
3
3
  import Buttonsimple from '../buttonsimple/buttonsimple.component';
4
+ import type { IconNames } from '../icon/icon.types';
4
5
  import type { ButtonColor, ButtonVariant, IconButtonSize, PillButtonSize } from './button.types';
5
6
  /**
6
7
  * `mdc-button` is a component that can be configured in various ways to suit different use cases.
@@ -39,12 +40,12 @@ declare class Button extends Buttonsimple {
39
40
  * The name of the icon to display as a prefix.
40
41
  * The icon is displayed on the left side of the button.
41
42
  */
42
- prefixIcon?: string;
43
+ prefixIcon?: IconNames;
43
44
  /**
44
45
  * The name of the icon to display as a postfix.
45
46
  * The icon is displayed on the right side of the button.
46
47
  */
47
- postfixIcon?: string;
48
+ postfixIcon?: IconNames;
48
49
  /**
49
50
  * There are 3 variants of button: primary, secondary, tertiary. They are styled differently.
50
51
  * - **Primary**: Solid background color.
@@ -191,22 +191,10 @@ class Button extends Buttonsimple {
191
191
  }
192
192
  render() {
193
193
  return html `
194
- ${this.prefixIcon
195
- ? html ` <mdc-icon
196
- name="${this.prefixIcon}"
197
- part="prefix-icon"
198
- length-unit="rem"
199
- >
200
- </mdc-icon>`
201
- : ''}
194
+ ${this.prefixIcon ? html ` <mdc-icon name="${this.prefixIcon}" part="prefix-icon"></mdc-icon>` : ''}
202
195
  <slot @slotchange=${this.inferButtonType}></slot>
203
196
  ${this.postfixIcon
204
- ? html ` <mdc-icon
205
- name="${this.postfixIcon}"
206
- part="postfix-icon"
207
- length-unit="rem"
208
- >
209
- </mdc-icon>`
197
+ ? html ` <mdc-icon name="${this.postfixIcon}" part="postfix-icon"></mdc-icon>`
210
198
  : ''}
211
199
  `;
212
200
  }
@@ -1,8 +1,9 @@
1
+ import type { IconNames } from '../icon/icon.types';
1
2
  /**
2
3
  * Returns the name of the icon without the style suffix.
3
4
  *
4
5
  * @param iconName - The name of the icon.
5
6
  * @returns The name of the icon without the suffix.
6
7
  */
7
- declare const getIconNameWithoutStyle: (iconName: string) => string;
8
+ declare const getIconNameWithoutStyle: (iconName: IconNames) => string;
8
9
  export { getIconNameWithoutStyle };
@@ -20,9 +20,11 @@ declare class Buttonsimple extends Buttonsimple_base {
20
20
  * The button's active state indicates whether it is currently toggled on (active) or off (inactive).
21
21
  * When the active state is true, the button is considered to be in an active state, meaning it is toggled on.
22
22
  * Conversely, when the active state is false, the button is in an inactive state, indicating it is toggled off.
23
- * @default false
23
+ *
24
+ * This attribute is used to set the provided `ariaStateKey` to true or false.
25
+ * @default undefined
24
26
  */
25
- active: boolean;
27
+ active?: boolean;
26
28
  /**
27
29
  * Indicates whether the button is soft disabled.
28
30
  * When set to `true`, the button appears visually disabled but still allows
@@ -31,9 +33,9 @@ declare class Buttonsimple extends Buttonsimple_base {
31
33
  * **Important:** When using soft disabled, consumers must ensure that
32
34
  * the button behaves like a disabled button, allowing only focus and
33
35
  * preventing any interactions (clicks or keyboard actions) from triggering unintended actions.
34
- * @default false
36
+ * @default undefined
35
37
  */
36
- softDisabled: boolean;
38
+ softDisabled?: boolean;
37
39
  /**
38
40
  * Simplebutton size is a super set of all the sizes supported by children components.
39
41
  * @default 32
@@ -47,6 +49,19 @@ declare class Buttonsimple extends Buttonsimple_base {
47
49
  * @default button
48
50
  */
49
51
  role: string;
52
+ /**
53
+ * This property defines the ARIA state key, which will be toggled when the
54
+ * Button is set to `active`.
55
+ * The default value is 'aria-pressed', which is commonly used for toggle buttons.
56
+ *
57
+ * Consumers can override this property to use a different ARIA state key if needed.
58
+ * In case multiple aria attributes should be toggled, they can be passed in as
59
+ * a comma separated string.
60
+ * For example: `aria-pressed,aria-expanded`
61
+ *
62
+ * @default 'aria-pressed'
63
+ */
64
+ ariaStateKey: string;
50
65
  /**
51
66
  * This property defines the type attribute for the button element.
52
67
  * The type attribute specifies the behavior of the button when it is clicked.
@@ -70,11 +85,11 @@ declare class Buttonsimple extends Buttonsimple_base {
70
85
  update(changedProperties: PropertyValues): void;
71
86
  protected executeAction(): void;
72
87
  /**
73
- * Sets the aria-pressed attribute based on the active state of the button.
88
+ * Sets the ariaStateKey attributes based on the active state of the button.
74
89
  * @param element - The button element
75
90
  * @param active - The active state of the element
76
91
  */
77
- protected setActive(element: HTMLElement, active: boolean): void;
92
+ protected setActive(element: HTMLElement, active?: boolean): void;
78
93
  /**
79
94
  * Sets the soft-disabled attribute for the button.
80
95
  * When soft-disabled, the button looks to be disabled but remains focusable and clickable.
@@ -33,24 +33,6 @@ class Buttonsimple extends TabIndexMixin(DisabledMixin(Component)) {
33
33
  }
34
34
  constructor() {
35
35
  super();
36
- /**
37
- * The button's active state indicates whether it is currently toggled on (active) or off (inactive).
38
- * When the active state is true, the button is considered to be in an active state, meaning it is toggled on.
39
- * Conversely, when the active state is false, the button is in an inactive state, indicating it is toggled off.
40
- * @default false
41
- */
42
- this.active = false;
43
- /**
44
- * Indicates whether the button is soft disabled.
45
- * When set to `true`, the button appears visually disabled but still allows
46
- * focus, click, and keyboard actions to be passed through.
47
- *
48
- * **Important:** When using soft disabled, consumers must ensure that
49
- * the button behaves like a disabled button, allowing only focus and
50
- * preventing any interactions (clicks or keyboard actions) from triggering unintended actions.
51
- * @default false
52
- */
53
- this.softDisabled = false;
54
36
  /**
55
37
  * Simplebutton size is a super set of all the sizes supported by children components.
56
38
  * @default 32
@@ -64,6 +46,19 @@ class Buttonsimple extends TabIndexMixin(DisabledMixin(Component)) {
64
46
  * @default button
65
47
  */
66
48
  this.role = DEFAULTS.ROLE;
49
+ /**
50
+ * This property defines the ARIA state key, which will be toggled when the
51
+ * Button is set to `active`.
52
+ * The default value is 'aria-pressed', which is commonly used for toggle buttons.
53
+ *
54
+ * Consumers can override this property to use a different ARIA state key if needed.
55
+ * In case multiple aria attributes should be toggled, they can be passed in as
56
+ * a comma separated string.
57
+ * For example: `aria-pressed,aria-expanded`
58
+ *
59
+ * @default 'aria-pressed'
60
+ */
61
+ this.ariaStateKey = DEFAULTS.ARIA_STATE_KEY;
67
62
  /**
68
63
  * This property defines the type attribute for the button element.
69
64
  * The type attribute specifies the behavior of the button when it is clicked.
@@ -105,16 +100,27 @@ class Buttonsimple extends TabIndexMixin(DisabledMixin(Component)) {
105
100
  }
106
101
  }
107
102
  /**
108
- * Sets the aria-pressed attribute based on the active state of the button.
103
+ * Sets the ariaStateKey attributes based on the active state of the button.
109
104
  * @param element - The button element
110
105
  * @param active - The active state of the element
111
106
  */
112
107
  setActive(element, active) {
113
- if (active) {
114
- element.setAttribute('aria-pressed', 'true');
115
- }
116
- else {
117
- element.removeAttribute('aria-pressed');
108
+ if (this.ariaStateKey) {
109
+ const ariaStateKeys = this.ariaStateKey.split(',');
110
+ ariaStateKeys
111
+ .filter((key) => key.trim().startsWith('aria-'))
112
+ .forEach((key) => {
113
+ if (active === true) {
114
+ element.setAttribute(key.trim(), 'true');
115
+ }
116
+ else if (active === false) {
117
+ element.setAttribute(key.trim(), 'false');
118
+ }
119
+ else {
120
+ // If the active state is not a boolean, remove the attribute
121
+ element.removeAttribute(key.trim());
122
+ }
123
+ });
118
124
  }
119
125
  }
120
126
  /**
@@ -207,9 +213,7 @@ class Buttonsimple extends TabIndexMixin(DisabledMixin(Component)) {
207
213
  }
208
214
  }
209
215
  render() {
210
- return html `
211
- <slot></slot>
212
- `;
216
+ return html ` <slot></slot> `;
213
217
  }
214
218
  }
215
219
  /** @internal */
@@ -217,11 +221,11 @@ Buttonsimple.formAssociated = true;
217
221
  Buttonsimple.styles = [...Component.styles, ...styles];
218
222
  __decorate([
219
223
  property({ type: Boolean, reflect: true }),
220
- __metadata("design:type", Object)
224
+ __metadata("design:type", Boolean)
221
225
  ], Buttonsimple.prototype, "active", void 0);
222
226
  __decorate([
223
227
  property({ type: Boolean, attribute: 'soft-disabled' }),
224
- __metadata("design:type", Object)
228
+ __metadata("design:type", Boolean)
225
229
  ], Buttonsimple.prototype, "softDisabled", void 0);
226
230
  __decorate([
227
231
  property({ type: Number, reflect: true }),
@@ -231,6 +235,10 @@ __decorate([
231
235
  property({ type: String, reflect: true }),
232
236
  __metadata("design:type", Object)
233
237
  ], Buttonsimple.prototype, "role", void 0);
238
+ __decorate([
239
+ property({ type: String, reflect: true }),
240
+ __metadata("design:type", Object)
241
+ ], Buttonsimple.prototype, "ariaStateKey", void 0);
234
242
  __decorate([
235
243
  property({ reflect: true }),
236
244
  __metadata("design:type", String)
@@ -21,5 +21,6 @@ declare const DEFAULTS: {
21
21
  SIZE: 32;
22
22
  TYPE: "button";
23
23
  ROLE: string;
24
+ ARIA_STATE_KEY: string;
24
25
  };
25
26
  export { TAG_NAME, DEFAULTS, BUTTON_TYPE, BUTTON_SIZES, };
@@ -22,5 +22,6 @@ const DEFAULTS = {
22
22
  SIZE: BUTTON_SIZES[32],
23
23
  TYPE: BUTTON_TYPE.BUTTON,
24
24
  ROLE: 'button',
25
+ ARIA_STATE_KEY: 'aria-pressed',
25
26
  };
26
27
  export { TAG_NAME, DEFAULTS, BUTTON_TYPE, BUTTON_SIZES, };
@@ -4,6 +4,7 @@ const styles = [hostFitContentStyles, css `
4
4
  :host {
5
5
  border: 0.0625rem solid transparent;
6
6
  cursor: pointer;
7
+ user-select: none;
7
8
 
8
9
  background-color: var(--mds-color-theme-text-primary-normal);
9
10
  color: var(--mds-color-theme-inverted-text-secondary-normal);
@@ -98,6 +98,7 @@ class Option extends FormInternalsMixin(ListItem) {
98
98
  tooltip.textContent = (_b = this.label) !== null && _b !== void 0 ? _b : '';
99
99
  tooltip.setAttribute('triggerid', this.id);
100
100
  tooltip.setAttribute('visible', '');
101
+ tooltip.setAttribute('show-arrow', '');
101
102
  // Add tooltip programmatically after the nearest select component or the parent element.
102
103
  const parent = this.closest(SELECT_TAG_NAME) || this.parentElement;
103
104
  parent === null || parent === void 0 ? void 0 : parent.after(tooltip);
@@ -493,7 +493,10 @@ class Popover extends FocusTrapMixin(Component) {
493
493
  this.triggerElement.removeAttribute('aria-expanded');
494
494
  }
495
495
  if (this.interactive) {
496
- this.triggerElement.removeAttribute('aria-haspopup');
496
+ const triggerElementRole = this.triggerElement.getAttribute('aria-haspopup');
497
+ if (triggerElementRole === 'dialog' || triggerElementRole === 'alertdialog') {
498
+ this.triggerElement.removeAttribute('aria-haspopup');
499
+ }
497
500
  }
498
501
  if (this.focusBackToTrigger) {
499
502
  (_c = this.triggerElement) === null || _c === void 0 ? void 0 : _c.focus();
@@ -89,7 +89,9 @@ export class PopoverUtils {
89
89
  */
90
90
  setupAccessibility() {
91
91
  var _a, _b, _c;
92
- this.popover.toggleAttribute('aria-modal', this.popover.interactive);
92
+ if (this.popover.role === 'dialog' || this.popover.role === 'alertdialog') {
93
+ this.popover.toggleAttribute('aria-modal', this.popover.interactive);
94
+ }
93
95
  if (this.popover.interactive) {
94
96
  if (!this.popover.ariaLabel) {
95
97
  this.popover.ariaLabel = ((_a = this.popover.triggerElement) === null || _a === void 0 ? void 0 : _a.ariaLabel)
@@ -90,9 +90,11 @@ class Select extends FormInternalsMixin(DataAriaLabelMixin(FormfieldWrapper)) {
90
90
  }).flat()) || [];
91
91
  }
92
92
  handlePopoverOpen() {
93
+ this.displayPopover = true;
93
94
  this.baseIconName = ARROW_ICON.ARROW_UP;
94
95
  }
95
96
  handlePopoverClose() {
97
+ this.displayPopover = false;
96
98
  this.baseIconName = ARROW_ICON.ARROW_DOWN;
97
99
  }
98
100
  /**
@@ -220,10 +222,12 @@ class Select extends FormInternalsMixin(DataAriaLabelMixin(FormfieldWrapper)) {
220
222
  case KEYS.SPACE:
221
223
  this.updateTabIndexForAllOptions(event.target);
222
224
  this.closePopover();
225
+ event.preventDefault();
223
226
  break;
224
227
  case KEYS.ENTER:
225
228
  this.updateTabIndexForAllOptions(event.target);
226
229
  this.closePopover();
230
+ event.preventDefault();
227
231
  // if the popover is closed, then we submit the form.
228
232
  (_a = this.form) === null || _a === void 0 ? void 0 : _a.requestSubmit();
229
233
  break;
@@ -232,9 +236,11 @@ class Select extends FormInternalsMixin(DataAriaLabelMixin(FormfieldWrapper)) {
232
236
  break;
233
237
  case KEYS.HOME:
234
238
  this.setFocusAndTabIndex(0);
239
+ event.preventDefault();
235
240
  break;
236
241
  case KEYS.END:
237
242
  this.setFocusAndTabIndex(this.getAllValidOptions().length - 1);
243
+ event.preventDefault();
238
244
  break;
239
245
  case KEYS.ARROW_DOWN:
240
246
  case KEYS.ARROW_UP:
@@ -269,10 +275,12 @@ class Select extends FormInternalsMixin(DataAriaLabelMixin(FormfieldWrapper)) {
269
275
  case KEYS.HOME:
270
276
  this.openPopover();
271
277
  this.setFocusAndTabIndex(0);
278
+ event.preventDefault();
272
279
  break;
273
280
  case KEYS.END:
274
281
  this.openPopover();
275
282
  this.setFocusAndTabIndex(this.getAllValidOptions().length - 1);
283
+ event.preventDefault();
276
284
  break;
277
285
  default:
278
286
  break;
@@ -379,7 +387,6 @@ class Select extends FormInternalsMixin(DataAriaLabelMixin(FormfieldWrapper)) {
379
387
  * @returns A TemplateResult representing the native select element.
380
388
  */
381
389
  getNativeSelect() {
382
- var _a;
383
390
  return html `
384
391
  <select
385
392
  part="native-select"
@@ -391,11 +398,6 @@ class Select extends FormInternalsMixin(DataAriaLabelMixin(FormfieldWrapper)) {
391
398
  ?autofocus="${this.autofocus}"
392
399
  ?disabled="${this.disabled}"
393
400
  ?required="${!!this.requiredLabel}"
394
- aria-activedescendant="${this.activeDescendant}"
395
- aria-expanded="${this.displayPopover}"
396
- aria-haspopup="listbox"
397
- aria-label="${(_a = this.dataAriaLabel) !== null && _a !== void 0 ? _a : ''}"
398
- aria-labelledby="${this.label ? FORMFIELD_DEFAULTS.HEADING_ID : ''}"
399
401
  @mousedown="${(event) => event.preventDefault()}"
400
402
  >
401
403
  ${this.getOptionsContentFromSlot()}
@@ -447,7 +449,6 @@ class Select extends FormInternalsMixin(DataAriaLabelMixin(FormfieldWrapper)) {
447
449
  hide-on-outside-click
448
450
  focus-back-to-trigger
449
451
  focus-trap
450
- prevent-scroll
451
452
  role="listbox"
452
453
  placement="${POPOVER_PLACEMENT.BOTTOM_START}"
453
454
  @shown="${this.handlePopoverOpen}"
@@ -466,7 +467,7 @@ class Select extends FormInternalsMixin(DataAriaLabelMixin(FormfieldWrapper)) {
466
467
  }
467
468
  }
468
469
  render() {
469
- var _a;
470
+ var _a, _b;
470
471
  return html `
471
472
  ${this.renderLabel()}
472
473
  <div part="container">
@@ -475,13 +476,19 @@ class Select extends FormInternalsMixin(DataAriaLabelMixin(FormfieldWrapper)) {
475
476
  part="base-container"
476
477
  tabindex="${this.disabled ? '-1' : '0'}"
477
478
  class="${this.disabled ? '' : 'mdc-focus-ring'}"
479
+ role="combobox"
480
+ aria-activedescendant="${this.activeDescendant}"
481
+ aria-haspopup="listbox"
482
+ aria-label="${(_a = this.dataAriaLabel) !== null && _a !== void 0 ? _a : ''}"
483
+ aria-labelledby="${this.label ? FORMFIELD_DEFAULTS.HEADING_ID : ''}"
484
+ aria-expanded="${this.displayPopover ? 'true' : 'false'}"
478
485
  >
479
486
  <mdc-text
480
487
  part="base-text ${this.selectedValueText ? 'selected' : ''}"
481
488
  type="${TYPE.BODY_MIDSIZE_REGULAR}"
482
489
  tagname="${VALID_TEXT_TAGS.SPAN}"
483
490
  >
484
- ${(_a = this.selectedValueText) !== null && _a !== void 0 ? _a : this.placeholder}
491
+ ${(_b = this.selectedValueText) !== null && _b !== void 0 ? _b : this.placeholder}
485
492
  </mdc-text>
486
493
  <div part="icon-container">
487
494
  <mdc-icon size="1" length-unit="rem" name="${this.baseIconName}"></mdc-icon>
@@ -29,7 +29,7 @@ const styles = css `
29
29
  position: absolute;
30
30
  width: 100%;
31
31
  height: 1px;
32
- z-index: 1;
32
+ z-index: -1;
33
33
  }
34
34
  :host::part(container) {
35
35
  width: 100%;
@@ -100,6 +100,18 @@ declare const Tab_base: import("../../utils/mixins/index.types").Constructor<imp
100
100
  * @cssproperty --mdc-tab-pill-inactive-color-disabled - Text and icon color for inactive pill tab in disabled state.
101
101
  */
102
102
  declare class Tab extends Tab_base {
103
+ /**
104
+ * The tab's active state indicates whether it is currently toggled on (active) or off (inactive).
105
+ * When the active state is true, the tab is considered to be in an active state, meaning it is toggled on.
106
+ * Conversely, when the active state is false, the tab is in an inactive state, indicating it is toggled off.
107
+ *
108
+ * This attribute also controls the "aria-selected" attribute of the tab.
109
+ * When the tab is active, "aria-selected" is set to true, indicating that the tab is selected.
110
+ * When the tab is inactive, "aria-selected" is set to false, indicating that the tab is not selected.
111
+ *
112
+ * @default false
113
+ */
114
+ active?: boolean;
103
115
  /**
104
116
  * Text to be displayed in the tab.
105
117
  * If no `text` is provided, no text will be rendered,
@@ -115,6 +115,18 @@ import { IconNameMixin } from '../../utils/mixins/IconNameMixin';
115
115
  class Tab extends IconNameMixin(Buttonsimple) {
116
116
  constructor() {
117
117
  super(...arguments);
118
+ /**
119
+ * The tab's active state indicates whether it is currently toggled on (active) or off (inactive).
120
+ * When the active state is true, the tab is considered to be in an active state, meaning it is toggled on.
121
+ * Conversely, when the active state is false, the tab is in an inactive state, indicating it is toggled off.
122
+ *
123
+ * This attribute also controls the "aria-selected" attribute of the tab.
124
+ * When the tab is active, "aria-selected" is set to true, indicating that the tab is selected.
125
+ * When the tab is inactive, "aria-selected" is set to false, indicating that the tab is not selected.
126
+ *
127
+ * @default false
128
+ */
129
+ this.active = DEFAULTS.ACTIVE;
118
130
  /**
119
131
  * Tab can have three variants:
120
132
  * - `glass`
@@ -144,6 +156,7 @@ class Tab extends IconNameMixin(Buttonsimple) {
144
156
  this.softDisabled = undefined;
145
157
  this.size = undefined;
146
158
  this.type = undefined;
159
+ this.ariaStateKey = 'aria-selected';
147
160
  if (!this.tabId && this.onerror) {
148
161
  this.onerror('tab id is required');
149
162
  }
@@ -186,7 +199,7 @@ class Tab extends IconNameMixin(Buttonsimple) {
186
199
  * @param active - The active state of the tab.
187
200
  */
188
201
  setActive(element, active) {
189
- element.setAttribute('aria-selected', active ? 'true' : 'false');
202
+ super.setActive(element, active);
190
203
  this.modifyIconName(active);
191
204
  }
192
205
  executeAction() {
@@ -222,6 +235,10 @@ class Tab extends IconNameMixin(Buttonsimple) {
222
235
  }
223
236
  }
224
237
  Tab.styles = [...Buttonsimple.styles, ...styles];
238
+ __decorate([
239
+ property({ type: Boolean, reflect: true }),
240
+ __metadata("design:type", Boolean)
241
+ ], Tab.prototype, "active", void 0);
225
242
  __decorate([
226
243
  property({ type: String, reflect: true }),
227
244
  __metadata("design:type", String)
@@ -6,5 +6,6 @@ declare const TAB_VARIANTS: {
6
6
  };
7
7
  declare const DEFAULTS: {
8
8
  readonly VARIANT: "pill";
9
+ readonly ACTIVE: false;
9
10
  };
10
11
  export { DEFAULTS, TAG_NAME, TAB_VARIANTS };
@@ -7,5 +7,6 @@ const TAB_VARIANTS = {
7
7
  };
8
8
  const DEFAULTS = {
9
9
  VARIANT: TAB_VARIANTS.PILL,
10
+ ACTIVE: false,
10
11
  };
11
12
  export { DEFAULTS, TAG_NAME, TAB_VARIANTS };
@@ -94,7 +94,7 @@ const styles = [hostFitContentStyles, css `
94
94
  flex-direction: column;
95
95
  }
96
96
 
97
- :host::part(text)::after{
97
+ :host mdc-text::after {
98
98
  content: attr(data-text);
99
99
  height: 0;
100
100
  visibility: hidden;