@crowdstrike/glide-core 0.33.0 → 0.34.1

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/dist/accordion.js CHANGED
@@ -42,13 +42,13 @@ let Accordion = class Accordion extends LitElement {
42
42
  this.#suffixIconsSlotElementRef = createRef();
43
43
  this.#summaryElementRef = createRef();
44
44
  }
45
- /* c8 ignore start */
45
+ /* v8 ignore start */
46
46
  static { this.shadowRootOptions = {
47
47
  ...LitElement.shadowRootOptions,
48
48
  delegatesFocus: true,
49
49
  mode: window.navigator.webdriver ? 'open' : 'closed',
50
50
  }; }
51
- /* c8 ignore end */
51
+ /* v8 ignore stop */
52
52
  static { this.styles = styles; }
53
53
  /**
54
54
  * @default false
@@ -209,13 +209,13 @@ let Accordion = class Accordion extends LitElement {
209
209
  const assignedNodes = this.#prefixIconSlotElementRef.value?.assignedNodes();
210
210
  this.hasPrefixIcon = Boolean(assignedNodes && assignedNodes.length > 0);
211
211
  }
212
- /* v8 ignore end */
212
+ /* v8 ignore stop */
213
213
  /* v8 ignore start */
214
214
  #onSuffixIconsSlotChange() {
215
215
  const assignedNodes = this.#suffixIconsSlotElementRef.value?.assignedNodes();
216
216
  this.hasSuffixIcons = Boolean(assignedNodes && assignedNodes.length > 0);
217
217
  }
218
- /* v8 ignore end */
218
+ /* v8 ignore stop */
219
219
  #onSummaryClick(event) {
220
220
  // Canceling it prevents `details` from immediately showing and hiding
221
221
  // the default slot on open and close, letting us animate it when we're ready.
package/dist/button.js CHANGED
@@ -35,13 +35,13 @@ import required from './library/required.js';
35
35
  */
36
36
  let Button = class Button extends LitElement {
37
37
  static { this.formAssociated = true; }
38
- /* c8 ignore start */
38
+ /* v8 ignore start */
39
39
  static { this.shadowRootOptions = {
40
40
  ...LitElement.shadowRootOptions,
41
41
  delegatesFocus: true,
42
42
  mode: window.navigator.webdriver ? 'open' : 'closed',
43
43
  }; }
44
- /* c8 ignore end */
44
+ /* v8 ignore stop */
45
45
  static { this.styles = styles; }
46
46
  // A getter and setter because Lit Analzyer doesn't recognize "aria-description"
47
47
  // as a valid attribute on the `<button>` and doesn't provide a way to selectively
@@ -162,7 +162,7 @@ let Button = class Button extends LitElement {
162
162
  const assignedNodes = this.#prefixIconSlotElementRef.value?.assignedNodes();
163
163
  this.hasPrefixIcon = Boolean(assignedNodes && assignedNodes.length > 0);
164
164
  }
165
- /* v8 ignore end */
165
+ /* v8 ignore stop */
166
166
  /* v8 ignore start */
167
167
  #onSuffixIconSlotChange() {
168
168
  const assignedNodes = this.#suffixIconSlotElementRef.value?.assignedNodes();
@@ -84,7 +84,11 @@ export default class Checkbox extends LitElement implements FormControl {
84
84
  privateDisableLabelTooltip: boolean;
85
85
  privateSplit?: 'left' | 'middle' | 'right';
86
86
  privateVariant?: 'minimal';
87
- required: boolean;
87
+ /**
88
+ * @default false
89
+ */
90
+ get required(): boolean;
91
+ set required(isRequired: boolean);
88
92
  summary?: string;
89
93
  tooltip?: string;
90
94
  /**
package/dist/checkbox.js CHANGED
@@ -68,12 +68,12 @@ import required from './library/required.js';
68
68
  */
69
69
  let Checkbox = class Checkbox extends LitElement {
70
70
  static { this.formAssociated = true; }
71
- /* c8 ignore start */
71
+ /* v8 ignore start */
72
72
  static { this.shadowRootOptions = {
73
73
  ...LitElement.shadowRootOptions,
74
74
  mode: window.navigator.webdriver ? 'open' : 'closed',
75
75
  }; }
76
- /* c8 ignore end */
76
+ /* v8 ignore stop */
77
77
  static { this.styles = styles; }
78
78
  /**
79
79
  * @default undefined
@@ -99,6 +99,7 @@ let Checkbox = class Checkbox extends LitElement {
99
99
  set checked(isChecked) {
100
100
  const hasChanged = isChecked !== this.#isChecked;
101
101
  this.#isChecked = isChecked;
102
+ this.#setValidity();
102
103
  if (hasChanged) {
103
104
  this.dispatchEvent(new Event('private-checked-change', { bubbles: true }));
104
105
  }
@@ -113,6 +114,16 @@ let Checkbox = class Checkbox extends LitElement {
113
114
  this.#isDisabled = isDisabled;
114
115
  this.dispatchEvent(new Event('private-disabled-change', { bubbles: true }));
115
116
  }
117
+ /**
118
+ * @default false
119
+ */
120
+ get required() {
121
+ return this.#isRequired;
122
+ }
123
+ set required(isRequired) {
124
+ this.#isRequired = isRequired;
125
+ this.#setValidity();
126
+ }
116
127
  /**
117
128
  * @default ''
118
129
  */
@@ -166,32 +177,8 @@ let Checkbox = class Checkbox extends LitElement {
166
177
  this.form?.removeEventListener('formdata', this.#onFormdata);
167
178
  this.#intersectionObserver?.disconnect();
168
179
  }
169
- /* v8 ignore end */
180
+ /* v8 ignore stop */
170
181
  get validity() {
171
- // If we're in a Checkbox Group, `disabled`, `required`, and whether or not
172
- // the form has been submitted don't apply because Checkbox Group handles those
173
- // states for the group as a whole.
174
- if (this.privateVariant === 'minimal') {
175
- return this.#internals.validity;
176
- }
177
- if (this.required && !this.checked) {
178
- // A validation message is required but unused because we disable native validation
179
- // feedback. And an empty string isn't allowed. Thus a single space.
180
- this.#internals.setValidity({ customError: Boolean(this.validityMessage), valueMissing: true }, ' ', this.#inputElementRef.value);
181
- return this.#internals.validity;
182
- }
183
- if (this.required &&
184
- this.#internals.validity.valueMissing &&
185
- this.checked) {
186
- this.#internals.setValidity({});
187
- return this.#internals.validity;
188
- }
189
- if (!this.required &&
190
- this.#internals.validity.valueMissing &&
191
- !this.checked) {
192
- this.#internals.setValidity({});
193
- return this.#internals.validity;
194
- }
195
182
  return this.#internals.validity;
196
183
  }
197
184
  focus(options) {
@@ -238,7 +225,8 @@ let Checkbox = class Checkbox extends LitElement {
238
225
  disabled: this.disabled,
239
226
  })}
240
227
  >
241
- <div class="checked-icon">${checkedIcon}</div>
228
+ <div class="checked-icon" role="none">${checkedIcon}</div>
229
+
242
230
  ${icons.indeterminate}
243
231
  </div>
244
232
  </div>
@@ -288,7 +276,7 @@ let Checkbox = class Checkbox extends LitElement {
288
276
  Screenreaders will come across the tooltip naturally as focus moves toward
289
277
  the Checkbox.
290
278
  -->
291
- <div class="input-and-checkbox" slot="control">
279
+ <div class="input-and-checkbox" slot="control" role="none">
292
280
  <input
293
281
  aria-describedby="summary description"
294
282
  aria-invalid=${this.#isShowValidationFeedback}
@@ -378,6 +366,7 @@ let Checkbox = class Checkbox extends LitElement {
378
366
  }
379
367
  }
380
368
  setValidity(flags, message) {
369
+ this.#hasCustomValidity = true;
381
370
  this.validityMessage = message;
382
371
  this.#internals.setValidity(flags, ' ', this.#inputElementRef.value);
383
372
  }
@@ -402,16 +391,17 @@ let Checkbox = class Checkbox extends LitElement {
402
391
  this.privateShowLabelTooltip = false;
403
392
  // Private because it's only meant to be used by Dropdown Option.
404
393
  this.privateDisableLabelTooltip = false;
405
- this.required = false;
406
394
  // Used by Checkbox Group.
407
395
  this.privateIsReportValidityOrSubmit = false;
408
396
  this.version = packageJson.version;
409
397
  this.isBlurring = false;
410
398
  this.isCheckingValidity = false;
411
399
  this.isLabelOverflow = false;
400
+ this.#hasCustomValidity = false;
412
401
  this.#inputElementRef = createRef();
413
402
  this.#isChecked = false;
414
403
  this.#isDisabled = false;
404
+ this.#isRequired = false;
415
405
  this.#labelElementRef = createRef();
416
406
  this.#value = '';
417
407
  // An arrow function field instead of a method so `this` is closed over and
@@ -456,11 +446,13 @@ let Checkbox = class Checkbox extends LitElement {
456
446
  }
457
447
  });
458
448
  }
449
+ #hasCustomValidity;
459
450
  #inputElementRef;
460
451
  #internals;
461
452
  #intersectionObserver;
462
453
  #isChecked;
463
454
  #isDisabled;
455
+ #isRequired;
464
456
  #label;
465
457
  #labelElementRef;
466
458
  #value;
@@ -468,10 +460,9 @@ let Checkbox = class Checkbox extends LitElement {
468
460
  // set to the component instead of `document`.
469
461
  #onFormdata;
470
462
  get #isShowValidationFeedback() {
471
- // If minimal, `disabled`, `required`, and whether the form has been submitted
472
- // don't apply because the parent component handles those states itself.
463
+ // When minimal, Checkbox Group handles validation feedback for the group.
473
464
  if (this.privateVariant === 'minimal') {
474
- return !this.validity.valid && this.privateIsReportValidityOrSubmit;
465
+ return false;
475
466
  }
476
467
  return (!this.disabled &&
477
468
  !this.validity.valid &&
@@ -524,6 +515,17 @@ let Checkbox = class Checkbox extends LitElement {
524
515
  this.form?.requestSubmit();
525
516
  }
526
517
  }
518
+ #setValidity() {
519
+ if (this.#hasCustomValidity) {
520
+ return;
521
+ }
522
+ // When minimal, Checkbox Group handles validation for the group.
523
+ if (this.required && !this.checked && this.privateVariant !== 'minimal') {
524
+ this.#internals.setValidity({ customError: Boolean(this.validityMessage), valueMissing: true }, ' ', this.#inputElementRef.value);
525
+ return;
526
+ }
527
+ this.#internals.setValidity({});
528
+ }
527
529
  #updateLabelOverflow() {
528
530
  if (this.#labelElementRef.value) {
529
531
  this.isLabelOverflow =
@@ -587,7 +589,7 @@ __decorate([
587
589
  ], Checkbox.prototype, "privateVariant", void 0);
588
590
  __decorate([
589
591
  property({ reflect: true, type: Boolean })
590
- ], Checkbox.prototype, "required", void 0);
592
+ ], Checkbox.prototype, "required", null);
591
593
  __decorate([
592
594
  property({ reflect: true })
593
595
  ], Checkbox.prototype, "summary", void 0);
package/dist/dropdown.js CHANGED
@@ -566,8 +566,10 @@ let Dropdown = class Dropdown extends LitElement {
566
566
  data-id=${option.id}
567
567
  label=${ifDefined(option.label)}
568
568
  removable
569
+ style="--max-inline-size: none"
569
570
  ?disabled=${this.disabled || this.readonly}
570
571
  ?private-editable=${option.editable}
572
+ ?private-readonly=${this.readonly}
571
573
  @edit=${this.#onTagEdit}
572
574
  @remove=${this.#onTagRemove.bind(this, option)}
573
575
  >
@@ -598,7 +600,11 @@ let Dropdown = class Dropdown extends LitElement {
598
600
  this.selectedAndEnabledOptions.length > this.tagOverflowLimit, () => {
599
601
  return html `<div
600
602
  aria-hidden="true"
601
- class="tag-overflow-text"
603
+ class=${classMap({
604
+ 'tag-overflow-text': true,
605
+ disabled: this.disabled,
606
+ readonly: this.readonly,
607
+ })}
602
608
  id="tag-overflow-text"
603
609
  >
604
610
  +
@@ -650,6 +656,7 @@ let Dropdown = class Dropdown extends LitElement {
650
656
  .isCommunicateItemCountToScreenreaders
651
657
  ? 'item-count'
652
658
  : ''}"
659
+ aria-required=${this.required}
653
660
  autocapitalize="off"
654
661
  autocomplete="off"
655
662
  class=${classMap({
@@ -755,32 +762,31 @@ let Dropdown = class Dropdown extends LitElement {
755
762
  ${pencilIcon}
756
763
  </glide-core-icon-button>`;
757
764
  })}
758
-
759
- <button
760
- aria-controls="options"
761
- aria-describedby="description"
762
- aria-expanded=${this.open && !this.disabled}
763
- aria-haspopup="listbox"
764
- aria-hidden=${this.filterable || this.isFilterable}
765
- aria-labelledby="selected-option-labels label loading-feedback"
766
- class="primary-button"
767
- data-test="primary-button"
768
- id="primary-button"
769
- tabindex=${this.filterable || this.isFilterable || this.disabled
770
- ? '-1'
771
- : '0'}
772
- type="button"
773
- ?disabled=${this.disabled}
774
- @focusin=${this.#onPrimaryButtonFocusin}
775
- @focusout=${this.#onPrimaryButtonFocusout}
776
- ${ref(this.#primaryButtonElementRef)}
777
- >
778
- ${when(this.isFiltering, () => {
779
- return html `<div data-test="magnifying-glass-icon">
780
- ${magnifyingGlassIcon}
781
- </div>`;
782
- }, () => chevronIcon)}
783
- </button>
765
+ ${when(!(this.disabled || this.readonly), () => {
766
+ return html `<button
767
+ aria-controls="options"
768
+ aria-describedby="description"
769
+ aria-expanded=${this.open}
770
+ aria-haspopup="listbox"
771
+ aria-hidden=${this.filterable || this.isFilterable}
772
+ aria-labelledby="selected-option-labels label loading-feedback"
773
+ aria-required=${this.required}
774
+ class="primary-button"
775
+ data-test="primary-button"
776
+ id="primary-button"
777
+ tabindex=${this.filterable || this.isFilterable ? '-1' : '0'}
778
+ type="button"
779
+ @focusin=${this.#onPrimaryButtonFocusin}
780
+ @focusout=${this.#onPrimaryButtonFocusout}
781
+ ${ref(this.#primaryButtonElementRef)}
782
+ >
783
+ ${when(this.isFiltering, () => {
784
+ return html `<div data-test="magnifying-glass-icon">
785
+ ${magnifyingGlassIcon}
786
+ </div>`;
787
+ }, () => chevronIcon)}
788
+ </button>`;
789
+ })}
784
790
  </div>
785
791
  </div>
786
792
 
@@ -93,9 +93,10 @@ export default [
93
93
  }
94
94
 
95
95
  &.readonly {
96
- background-color: transparent;
96
+ background-color: var(
97
+ --glide-core-color-interactive-surface-container--disabled
98
+ );
97
99
  border-color: transparent;
98
- padding-inline-start: 0;
99
100
  }
100
101
 
101
102
  &.quiet {
@@ -123,16 +124,13 @@ export default [
123
124
  ) {
124
125
  &:not(.error) {
125
126
  border-color: var(--glide-core-color-interactive-stroke-focus);
126
- box-shadow:
127
- 0 0 0 1px var(--glide-core-color-interactive-stroke-focus),
128
- 1px 1px 4px -1px var(--glide-core-color-interactive-stroke-focus);
127
+ box-shadow: inset 0 0 0 1px
128
+ var(--glide-core-color-interactive-stroke-focus);
129
129
  }
130
130
 
131
131
  &.error {
132
- box-shadow:
133
- 0 0 0 1px var(--glide-core-color-advisory-stroke-error-primary),
134
- 1px 1px 4px -1px
135
- var(--glide-core-color-advisory-stroke-error-primary);
132
+ box-shadow: inset 0 0 0 1px
133
+ var(--glide-core-color-advisory-stroke-error-primary);
136
134
  }
137
135
  }
138
136
  }
@@ -214,17 +212,11 @@ export default [
214
212
  gap: var(--glide-core-spacing-base-xs);
215
213
 
216
214
  /*
217
- Tags will shrink down to zero and never overflow if they don't have a minimum
218
- width. If they don't overflow, they'll remain visible and additionally won't be
219
- included in the overflow count text. Thus a minimum width.
220
-
221
- "3.5rem" is the size of a tag with only a single character. Ideally, its
222
- minimum would be wider so a few characters are always visible. But a single-
223
- character tag is possible and even likely. Setting a higher minimum width
224
- would mean single or double-character tags would have whitespace between them.
225
- It's equally unfortunate that Dropdown has to know anything about Tag's width.
215
+ Tags will overflow their columns if they don't have a minimum width. "5.5rem"
216
+ is roughly the size of a Tag with a few characters in it. That Dropdown has
217
+ to know anything about Tag's internal width is unfortunate.
226
218
  */
227
- grid-auto-columns: minmax(3.5rem, auto);
219
+ grid-auto-columns: minmax(5.5rem, auto);
228
220
  grid-auto-flow: column;
229
221
  list-style-type: none;
230
222
  margin-block: 0;
@@ -249,6 +241,14 @@ export default [
249
241
  align-content: center;
250
242
  color: var(--glide-core-color-interactive-text-link);
251
243
  white-space: nowrap;
244
+
245
+ &.disabled {
246
+ color: var(--glide-core-color-interactive-text-link--disabled);
247
+ }
248
+
249
+ &.readonly {
250
+ color: var(--glide-core-color-interactive-text-default);
251
+ }
252
252
  }
253
253
 
254
254
  .single-select-icon-slot {
@@ -329,7 +329,7 @@ export default [
329
329
  font-family: var(--glide-core-typography-family-primary);
330
330
  font-size: inherit;
331
331
  inline-size: 100%;
332
- min-inline-size: 3.75rem;
332
+ min-inline-size: 3.125rem;
333
333
  padding-block-end: 0;
334
334
  padding-inline: 0;
335
335
 
@@ -41,12 +41,13 @@ let IconButton = class IconButton extends LitElement {
41
41
  this.#buttonElementRef = createRef();
42
42
  this.#defaultSlotElementRef = createRef();
43
43
  }
44
- /* c8 ignore start */
44
+ /* v8 ignore start */
45
45
  static { this.shadowRootOptions = {
46
46
  ...LitElement.shadowRootOptions,
47
47
  delegatesFocus: true,
48
48
  mode: window.navigator.webdriver ? 'open' : 'closed',
49
49
  }; }
50
+ /* v8 ignore stop */
50
51
  static { this.styles = styles; }
51
52
  // A getter and setter because Lit Analzyer doesn't recognize "aria-description"
52
53
  // as a valid attribute on the `<button>` and doesn't provide a way to selectively
@@ -11,6 +11,9 @@ declare global {
11
11
  * @attr {string} [version]
12
12
  *
13
13
  * @slot {Element | string} - The content of the alert
14
+ *
15
+ * @readonly
16
+ * @prop {string} ariaLabel
14
17
  */
15
18
  export default class InlineAlert extends LitElement {
16
19
  #private;
@@ -18,6 +21,7 @@ export default class InlineAlert extends LitElement {
18
21
  static styles: import("lit").CSSResult[];
19
22
  variant: 'informational' | 'medium' | 'high' | 'critical';
20
23
  readonly version: string;
24
+ get ariaLabel(): string;
21
25
  firstUpdated(): void;
22
26
  render(): import("lit").TemplateResult<1>;
23
27
  }
@@ -7,7 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  import { html, LitElement } from 'lit';
8
8
  import { classMap } from 'lit/directives/class-map.js';
9
9
  import { createRef, ref } from 'lit/directives/ref.js';
10
- import { customElement, property } from 'lit/decorators.js';
10
+ import { customElement, property, state } from 'lit/decorators.js';
11
11
  import { styleMap } from 'lit/directives/style-map.js';
12
12
  import packageJson from '../package.json' with { type: 'json' };
13
13
  import styles from './inline-alert.styles.js';
@@ -16,6 +16,7 @@ import severityMediumIcon from './icons/severity-medium.js';
16
16
  import severityCriticalIcon from './icons/severity-critical.js';
17
17
  import assertSlot from './library/assert-slot.js';
18
18
  import final from './library/final.js';
19
+ import { LocalizeController } from './library/localize.js';
19
20
  /**
20
21
  * @attr {'informational'|'medium'|'high'|'critical'} [variant='informational']
21
22
  *
@@ -23,6 +24,9 @@ import final from './library/final.js';
23
24
  * @attr {string} [version]
24
25
  *
25
26
  * @slot {Element | string} - The content of the alert
27
+ *
28
+ * @readonly
29
+ * @prop {string} ariaLabel
26
30
  */
27
31
  let InlineAlert = class InlineAlert extends LitElement {
28
32
  constructor() {
@@ -31,6 +35,7 @@ let InlineAlert = class InlineAlert extends LitElement {
31
35
  this.version = packageJson.version;
32
36
  this.#animationDuration = 100;
33
37
  this.#componentElementRef = createRef();
38
+ this.#localize = new LocalizeController(this);
34
39
  }
35
40
  /* c8 ignore start */
36
41
  static { this.shadowRootOptions = {
@@ -39,6 +44,15 @@ let InlineAlert = class InlineAlert extends LitElement {
39
44
  }; }
40
45
  /* c8 ignore end */
41
46
  static { this.styles = styles; }
47
+ get ariaLabel() {
48
+ return this.#localize.term(this.variant === 'informational'
49
+ ? 'severityInformational'
50
+ : this.variant === 'medium'
51
+ ? 'severityMedium'
52
+ : this.variant === 'high'
53
+ ? 'severityHigh'
54
+ : 'severityCritical');
55
+ }
42
56
  firstUpdated() {
43
57
  this.#componentElementRef.value?.addEventListener('animationend', () => {
44
58
  this.#componentElementRef.value?.classList.remove('added');
@@ -47,14 +61,14 @@ let InlineAlert = class InlineAlert extends LitElement {
47
61
  render() {
48
62
  return html `
49
63
  <div
64
+ aria-label=${this.ariaLabel}
50
65
  class=${classMap({
51
66
  component: true,
52
67
  added: true,
53
68
  [this.variant]: true,
54
69
  })}
55
- role="alert"
56
- aria-labelledby="label"
57
70
  data-test="component"
71
+ role="alert"
58
72
  style="--private-animation-duration: ${this.#animationDuration}ms"
59
73
  ${ref(this.#componentElementRef)}
60
74
  >
@@ -68,7 +82,7 @@ let InlineAlert = class InlineAlert extends LitElement {
68
82
  ${icons[this.variant]}
69
83
  </div>
70
84
 
71
- <div id="label" class="content">
85
+ <div class="content">
72
86
  <slot ${assertSlot()}>
73
87
  <!--
74
88
  The content of the alert
@@ -82,6 +96,7 @@ let InlineAlert = class InlineAlert extends LitElement {
82
96
  }
83
97
  #animationDuration;
84
98
  #componentElementRef;
99
+ #localize;
85
100
  };
86
101
  __decorate([
87
102
  property({ reflect: true, useDefault: true })
@@ -89,6 +104,9 @@ __decorate([
89
104
  __decorate([
90
105
  property({ reflect: true })
91
106
  ], InlineAlert.prototype, "version", void 0);
107
+ __decorate([
108
+ state()
109
+ ], InlineAlert.prototype, "ariaLabel", null);
92
110
  InlineAlert = __decorate([
93
111
  customElement('glide-core-inline-alert'),
94
112
  final
@@ -68,16 +68,13 @@ export default [
68
68
  &.focused:not(.readonly) {
69
69
  &:not(.error) {
70
70
  border-color: var(--glide-core-color-interactive-stroke-focus);
71
- box-shadow:
72
- 0 0 0 1px var(--glide-core-color-interactive-stroke-focus),
73
- 1px 1px 4px -1px var(--glide-core-color-interactive-stroke-focus);
71
+ box-shadow: inset 0 0 0 1px
72
+ var(--glide-core-color-interactive-stroke-focus);
74
73
  }
75
74
 
76
75
  &.error {
77
- box-shadow:
78
- 0 0 0 1px var(--glide-core-color-advisory-stroke-error-primary),
79
- 1px 1px 4px -1px
80
- var(--glide-core-color-advisory-stroke-error-primary);
76
+ box-shadow: inset 0 0 0 1px
77
+ var(--glide-core-color-advisory-stroke-error-primary);
81
78
  }
82
79
  }
83
80
 
@@ -86,9 +83,10 @@ export default [
86
83
  with ":read-only": https://bugs.chromium.org/p/chromium/issues/detail?id=1519649
87
84
  */
88
85
  &.readonly {
89
- background-color: transparent;
86
+ background-color: var(
87
+ --glide-core-color-interactive-surface-container--disabled
88
+ );
90
89
  border: 1px solid transparent;
91
- padding-inline-start: 0;
92
90
  }
93
91
 
94
92
  &.disabled {
@@ -18,6 +18,7 @@ export interface Translation extends DefaultTranslation {
18
18
  severityInformational: string;
19
19
  severityCritical: string;
20
20
  severityMedium: string;
21
+ severityHigh: string;
21
22
  success: string;
22
23
  error: string;
23
24
  informational: string;
package/dist/link.js CHANGED
@@ -37,6 +37,7 @@ let Link = class Link extends LitElement {
37
37
  delegatesFocus: true,
38
38
  mode: window.navigator.webdriver ? 'open' : 'closed',
39
39
  }; }
40
+ /* c8 ignore end */
40
41
  static { this.styles = styles; }
41
42
  click() {
42
43
  this.#componentElementRef.value?.click();
package/dist/menu.js CHANGED
@@ -665,7 +665,8 @@ let Menu = class Menu extends LitElement {
665
665
  // On both slots because VoiceOver can focus Options, causing them to emit
666
666
  // "keydown" events.
667
667
  #onTargetAndDefaultSlotKeyDown(event) {
668
- const isOwnTarget = event.target === this.#targetElement;
668
+ const isOwnTarget = event.target instanceof Element &&
669
+ this.#targetElement?.contains(event.target);
669
670
  const isChildOfOptions = event.target instanceof Element &&
670
671
  event.target.closest('glide-core-options');
671
672
  const isArbitraryContent = !isOwnTarget && !isChildOfOptions;
package/dist/select.js CHANGED
@@ -54,12 +54,12 @@ import OptionsGroup from './options.group.js';
54
54
  */
55
55
  let Select = class Select extends LitElement {
56
56
  static { this.formAssociated = true; }
57
- /* c8 ignore start */
57
+ /* v8 ignore start */
58
58
  static { this.shadowRootOptions = {
59
59
  ...LitElement.shadowRootOptions,
60
60
  mode: window.navigator.webdriver ? 'open' : 'closed',
61
61
  }; }
62
- /* c8 ignore end */
62
+ /* v8 ignore end */
63
63
  static { this.styles = styles; }
64
64
  /**
65
65
  * @default 4
package/dist/slider.js CHANGED
@@ -73,6 +73,7 @@ let Slider = class Slider extends LitElement {
73
73
  mode: window.navigator.webdriver ? 'open' : 'closed',
74
74
  delegatesFocus: true,
75
75
  }; }
76
+ /* c8 ignore end */
76
77
  static { this.styles = styles; }
77
78
  // Intentionally not reflected to match native.
78
79
  /**
@@ -118,9 +118,7 @@ export default [
118
118
  }
119
119
 
120
120
  .handle {
121
- background-color: var(
122
- --glide-core-private-color-slider-and-scrollbar-surface-handle
123
- );
121
+ background-color: var(--glide-core-private-color-slider-surface-handle);
124
122
  block-size: 1.5rem;
125
123
  border: 2px solid var(--glide-core-color-interactive-stroke-active);
126
124
  border-radius: var(--glide-core-rounding-base-radius-round);
package/dist/spinner.js CHANGED
@@ -25,12 +25,13 @@ let Spinner = class Spinner extends LitElement {
25
25
  this.size = 'medium';
26
26
  this.version = packageJson.version;
27
27
  }
28
- /* c8 ignore start */
28
+ /* v8 ignore start */
29
29
  static { this.shadowRootOptions = {
30
30
  ...LitElement.shadowRootOptions,
31
31
  delegatesFocus: true,
32
32
  mode: window.navigator.webdriver ? 'open' : 'closed',
33
33
  }; }
34
+ /* v8 ignore stop */
34
35
  static { this.styles = styles; }
35
36
  render() {
36
37
  return html `<div
@@ -41,6 +41,7 @@ let SplitButtonPrimaryButton = class SplitButtonPrimaryButton extends LitElement
41
41
  delegatesFocus: true,
42
42
  mode: window.navigator.webdriver ? 'open' : 'closed',
43
43
  }; }
44
+ /* c8 ignore end */
44
45
  static { this.styles = styles; }
45
46
  render() {
46
47
  return html `<button
@@ -36,6 +36,7 @@ let SplitButtonPrimaryLink = class SplitButtonPrimaryLink extends LitElement {
36
36
  delegatesFocus: true,
37
37
  mode: window.navigator.webdriver ? 'open' : 'closed',
38
38
  }; }
39
+ /* c8 ignore end */
39
40
  static { this.styles = styles; }
40
41
  render() {
41
42
  if (this.disabled) {
@@ -47,6 +47,7 @@ let SplitButtonSecondaryButton = class SplitButtonSecondaryButton extends LitEle
47
47
  delegatesFocus: true,
48
48
  mode: window.navigator.webdriver ? 'open' : 'closed',
49
49
  }; }
50
+ /* c8 ignore end */
50
51
  static { this.styles = styles; }
51
52
  click() {
52
53
  this.#buttonElementRef.value?.click();
@@ -123,7 +123,7 @@
123
123
  --glide-core-color-severity-stroke-high: #ffbf66;
124
124
  --glide-core-color-severity-stroke-medium: #ffcc00;
125
125
  --glide-core-color-severity-stroke-low: #c9c9c9;
126
- --glide-core-color-severity-text-citical: #2c0907;
126
+ --glide-core-color-severity-text-critical: #2c0907;
127
127
  --glide-core-color-severity-text-high: #331e00;
128
128
  --glide-core-color-severity-text-medium: #332900;
129
129
  --glide-core-color-severity-text-low: #212121;
@@ -153,7 +153,7 @@
153
153
  --glide-core-private-color-dialog-and-modal-surface-overlay: #0000008c;
154
154
  --glide-core-private-color-skeleton-loader-surface-linear-gradient-sides: #0000000d;
155
155
  --glide-core-private-color-skeleton-loader-surface-linear-gradient-middle: #0000001a;
156
- --glide-core-private-color-slider-and-scrollbar-surface-handle: #f0f0f0;
156
+ --glide-core-private-color-slider-surface-handle: #f0f0f0;
157
157
  --glide-core-private-color-tabs-stroke-underline: #e3e3e3;
158
158
  --glide-core-private-color-template-surface-container-detail: #ffffffe5;
159
159
  --glide-core-private-color-tooltip-surface-container: #212121;
@@ -284,7 +284,7 @@
284
284
  --glide-core-color-severity-stroke-high: #e7a649;
285
285
  --glide-core-color-severity-stroke-medium: #f0cf4f;
286
286
  --glide-core-color-severity-stroke-low: #727272;
287
- --glide-core-color-severity-text-citical: #e67873;
287
+ --glide-core-color-severity-text-critical: #e67873;
288
288
  --glide-core-color-severity-text-high: #ffb64f;
289
289
  --glide-core-color-severity-text-medium: #f0cf4f;
290
290
  --glide-core-color-severity-text-low: #f9f9f9;
@@ -314,7 +314,7 @@
314
314
  --glide-core-private-color-dialog-and-modal-surface-overlay: #141414d9;
315
315
  --glide-core-private-color-skeleton-loader-surface-linear-gradient-sides: #ffffff0d;
316
316
  --glide-core-private-color-skeleton-loader-surface-linear-gradient-middle: #ffffff1a;
317
- --glide-core-private-color-slider-and-scrollbar-surface-handle: #2c2c2c;
317
+ --glide-core-private-color-slider-surface-handle: #2c2c2c;
318
318
  --glide-core-private-color-tabs-stroke-underline: #ffffff26;
319
319
  --glide-core-private-color-template-surface-container-detail: #222222;
320
320
  --glide-core-private-color-tooltip-surface-container: #dcdcdc;
@@ -337,12 +337,18 @@
337
337
  --glide-core-duration-fast-02: 100ms;
338
338
  --glide-core-duration-moderate-01: 150ms;
339
339
  --glide-core-duration-moderate-02: 250ms;
340
+ --glide-core-duration-moderate-03: 325ms;
340
341
  --glide-core-duration-slow-01: 400ms;
341
342
  --glide-core-duration-slow-02: 900ms;
342
343
  }
343
344
 
344
345
  /* src/styles/variables/miscellaneous.css */
345
346
  :root {
347
+ --glide-core-typography-family-primary: "Nunito", system-ui;
348
+ --glide-core-typography-family-monospace:
349
+ "Oxygen Mono",
350
+ ui-monospace,
351
+ monospace;
346
352
  --glide-core-effect-hovered: 0px 0px 2px 0px var(--glide-core-color-effect-color-elevation-hovered);
347
353
  --glide-core-effect-lifted: 0px 2px 8px 0px var(--glide-core-color-effect-color-elevation-lifted);
348
354
  --glide-core-effect-raised: 0px 3px 1px 0px var(--glide-core-color-effect-color-elevation-raised-1), 0px 3px 8px 0 var(--glide-core-color-effect-color-elevation-raised-2);
@@ -394,11 +400,6 @@
394
400
  --glide-core-typography-size-body-default: 0.875rem;
395
401
  --glide-core-typography-size-body-small: 0.75rem;
396
402
  --glide-core-typography-size-component-chartlabel-md: 0.625rem;
397
- --glide-core-typography-family-primary: "Nunito", system-ui;
398
- --glide-core-typography-family-monospace:
399
- "Oxygen Mono",
400
- ui-monospace,
401
- monospace;
402
403
  --glide-core-typography-weight-light: 300;
403
404
  --glide-core-typography-weight-regular: 400;
404
405
  --glide-core-typography-weight-semibold: 600;
package/dist/tab.group.js CHANGED
@@ -103,6 +103,7 @@ let TabGroup = class TabGroup extends LitElement {
103
103
  animated: this.hasUpdated,
104
104
  })}
105
105
  data-test="selected-tab-indicator"
106
+ @transitionstart=${this.#onSelectedTabIndicatorTransition}
106
107
  ${ref(this.#selectedTabIndicatorElementRef)}
107
108
  ></div>
108
109
  </div>
@@ -260,6 +261,9 @@ let TabGroup = class TabGroup extends LitElement {
260
261
  });
261
262
  }
262
263
  }
264
+ #onSelectedTabIndicatorTransition() {
265
+ this.#setOverflowButtonsState();
266
+ }
263
267
  #onTabListFocusout() {
264
268
  // Set the last selected tab as tabbable so that when pressing Shift + Tab on the
265
269
  // Tab Panel focus goes back to the last selected tab.
package/dist/tag.d.ts CHANGED
@@ -14,6 +14,8 @@ declare global {
14
14
  *
15
15
  * @slot {Element} [icon]
16
16
  *
17
+ * @cssprop [--max-inline-size=max-content]
18
+ *
17
19
  * @fires {Event} edit
18
20
  * @fires {Event} remove
19
21
  */
@@ -24,6 +26,7 @@ export default class Tag extends LitElement {
24
26
  label?: string;
25
27
  disabled: boolean;
26
28
  privateEditable: boolean;
29
+ privateReadonly: boolean;
27
30
  removable: boolean;
28
31
  readonly version: string;
29
32
  click(): void;
package/dist/tag.js CHANGED
@@ -26,6 +26,8 @@ import required from './library/required.js';
26
26
  *
27
27
  * @slot {Element} [icon]
28
28
  *
29
+ * @cssprop [--max-inline-size=max-content]
30
+ *
29
31
  * @fires {Event} edit
30
32
  * @fires {Event} remove
31
33
  */
@@ -35,6 +37,8 @@ let Tag = class Tag extends LitElement {
35
37
  this.disabled = false;
36
38
  // Private because it's only meant to be used by Dropdown.
37
39
  this.privateEditable = false;
40
+ // Private because it's only meant to be used by Dropdown.
41
+ this.privateReadonly = false;
38
42
  this.removable = false;
39
43
  this.version = packageJson.version;
40
44
  this.#animationDuration = 100;
@@ -53,12 +57,13 @@ let Tag = class Tag extends LitElement {
53
57
  this.#localize = new LocalizeController(this);
54
58
  this.#removalButtonElementRef = createRef();
55
59
  }
56
- /* c8 ignore start */
60
+ /* v8 ignore start */
57
61
  static { this.shadowRootOptions = {
58
62
  ...LitElement.shadowRootOptions,
59
63
  delegatesFocus: true,
60
64
  mode: window.navigator.webdriver ? 'open' : 'closed',
61
65
  }; }
66
+ /* v8 ignore stop */
62
67
  static { this.styles = styles; }
63
68
  click() {
64
69
  this.#removalButtonElementRef.value?.click();
@@ -78,6 +83,7 @@ let Tag = class Tag extends LitElement {
78
83
  component: true,
79
84
  added: true,
80
85
  disabled: this.disabled,
86
+ readonly: this.privateReadonly,
81
87
  })}
82
88
  data-test="component"
83
89
  data-animation-duration=${this.#animationDuration}
@@ -194,6 +200,9 @@ __decorate([
194
200
  __decorate([
195
201
  property({ attribute: 'private-editable', reflect: true, type: Boolean })
196
202
  ], Tag.prototype, "privateEditable", void 0);
203
+ __decorate([
204
+ property({ attribute: 'private-readonly', reflect: true, type: Boolean })
205
+ ], Tag.prototype, "privateReadonly", void 0);
197
206
  __decorate([
198
207
  property({ reflect: true, type: Boolean })
199
208
  ], Tag.prototype, "removable", void 0);
@@ -26,6 +26,10 @@ export default [
26
26
  }
27
27
  }
28
28
 
29
+ :host {
30
+ --max-inline-size: max-content;
31
+ }
32
+
29
33
  .component {
30
34
  align-items: center;
31
35
  background-color: var(
@@ -43,7 +47,7 @@ export default [
43
47
  font-weight: var(--glide-core-typography-weight-regular);
44
48
  justify-content: center;
45
49
  line-height: 1;
46
- max-inline-size: max-content;
50
+ max-inline-size: var(--max-inline-size);
47
51
  opacity: 1;
48
52
  padding-inline: var(--glide-core-spacing-base-sm);
49
53
 
@@ -54,11 +58,19 @@ export default [
54
58
  }
55
59
 
56
60
  &.disabled {
57
- background: var(--glide-core-color-static-surface-container-secondary);
61
+ background-color: var(
62
+ --glide-core-color-static-surface-container-secondary
63
+ );
58
64
  border-color: var(--glide-core-color-interactive-stroke-primary);
59
65
  color: var(--glide-core-color-interactive-icon-default--disabled);
60
66
  }
61
67
 
68
+ &.readonly {
69
+ background-color: var(--glide-core-color-static-surface-container);
70
+ border-color: var(--glide-core-color-interactive-stroke-primary);
71
+ color: var(--glide-core-color-interactive-text-default);
72
+ }
73
+
62
74
  &.removed {
63
75
  @media (prefers-reduced-motion: no-preference) {
64
76
  animation-duration: var(--private-animation-duration);
@@ -71,6 +83,7 @@ export default [
71
83
 
72
84
  .label {
73
85
  overflow: hidden;
86
+ text-align: center;
74
87
  text-overflow: ellipsis;
75
88
  white-space: nowrap;
76
89
  }
@@ -88,16 +88,13 @@ export default [
88
88
  &:focus-visible:not([readonly]) {
89
89
  &:not(.error) {
90
90
  border-color: var(--glide-core-color-interactive-stroke-focus);
91
- box-shadow:
92
- 0 0 0 1px var(--glide-core-color-interactive-stroke-focus),
93
- 1px 1px 4px -1px var(--glide-core-color-interactive-stroke-focus);
91
+ box-shadow: inset 0 0 0 1px
92
+ var(--glide-core-color-interactive-stroke-focus);
94
93
  }
95
94
 
96
95
  &.error {
97
- box-shadow:
98
- 0 0 0 1px var(--glide-core-color-advisory-stroke-error-primary),
99
- 1px 1px 4px -1px
100
- var(--glide-core-color-advisory-stroke-error-primary);
96
+ box-shadow: inset 0 0 0 1px
97
+ var(--glide-core-color-advisory-stroke-error-primary);
101
98
  }
102
99
  }
103
100
 
@@ -114,10 +111,11 @@ export default [
114
111
  }
115
112
 
116
113
  &[readonly] {
117
- background-color: transparent;
114
+ background-color: var(
115
+ --glide-core-color-interactive-surface-container--disabled
116
+ );
118
117
  border-color: transparent;
119
118
  outline: none;
120
- padding-inline-start: 0;
121
119
  resize: none;
122
120
  transition: none;
123
121
  }
@@ -80,7 +80,7 @@ let Toasts = class Toasts extends LitElement {
80
80
  <div class="toasts">
81
81
  ${repeat(this.toasts, (toast) => toast.privateId, (toast) => {
82
82
  return html `<div
83
- aria-labelledby="prefix label description"
83
+ aria-describedby="description"
84
84
  class=${classMap({
85
85
  toast: true,
86
86
  error: toast.variant === 'error',
@@ -96,7 +96,7 @@ let Toasts = class Toasts extends LitElement {
96
96
  @mouseout=${this.#onToastMouseOut.bind(this, toast)}
97
97
  @transitionend=${this.#onToastTransitionEnd.bind(this, toast)}
98
98
  >
99
- <span class="prefix" id="prefix">
99
+ <span class="prefix">
100
100
  ${this.#localize.term(toast.variant)}
101
101
  </span>
102
102
 
@@ -105,9 +105,7 @@ let Toasts = class Toasts extends LitElement {
105
105
  ['error', () => icons.error],
106
106
  ], () => icons.warningInformational)}
107
107
 
108
- <div class="label" data-test="label" id="label">
109
- ${toast.label}
110
- </div>
108
+ <div class="label" data-test="label">${toast.label}</div>
111
109
 
112
110
  <glide-core-icon-button
113
111
  class="dismiss-button"
package/dist/tooltip.js CHANGED
@@ -330,8 +330,8 @@ let Tooltip = class Tooltip extends LitElement {
330
330
  #onTargetSlotChange() {
331
331
  const container = this.querySelector('glide-core-private-tooltip-container');
332
332
  const target = this.#targetSlotElementRef.value?.assignedElements().at(0);
333
- if (container && target && !this.disabled && !this.screenreaderHidden) {
334
- target.setAttribute('aria-describedby', container.id);
333
+ if (container && !this.disabled && !this.screenreaderHidden) {
334
+ target?.setAttribute('aria-describedby', container.id);
335
335
  }
336
336
  }
337
337
  #onTargetSlotFocusIn() {
@@ -16,6 +16,7 @@ const translation = {
16
16
  severityInformational: 'Severity: Informational',
17
17
  severityCritical: 'Severity: Critical',
18
18
  severityMedium: 'Severity: Medium',
19
+ severityHigh: 'Severity: High',
19
20
  success: 'Success:',
20
21
  error: 'Error:',
21
22
  informational: 'Informational:',
@@ -1,5 +1,5 @@
1
1
  import type { Translation } from '../library/localize.js';
2
- export declare const PENDING_STRINGS: readonly ["severityInformational", "severityCritical", "severityMedium", "success", "error", "informational", "loading", "noAvailableOptions", "noMatchingOptions", "maximum", "setMaximum", "minimum", "setMinimum", "add"];
2
+ export declare const PENDING_STRINGS: readonly ["severityInformational", "severityCritical", "severityMedium", "severityHigh", "success", "error", "informational", "loading", "noAvailableOptions", "noMatchingOptions", "maximum", "setMaximum", "minimum", "setMinimum", "add"];
3
3
  type PendingTranslation = (typeof PENDING_STRINGS)[number];
4
4
  declare const translation: Omit<Translation, PendingTranslation>;
5
5
  export default translation;
@@ -2,6 +2,7 @@ export const PENDING_STRINGS = [
2
2
  'severityInformational',
3
3
  'severityCritical',
4
4
  'severityMedium',
5
+ 'severityHigh',
5
6
  'success',
6
7
  'error',
7
8
  'informational',
@@ -1,5 +1,5 @@
1
1
  import type { Translation } from '../library/localize.js';
2
- export declare const PENDING_STRINGS: readonly ["severityInformational", "severityCritical", "severityMedium", "success", "error", "informational", "loading", "noAvailableOptions", "noMatchingOptions", "maximum", "setMaximum", "minimum", "setMinimum", "add"];
2
+ export declare const PENDING_STRINGS: readonly ["severityInformational", "severityCritical", "severityMedium", "severityHigh", "success", "error", "informational", "loading", "noAvailableOptions", "noMatchingOptions", "maximum", "setMaximum", "minimum", "setMinimum", "add"];
3
3
  type PendingTranslation = (typeof PENDING_STRINGS)[number];
4
4
  declare const translation: Omit<Translation, PendingTranslation>;
5
5
  export default translation;
@@ -2,6 +2,7 @@ export const PENDING_STRINGS = [
2
2
  'severityInformational',
3
3
  'severityCritical',
4
4
  'severityMedium',
5
+ 'severityHigh',
5
6
  'success',
6
7
  'error',
7
8
  'informational',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crowdstrike/glide-core",
3
- "version": "0.33.0",
3
+ "version": "0.34.1",
4
4
  "description": "A Web Component design system",
5
5
  "author": "CrowdStrike UX Team",
6
6
  "license": "Apache-2.0",
@@ -91,8 +91,8 @@
91
91
  "@types/mocha": "^10.0.10",
92
92
  "@types/serialize-javascript": "^5.0.4",
93
93
  "@types/sinon": "^17.0.3",
94
- "@typescript-eslint/types": "^8.33.0",
95
- "@typescript-eslint/utils": "^8.33.0",
94
+ "@typescript-eslint/types": "^8.42.0",
95
+ "@typescript-eslint/utils": "^8.42.0",
96
96
  "@web/dev-server-esbuild": "^1.0.4",
97
97
  "@web/dev-server-rollup": "^0.6.4",
98
98
  "@web/test-runner": "^0.20.2",
@@ -114,7 +114,7 @@
114
114
  "globals": "^15.13.0",
115
115
  "globby": "^14.0.2",
116
116
  "http-server": "^14.1.1",
117
- "husky": "^8.0.3",
117
+ "husky": "^9.1.7",
118
118
  "is-ci": "^4.1.0",
119
119
  "istanbul-lib-coverage": "^3.2.2",
120
120
  "istanbul-lib-report": "^3.0.1",
@@ -125,7 +125,7 @@
125
125
  "matcher": "^5.0.0",
126
126
  "minify-literals": "^1.0.10",
127
127
  "node-html-parser": "^7.0.1",
128
- "npm-run-all2": "^7.0.2",
128
+ "npm-run-all2": "^8.0.4",
129
129
  "per-env": "^1.0.2",
130
130
  "playwright": "^1.54.2",
131
131
  "postcss": "^8.5.6",
@@ -144,10 +144,10 @@
144
144
  "stylelint-use-logical": "^2.1.2",
145
145
  "stylelint-use-nesting": "^6.0.0",
146
146
  "ts-lit-plugin": "^2.0.2",
147
- "ts-morph": "^25.0.1",
147
+ "ts-morph": "^26.0.0",
148
148
  "tsx": "^4.19.2",
149
149
  "typescript": "^5.8.3",
150
- "typescript-eslint": "^8.33.0",
150
+ "typescript-eslint": "^8.42.0",
151
151
  "v8-to-istanbul": "^9.3.0",
152
152
  "vite": "^6.3.2",
153
153
  "yocto-spinner": "^0.2.0"