@crowdstrike/glide-core 0.7.0 → 0.9.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.
Files changed (203) hide show
  1. package/README.md +44 -5
  2. package/dist/accordion.test.basics.js +1 -0
  3. package/dist/accordion.test.events.js +1 -0
  4. package/dist/button-group.button.d.ts +14 -15
  5. package/dist/button-group.button.js +1 -1
  6. package/dist/button-group.button.styles.js +75 -52
  7. package/dist/button-group.button.test.basics.d.ts +1 -1
  8. package/dist/button-group.button.test.basics.js +84 -147
  9. package/dist/button-group.button.test.events.js +9 -67
  10. package/dist/button-group.button.test.focus.js +13 -0
  11. package/dist/button-group.button.test.interactions.d.ts +1 -0
  12. package/dist/button-group.button.test.interactions.js +42 -0
  13. package/dist/button-group.d.ts +7 -10
  14. package/dist/button-group.js +1 -1
  15. package/dist/button-group.stories.d.ts +1 -5
  16. package/dist/button-group.styles.js +18 -6
  17. package/dist/button-group.test.basics.js +114 -234
  18. package/dist/button-group.test.events.js +211 -263
  19. package/dist/button-group.test.focus.d.ts +1 -0
  20. package/dist/button-group.test.focus.js +39 -0
  21. package/dist/button-group.test.interactions.d.ts +1 -0
  22. package/dist/button-group.test.interactions.js +91 -0
  23. package/dist/button.test.basics.js +2 -1
  24. package/dist/button.test.events.js +1 -0
  25. package/dist/button.test.form.js +1 -0
  26. package/dist/checkbox-group.js +1 -1
  27. package/dist/checkbox-group.styles.js +1 -1
  28. package/dist/checkbox-group.test.basics.js +2 -1
  29. package/dist/checkbox-group.test.events.js +5 -4
  30. package/dist/checkbox-group.test.focus.js +5 -3
  31. package/dist/checkbox-group.test.form.js +1 -0
  32. package/dist/checkbox-group.test.validity.js +1 -0
  33. package/dist/checkbox.d.ts +7 -1
  34. package/dist/checkbox.js +1 -1
  35. package/dist/checkbox.styles.js +11 -3
  36. package/dist/checkbox.test.basics.js +1 -0
  37. package/dist/checkbox.test.events.js +5 -4
  38. package/dist/checkbox.test.focus.js +2 -2
  39. package/dist/checkbox.test.form.js +1 -0
  40. package/dist/{checkbox.test.states.js → checkbox.test.interactions.js} +25 -1
  41. package/dist/checkbox.test.validity.js +1 -0
  42. package/dist/drawer.js +1 -1
  43. package/dist/drawer.test.basics.js +1 -0
  44. package/dist/drawer.test.closing.js +1 -0
  45. package/dist/drawer.test.events.js +1 -0
  46. package/dist/drawer.test.methods.js +1 -0
  47. package/dist/dropdown.d.ts +6 -4
  48. package/dist/dropdown.js +1 -1
  49. package/dist/dropdown.option.d.ts +7 -2
  50. package/dist/dropdown.option.js +1 -1
  51. package/dist/dropdown.option.styles.js +13 -0
  52. package/dist/dropdown.option.test.basics.js +7 -3
  53. package/dist/dropdown.option.test.basics.multiple.js +1 -0
  54. package/dist/dropdown.option.test.basics.single.js +1 -0
  55. package/dist/dropdown.option.test.events.js +2 -1
  56. package/dist/dropdown.option.test.focus.js +1 -1
  57. package/dist/dropdown.option.test.interactions.multiple.js +2 -54
  58. package/dist/dropdown.option.test.interactions.single.js +52 -9
  59. package/dist/dropdown.styles.js +20 -19
  60. package/dist/dropdown.test.basics.filterable.js +1 -0
  61. package/dist/dropdown.test.basics.js +144 -2
  62. package/dist/dropdown.test.basics.multiple.js +6 -3
  63. package/dist/dropdown.test.basics.single.js +1 -1
  64. package/dist/dropdown.test.events.filterable.js +74 -0
  65. package/dist/dropdown.test.events.js +50 -160
  66. package/dist/dropdown.test.events.multiple.js +268 -10
  67. package/dist/dropdown.test.events.single.js +202 -4
  68. package/dist/dropdown.test.focus.filterable.js +9 -5
  69. package/dist/dropdown.test.focus.js +2 -1
  70. package/dist/dropdown.test.focus.multiple.js +1 -2
  71. package/dist/dropdown.test.focus.single.js +1 -1
  72. package/dist/dropdown.test.form.js +1 -0
  73. package/dist/dropdown.test.form.multiple.js +1 -0
  74. package/dist/dropdown.test.form.single.js +1 -0
  75. package/dist/dropdown.test.interactions.filterable.js +69 -11
  76. package/dist/dropdown.test.interactions.js +95 -5
  77. package/dist/dropdown.test.interactions.multiple.js +203 -6
  78. package/dist/dropdown.test.interactions.single.js +69 -6
  79. package/dist/dropdown.test.validity.js +1 -0
  80. package/dist/form-controls-layout.test.basics.js +2 -1
  81. package/dist/icon-button.test.basics.js +2 -1
  82. package/dist/icons/checked.d.ts +1 -1
  83. package/dist/icons/checked.js +1 -1
  84. package/dist/icons/magnifying-glass.js +1 -1
  85. package/dist/input.d.ts +0 -6
  86. package/dist/input.js +1 -1
  87. package/dist/input.styles.js +7 -2
  88. package/dist/input.test.basics.js +20 -5
  89. package/dist/input.test.events.js +5 -4
  90. package/dist/input.test.focus.js +5 -4
  91. package/dist/input.test.form.js +1 -0
  92. package/dist/input.test.translations.d.ts +1 -0
  93. package/dist/input.test.translations.js +38 -0
  94. package/dist/input.test.validity.js +134 -4
  95. package/dist/label.d.ts +1 -1
  96. package/dist/label.js +1 -1
  97. package/dist/label.styles.js +29 -20
  98. package/dist/label.test.basics.js +27 -24
  99. package/dist/library/expect-argument-error.js +1 -1
  100. package/dist/library/localize.d.ts +5 -1
  101. package/dist/library/ow.test.d.ts +2 -1
  102. package/dist/library/ow.test.js +8 -3
  103. package/dist/menu.button.test.basics.js +1 -0
  104. package/dist/menu.d.ts +3 -5
  105. package/dist/menu.js +1 -1
  106. package/dist/menu.link.test.basics.js +1 -0
  107. package/dist/menu.options.test.basics.js +3 -2
  108. package/dist/menu.styles.js +1 -15
  109. package/dist/menu.test.basics.d.ts +1 -2
  110. package/dist/menu.test.basics.js +23 -6
  111. package/dist/menu.test.events.d.ts +1 -0
  112. package/dist/menu.test.events.js +2 -1
  113. package/dist/menu.test.focus.d.ts +1 -0
  114. package/dist/menu.test.focus.js +14 -6
  115. package/dist/menu.test.interactions.js +213 -56
  116. package/dist/modal.icon-button.test.basics.js +2 -1
  117. package/dist/modal.js +1 -1
  118. package/dist/modal.styles.js +18 -13
  119. package/dist/modal.tertiary-icon.d.ts +0 -1
  120. package/dist/modal.tertiary-icon.js +1 -1
  121. package/dist/modal.tertiary-icon.test.basics.js +2 -1
  122. package/dist/modal.test.accessibility.js +1 -0
  123. package/dist/modal.test.basics.js +2 -1
  124. package/dist/modal.test.close.js +1 -0
  125. package/dist/modal.test.events.js +11 -10
  126. package/dist/modal.test.lock-scroll.js +1 -0
  127. package/dist/modal.test.methods.js +1 -0
  128. package/dist/modal.test.scrollbars.js +1 -0
  129. package/dist/radio-group.js +1 -1
  130. package/dist/radio-group.styles.js +1 -1
  131. package/dist/radio-group.test.basics.js +1 -0
  132. package/dist/radio-group.test.events.js +1 -0
  133. package/dist/radio-group.test.focus.js +4 -3
  134. package/dist/radio-group.test.form.js +1 -0
  135. package/dist/radio-group.test.validity.js +1 -0
  136. package/dist/radio.d.ts +1 -0
  137. package/dist/radio.js +1 -1
  138. package/dist/radio.styles.js +33 -0
  139. package/dist/split-button.test.basics.js +1 -0
  140. package/dist/split-container.test.basics.js +5 -0
  141. package/dist/split-link.test.basics.js +1 -0
  142. package/dist/split-link.test.interactions.js +2 -1
  143. package/dist/styles/variables.css +1 -1
  144. package/dist/tab.d.ts +1 -3
  145. package/dist/tab.group.d.ts +3 -5
  146. package/dist/tab.group.js +1 -1
  147. package/dist/tab.group.styles.js +27 -13
  148. package/dist/tab.group.test.basics.js +8 -57
  149. package/dist/tab.group.test.interactions.d.ts +3 -0
  150. package/dist/tab.group.test.interactions.js +454 -0
  151. package/dist/tab.js +1 -1
  152. package/dist/tab.panel.d.ts +1 -0
  153. package/dist/tab.panel.js +1 -1
  154. package/dist/tab.panel.styles.js +11 -1
  155. package/dist/tab.styles.js +7 -68
  156. package/dist/tab.test.basics.js +0 -20
  157. package/dist/tabs.stories.d.ts +1 -2
  158. package/dist/tag.test.basics.js +3 -2
  159. package/dist/textarea.d.ts +0 -1
  160. package/dist/textarea.js +2 -2
  161. package/dist/textarea.stories.d.ts +3 -4
  162. package/dist/textarea.styles.js +14 -3
  163. package/dist/textarea.test.basics.js +81 -44
  164. package/dist/textarea.test.events.js +57 -41
  165. package/dist/textarea.test.form.js +1 -0
  166. package/dist/textarea.test.translations.d.ts +1 -0
  167. package/dist/textarea.test.translations.js +34 -0
  168. package/dist/textarea.test.validity.js +105 -20
  169. package/dist/toasts.js +1 -1
  170. package/dist/toasts.styles.js +8 -1
  171. package/dist/toasts.test.basics.js +20 -0
  172. package/dist/toggle.js +1 -1
  173. package/dist/toggle.test.basics.js +1 -0
  174. package/dist/toggle.test.events.js +1 -0
  175. package/dist/toggle.test.focus.js +1 -1
  176. package/dist/toggle.test.interactions.d.ts +1 -0
  177. package/dist/{toggle.test.states.js → toggle.test.interactions.js} +1 -0
  178. package/dist/tooltip.d.ts +7 -5
  179. package/dist/tooltip.js +1 -1
  180. package/dist/tooltip.styles.js +90 -25
  181. package/dist/tooltip.test.basics.js +39 -3
  182. package/dist/tooltip.test.interactions.js +137 -34
  183. package/dist/translations/en.js +1 -1
  184. package/dist/translations/fr.js +1 -1
  185. package/dist/translations/ja.js +1 -1
  186. package/dist/tree.d.ts +0 -1
  187. package/dist/tree.item.d.ts +2 -3
  188. package/dist/tree.item.js +1 -1
  189. package/dist/tree.item.menu.d.ts +0 -1
  190. package/dist/tree.item.menu.js +1 -1
  191. package/dist/tree.item.test.basics.js +1 -0
  192. package/dist/tree.js +1 -1
  193. package/dist/tree.test.basics.js +2 -1
  194. package/dist/tree.test.events.js +1 -1
  195. package/package.json +40 -29
  196. package/dist/drawer.test.floating-components.d.ts +0 -1
  197. package/dist/drawer.test.floating-components.js +0 -51
  198. package/dist/library/set-containing-block.d.ts +0 -15
  199. package/dist/library/set-containing-block.js +0 -1
  200. package/dist/modal.test.floating-components.js +0 -62
  201. /package/dist/{checkbox.test.states.d.ts → button-group.button.test.focus.d.ts} +0 -0
  202. /package/dist/{modal.test.floating-components.d.ts → checkbox.test.interactions.d.ts} +0 -0
  203. /package/dist/{toggle.test.states.d.ts → dropdown.test.events.filterable.d.ts} +0 -0
@@ -1,7 +1,10 @@
1
1
  import{css}from"lit";export default[css`
2
2
  .component {
3
3
  align-items: center;
4
+ block-size: var(--private-option-height);
4
5
  border-radius: var(--glide-core-spacing-sm);
6
+ max-inline-size: 21.875rem;
7
+ user-select: none;
5
8
 
6
9
  &.active {
7
10
  background-color: var(--glide-core-surface-hover);
@@ -61,4 +64,14 @@ import{css}from"lit";export default[css`
61
64
  .indeterminate-icon {
62
65
  display: none;
63
66
  }
67
+
68
+ .tooltip {
69
+ overflow: hidden;
70
+ }
71
+
72
+ .label {
73
+ overflow: hidden;
74
+ text-overflow: ellipsis;
75
+ white-space: nowrap;
76
+ }
64
77
  `];
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
1
2
  import { expect, fixture, html } from '@open-wc/testing';
2
3
  import GlideCoreDropdownOption from './dropdown.option.js';
3
4
  GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
@@ -15,18 +16,21 @@ it('has defaults', async () => {
15
16
  expect(component.getAttribute('private-multiple')).to.equal(null);
16
17
  expect(component.privateSize).to.equal('large');
17
18
  expect(component.getAttribute('private-size')).to.equal('large');
19
+ expect(component.selected).to.equal(false);
20
+ expect(component.hasAttribute('selected')).to.be.false;
21
+ expect(component.value).to.equal('');
22
+ expect(component.getAttribute('value')).to.equal('');
18
23
  // None are reflected, so no attribute assertions are necessary.
19
24
  expect(component.privateActive).to.equal(false);
20
25
  expect(component.privateIndeterminate).to.equal(false);
21
- expect(component.selected).to.equal(false);
22
- expect(component.value).to.equal('');
23
26
  });
24
27
  it('can have a label', async () => {
25
28
  const component = await fixture(html `<glide-core-dropdown-option
26
29
  label="Label"
27
30
  value="value"
28
31
  ></glide-core-dropdown-option>`);
29
- expect(component.shadowRoot?.textContent?.trim()).to.equal('Label');
32
+ const label = component.shadowRoot?.querySelector('[data-test="label"]');
33
+ expect(label?.textContent?.trim()).to.equal('Label');
30
34
  });
31
35
  it('can have an icon', async () => {
32
36
  const component = await fixture(html `<glide-core-dropdown-option label="Label" value="value">
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
1
2
  import { expect, fixture, html } from '@open-wc/testing';
2
3
  import GlideCoreDropdownOption from './dropdown.option.js';
3
4
  GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
1
2
  import { expect, fixture, html } from '@open-wc/testing';
2
3
  import GlideCoreDropdownOption from './dropdown.option.js';
3
4
  GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
1
2
  import { expect, fixture, html, oneEvent } from '@open-wc/testing';
2
3
  import GlideCoreDropdownOption from './dropdown.option.js';
3
4
  GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
@@ -7,7 +8,7 @@ it('dispatches a "private-selected-change" event', async () => {
7
8
  value="value"
8
9
  ></glide-core-dropdown-option>`);
9
10
  setTimeout(() => {
10
- component.click();
11
+ component.selected = true;
11
12
  });
12
13
  const event = await oneEvent(component, 'private-selected-change');
13
14
  expect(event instanceof Event).to.be.true;
@@ -1,7 +1,7 @@
1
1
  import { expect, fixture, html } from '@open-wc/testing';
2
2
  import GlideCoreDropdownOption from './dropdown.option.js';
3
3
  GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
4
- it('focuses itself when `focus` is called', async () => {
4
+ it('focuses itself when `focus()` is called', async () => {
5
5
  const component = await fixture(html `<glide-core-dropdown-option
6
6
  label="Label"
7
7
  value="value"
@@ -1,58 +1,7 @@
1
- import { elementUpdated, expect, fixture, html, waitUntil, } from '@open-wc/testing';
2
- import GlideCoreCheckbox from './checkbox.js';
1
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
2
+ import { elementUpdated, expect, fixture, html } from '@open-wc/testing';
3
3
  import GlideCoreDropdownOption from './dropdown.option.js';
4
4
  GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
5
- it('is selected on click', async () => {
6
- const component = await fixture(html `<glide-core-dropdown-option
7
- label="Label"
8
- private-multiple
9
- ></glide-core-dropdown-option>`);
10
- component.click();
11
- await elementUpdated(component);
12
- expect(component.selected).to.be.true;
13
- expect(component.ariaSelected).to.equal('true');
14
- });
15
- it('is deselected on click', async () => {
16
- const component = await fixture(html `<glide-core-dropdown-option
17
- label="Label"
18
- private-multiple
19
- selected
20
- ></glide-core-dropdown-option>`);
21
- component.click();
22
- await elementUpdated(component);
23
- expect(component.selected).to.be.false;
24
- expect(component.ariaSelected).to.equal('false');
25
- });
26
- it('is selected on click when the checkbox itself is clicked', async () => {
27
- const component = await fixture(html `<glide-core-dropdown-option
28
- label="Label"
29
- private-multiple
30
- ></glide-core-dropdown-option>`);
31
- const checkbox = component.shadowRoot?.querySelector('[data-test="checkbox"]');
32
- checkbox?.click();
33
- await elementUpdated(component);
34
- expect(component.selected).to.be.true;
35
- expect(component.ariaSelected).to.equal('true');
36
- expect(checkbox?.checked).to.be.true;
37
- });
38
- it('is deselected on click when the checkbox itself is clicked', async () => {
39
- const component = await fixture(html `<glide-core-dropdown-option
40
- label="Label"
41
- private-multiple
42
- selected
43
- ></glide-core-dropdown-option>`);
44
- // Checkbox has its own lifecycle. Wait until it's ready.
45
- await waitUntil(() => {
46
- return (component.shadowRoot?.querySelector('[data-test="checkbox"]') instanceof
47
- GlideCoreCheckbox);
48
- });
49
- const checkbox = component.shadowRoot?.querySelector('[data-test="checkbox"]');
50
- checkbox?.click();
51
- await elementUpdated(component);
52
- expect(component.selected).to.be.false;
53
- expect(component.ariaSelected).to.equal('false');
54
- expect(checkbox?.checked).to.be.false;
55
- });
56
5
  it('is selected when programmatically selected', async () => {
57
6
  const component = await fixture(html `<glide-core-dropdown-option
58
7
  label="Label"
@@ -62,7 +11,6 @@ it('is selected when programmatically selected', async () => {
62
11
  component.selected = true;
63
12
  await elementUpdated(component);
64
13
  const checkbox = component.shadowRoot?.querySelector('[data-test="checkbox"]');
65
- expect(component.selected).to.be.true;
66
14
  expect(component.ariaSelected).to.equal('true');
67
15
  expect(checkbox?.checked).to.be.true;
68
16
  });
@@ -1,22 +1,65 @@
1
- import { elementUpdated, expect, fixture, html } from '@open-wc/testing';
1
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
2
+ import { aTimeout, elementUpdated, expect, fixture, html, } from '@open-wc/testing';
2
3
  import GlideCoreDropdownOption from './dropdown.option.js';
3
4
  GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
4
- it('is selected on click', async () => {
5
+ it('is selected when programmatically selected', async () => {
5
6
  const component = await fixture(html `<glide-core-dropdown-option
6
7
  label="Label"
8
+ value="value"
7
9
  ></glide-core-dropdown-option>`);
8
- component.click();
10
+ component.selected = true;
9
11
  await elementUpdated(component);
10
- expect(component.selected).to.be.true;
11
12
  expect(component.ariaSelected).to.equal('true');
12
13
  });
13
- it('is selected when programmatically selected', async () => {
14
+ it('has a tooltip when active and with a long label', async () => {
15
+ // The period is arbitrary. 500 of them ensures we exceed the maximum
16
+ // width even if it's increased.
17
+ const component = await fixture(html `<glide-core-dropdown-option
18
+ label=${'.'.repeat(500)}
19
+ value="value"
20
+ ></glide-core-dropdown-option>`);
21
+ component.privateActive = true;
22
+ // Wait for the tooltip.
23
+ await aTimeout(0);
24
+ const tooltip = component.shadowRoot?.querySelector('[data-test="tooltip"]');
25
+ expect(tooltip?.checkVisibility()).to.be.true;
26
+ });
27
+ it('has no tooltip when active and with a short label', async () => {
14
28
  const component = await fixture(html `<glide-core-dropdown-option
15
29
  label="Label"
16
30
  value="value"
17
31
  ></glide-core-dropdown-option>`);
18
- component.selected = true;
19
- await elementUpdated(component);
20
- expect(component.selected).to.be.true;
21
- expect(component.ariaSelected).to.equal('true');
32
+ component.privateActive = true;
33
+ // Wait for the tooltip.
34
+ await aTimeout(0);
35
+ const tooltip = component.shadowRoot?.querySelector('[data-test="tooltip"]');
36
+ expect(tooltip?.checkVisibility()).to.be.false;
37
+ });
38
+ it('has a tooltip when active and with a long label set programmatically', async () => {
39
+ const component = await fixture(html `<glide-core-dropdown-option
40
+ label="Label"
41
+ value="value"
42
+ ></glide-core-dropdown-option>`);
43
+ component.privateActive = true;
44
+ // The period is arbitrary. 500 of them ensures we exceed the maximum
45
+ // width even if it's increased.
46
+ component.label = '.'.repeat(500);
47
+ // Wait for the tooltip.
48
+ await aTimeout(0);
49
+ const tooltip = component.shadowRoot?.querySelector('[data-test="tooltip"]');
50
+ expect(tooltip?.checkVisibility()).to.be.true;
51
+ });
52
+ it('has no tooltip when active and with a short label set programmatically', async () => {
53
+ // The period is arbitrary. 500 of them ensures we exceed the maximum
54
+ // width even if it's increased.
55
+ const component = await fixture(html `<glide-core-dropdown-option
56
+ label=${'.'.repeat(500)}
57
+ value="value"
58
+ ></glide-core-dropdown-option>`);
59
+ component.privateActive = true;
60
+ component.label = 'Label';
61
+ // Wait for the tooltip.
62
+ await aTimeout(0);
63
+ const tooltip = component.shadowRoot?.querySelector('[data-test="tooltip"]');
64
+ expect(tooltip?.checkVisibility()).to.be.false;
22
65
  });
@@ -31,7 +31,6 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
31
31
  font-style: var(--glide-core-body-sm-font-style);
32
32
  font-weight: var(--glide-core-body-sm-font-weight);
33
33
  gap: var(--glide-core-spacing-xs);
34
- justify-content: space-between;
35
34
  min-inline-size: var(--min-inline-size);
36
35
  padding-inline: var(--glide-core-spacing-sm);
37
36
  text-align: start;
@@ -79,29 +78,25 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
79
78
  }
80
79
 
81
80
  .options {
81
+ --border-width: 1px;
82
+ --padding: var(--glide-core-spacing-xxxs);
83
+ --private-option-height: 1.75rem;
84
+
82
85
  background-color: var(--glide-core-surface-modal);
83
- border: 1px solid var(--glide-core-surface-modal);
86
+ border: var(--border-width) solid var(--glide-core-surface-modal);
84
87
  border-radius: var(--glide-core-spacing-xs);
85
88
  box-shadow: var(--glide-core-shadow-lg);
86
89
  box-sizing: border-box;
87
- inset-block-start: 100%;
88
- inset-inline-start: 0;
89
- margin-block: var(--glide-core-spacing-xxs) 0;
90
+ inset: unset;
91
+ max-block-size: calc(
92
+ var(--private-option-height) * 9 + var(--padding) * 2 +
93
+ var(--border-width) * 2
94
+ );
90
95
  min-inline-size: var(--min-inline-size);
91
- padding: var(--glide-core-spacing-xxxs);
96
+ overflow: auto;
97
+ padding: var(--padding);
92
98
  position: absolute;
93
- visibility: hidden;
94
-
95
- /*
96
- ".dropdown-and-options" is relative and many Dropdowns may be stacked in a column.
97
- This ensures the ".options" of Dropdowns earlier in the column aren't obscured by
98
- the ".dropdown-and-options" that come later.
99
- */
100
- z-index: 1;
101
-
102
- &.visible {
103
- visibility: visible;
104
- }
99
+ scroll-behavior: smooth;
105
100
  }
106
101
 
107
102
  .select-all {
@@ -134,9 +129,14 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
134
129
  }
135
130
  }
136
131
 
132
+ .tag-overflow-text-and-button {
133
+ column-gap: var(--glide-core-spacing-md);
134
+ display: flex;
135
+ margin-inline-start: auto;
136
+ }
137
+
137
138
  .tag-overflow-text {
138
139
  color: var(--glide-core-text-link);
139
- margin-inline-end: var(--glide-core-spacing-md);
140
140
  }
141
141
 
142
142
  .button {
@@ -158,6 +158,7 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import
158
158
  block-size: var(--button-and-input-height);
159
159
  border: none;
160
160
  cursor: inherit;
161
+ flex-grow: 1;
161
162
  font-size: inherit;
162
163
  min-inline-size: var(--min-inline-size);
163
164
  padding: 0;
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
1
2
  import './dropdown.option.js';
2
3
  import { expect, fixture, html } from '@open-wc/testing';
3
4
  import GlideCoreDropdown from './dropdown.js';
@@ -1,6 +1,7 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
1
2
  import './dropdown.option.js';
2
3
  import { ArgumentError } from 'ow';
3
- import { expect, fixture, html } from '@open-wc/testing';
4
+ import { aTimeout, assert, expect, fixture, html } from '@open-wc/testing';
4
5
  import { repeat } from 'lit/directives/repeat.js';
5
6
  import GlideCoreDropdown from './dropdown.js';
6
7
  import expectArgumentError from './library/expect-argument-error.js';
@@ -41,6 +42,36 @@ it('has defaults', async () => {
41
42
  // Not reflected, so no attribute assertion is necessary.
42
43
  expect(component.value).to.deep.equal([]);
43
44
  });
45
+ it('can be open', async () => {
46
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" open>
47
+ <glide-core-dropdown-option
48
+ label="Label"
49
+ value="value"
50
+ selected
51
+ ></glide-core-dropdown-option>
52
+ </glide-core-dropdown>`);
53
+ // Wait for it to open.
54
+ await aTimeout(0);
55
+ const options = component.shadowRoot?.querySelector('[data-test="options"]');
56
+ expect(component.open).to.be.true;
57
+ expect(component.hasAttribute('open')).to.be.true;
58
+ expect(options?.checkVisibility()).to.be.true;
59
+ });
60
+ it('cannot be open when disabled', async () => {
61
+ const component = await fixture(html `<glide-core-dropdown
62
+ label="Label"
63
+ placeholder="Placeholder"
64
+ open
65
+ disabled
66
+ >
67
+ <glide-core-dropdown-option
68
+ label="Label"
69
+ value="value"
70
+ ></glide-core-dropdown-option>
71
+ </glide-core-dropdown>`);
72
+ const options = component?.shadowRoot?.querySelector('[data-test="options"]');
73
+ expect(options?.checkVisibility()).to.be.false;
74
+ });
44
75
  it('can have a label', async () => {
45
76
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
46
77
  <glide-core-dropdown-option
@@ -207,6 +238,117 @@ it('activates the last selected option when options are initially selected', asy
207
238
  expect(options[1]?.privateActive).to.be.false;
208
239
  expect(options[2]?.privateActive).to.be.true;
209
240
  });
241
+ it('is scrollable', async () => {
242
+ const component = await fixture(html `<glide-core-dropdown open>
243
+ <glide-core-dropdown-option
244
+ label="One"
245
+ value="one"
246
+ ></glide-core-dropdown-option>
247
+
248
+ <glide-core-dropdown-option
249
+ label="Two"
250
+ value="two"
251
+ ></glide-core-dropdown-option>
252
+
253
+ <glide-core-dropdown-option
254
+ label="Three"
255
+ value="three"
256
+ ></glide-core-dropdown-option>
257
+
258
+ <glide-core-dropdown-option
259
+ label="Four"
260
+ value="four"
261
+ ></glide-core-dropdown-option>
262
+
263
+ <glide-core-dropdown-option
264
+ label="Five"
265
+ value="five"
266
+ ></glide-core-dropdown-option>
267
+
268
+ <glide-core-dropdown-option
269
+ label="Six"
270
+ value="six"
271
+ ></glide-core-dropdown-option>
272
+
273
+ <glide-core-dropdown-option
274
+ label="Seven"
275
+ value="seven"
276
+ ></glide-core-dropdown-option>
277
+
278
+ <glide-core-dropdown-option
279
+ label="Eight"
280
+ value="eight"
281
+ ></glide-core-dropdown-option>
282
+
283
+ <glide-core-dropdown-option
284
+ label="Nine"
285
+ value="nine"
286
+ ></glide-core-dropdown-option>
287
+
288
+ <glide-core-dropdown-option
289
+ label="Ten"
290
+ value="ten"
291
+ ></glide-core-dropdown-option>
292
+ </glide-core-dropdown>`);
293
+ // Wait for it to open.
294
+ await aTimeout(0);
295
+ const options = component.shadowRoot?.querySelector('[data-test="options"]');
296
+ assert(options);
297
+ expect(options.scrollHeight).to.be.greaterThan(options.clientHeight);
298
+ });
299
+ it('is not scrollable', async () => {
300
+ const component = await fixture(html `<glide-core-dropdown open>
301
+ <glide-core-dropdown-option
302
+ label="One"
303
+ value="one"
304
+ ></glide-core-dropdown-option>
305
+
306
+ <glide-core-dropdown-option
307
+ label="Two"
308
+ value="two"
309
+ ></glide-core-dropdown-option>
310
+
311
+ <glide-core-dropdown-option
312
+ label="Three"
313
+ value="three"
314
+ ></glide-core-dropdown-option>
315
+
316
+ <glide-core-dropdown-option
317
+ label="Four"
318
+ value="four"
319
+ ></glide-core-dropdown-option>
320
+
321
+ <glide-core-dropdown-option
322
+ label="Five"
323
+ value="five"
324
+ ></glide-core-dropdown-option>
325
+
326
+ <glide-core-dropdown-option
327
+ label="Six"
328
+ value="six"
329
+ ></glide-core-dropdown-option>
330
+
331
+ <glide-core-dropdown-option
332
+ label="Seven"
333
+ value="seven"
334
+ ></glide-core-dropdown-option>
335
+
336
+ <glide-core-dropdown-option
337
+ label="Eight"
338
+ value="eight"
339
+ ></glide-core-dropdown-option>
340
+
341
+ <glide-core-dropdown-option
342
+ label="Nine"
343
+ value="nine"
344
+ ></glide-core-dropdown-option>
345
+ </glide-core-dropdown>`);
346
+ // Wait for it to open.
347
+ await aTimeout(0);
348
+ const options = component.shadowRoot?.querySelector('[data-test="options"]');
349
+ assert(options);
350
+ expect(options.scrollHeight).to.equal(options.clientHeight);
351
+ });
210
352
  it('throws if the default slot is the incorrect type', async () => {
211
353
  await expectArgumentError(() => {
212
354
  return fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
@@ -229,5 +371,5 @@ it('does not throw if the default slot only contains whitespace', async () => {
229
371
  spy();
230
372
  }
231
373
  }
232
- expect(spy.notCalled).to.be.true;
374
+ expect(spy.callCount).to.equal(0);
233
375
  });
@@ -1,7 +1,7 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
1
2
  import './dropdown.option.js';
2
- import { expect, fixture, html } from '@open-wc/testing';
3
+ import { aTimeout, expect, fixture, html } from '@open-wc/testing';
3
4
  import GlideCoreDropdown from './dropdown.js';
4
- import GlideCoreDropdownOption from './dropdown.option.js';
5
5
  GlideCoreDropdown.shadowRootOptions.mode = 'open';
6
6
  it('is accessible', async () => {
7
7
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder" multiple>
@@ -112,6 +112,7 @@ it('shows Select All', async () => {
112
112
  placeholder="Placeholder"
113
113
  multiple
114
114
  select-all
115
+ open
115
116
  >
116
117
  <glide-core-dropdown-option
117
118
  label="One"
@@ -124,8 +125,10 @@ it('shows Select All', async () => {
124
125
  value="two"
125
126
  ></glide-core-dropdown-option>
126
127
  </glide-core-dropdown>`);
128
+ // Wait for it to open.
129
+ await aTimeout(0);
127
130
  const selectAll = component.shadowRoot?.querySelector('[data-test="select-all"]');
128
- expect(selectAll?.checkVisibility()).to.be.ok;
131
+ expect(selectAll?.checkVisibility()).to.be.true;
129
132
  });
130
133
  it('sets Select All as selected when all options are initially selected', async () => {
131
134
  const component = await fixture(html `<glide-core-dropdown
@@ -1,6 +1,6 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
1
2
  import { expect, fixture, html } from '@open-wc/testing';
2
3
  import GlideCoreDropdown from './dropdown.js';
3
- import GlideCoreDropdownOption from './dropdown.option.js';
4
4
  GlideCoreDropdown.shadowRootOptions.mode = 'open';
5
5
  it('is accessible ', async () => {
6
6
  const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
@@ -0,0 +1,74 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
2
+ import * as sinon from 'sinon';
3
+ import { expect, fixture, html } from '@open-wc/testing';
4
+ import { sendKeys } from '@web/test-runner-commands';
5
+ import GlideCoreDropdown from './dropdown.js';
6
+ import GlideCoreDropdownOption from './dropdown.option.js';
7
+ GlideCoreDropdown.shadowRootOptions.mode = 'open';
8
+ GlideCoreDropdownOption.shadowRootOptions.mode = 'open';
9
+ const defaultSlot = html `
10
+ <glide-core-dropdown-option
11
+ label="One"
12
+ value="one"
13
+ ></glide-core-dropdown-option>
14
+
15
+ <glide-core-dropdown-option
16
+ label="Two"
17
+ value="two"
18
+ ></glide-core-dropdown-option>
19
+
20
+ <glide-core-dropdown-option
21
+ label="Three"
22
+ value="three"
23
+ ></glide-core-dropdown-option>
24
+
25
+ <glide-core-dropdown-option
26
+ label="Four"
27
+ value="four"
28
+ ></glide-core-dropdown-option>
29
+
30
+ <glide-core-dropdown-option
31
+ label="Five"
32
+ value="five"
33
+ ></glide-core-dropdown-option>
34
+
35
+ <glide-core-dropdown-option
36
+ label="Six"
37
+ value="six"
38
+ ></glide-core-dropdown-option>
39
+
40
+ <glide-core-dropdown-option
41
+ label="Seven"
42
+ value="seven"
43
+ ></glide-core-dropdown-option>
44
+
45
+ <glide-core-dropdown-option
46
+ label="Eight"
47
+ value="eight"
48
+ ></glide-core-dropdown-option>
49
+
50
+ <glide-core-dropdown-option
51
+ label="Nine"
52
+ value="nine"
53
+ ></glide-core-dropdown-option>
54
+
55
+ <glide-core-dropdown-option
56
+ label="Ten"
57
+ value="ten"
58
+ ></glide-core-dropdown-option>
59
+
60
+ <glide-core-dropdown-option
61
+ label="Eleven"
62
+ value="eleven"
63
+ ></glide-core-dropdown-option>
64
+ `;
65
+ it('does not dispatch "input" events on input', async () => {
66
+ const component = await fixture(html `<glide-core-dropdown label="Label" placeholder="Placeholder">
67
+ ${defaultSlot}
68
+ </glide-core-dropdown>`);
69
+ const spy = sinon.spy();
70
+ component.addEventListener('input', spy);
71
+ component.focus();
72
+ await sendKeys({ type: ' one ' });
73
+ expect(spy.callCount).to.equal(0);
74
+ });