@crowdstrike/glide-core 0.9.0 → 0.9.2

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 (148) hide show
  1. package/dist/accordion.d.ts +7 -3
  2. package/dist/accordion.styles.js +2 -4
  3. package/dist/button-group.button.d.ts +1 -4
  4. package/dist/button-group.button.styles.js +4 -8
  5. package/dist/button-group.d.ts +3 -0
  6. package/dist/button-group.styles.js +2 -2
  7. package/dist/button.d.ts +4 -0
  8. package/dist/button.js +1 -1
  9. package/dist/button.styles.js +2 -4
  10. package/dist/button.test.events.js +86 -10
  11. package/dist/checkbox-group.d.ts +6 -2
  12. package/dist/checkbox-group.stories.d.ts +1 -1
  13. package/dist/checkbox.d.ts +5 -4
  14. package/dist/checkbox.js +1 -1
  15. package/dist/checkbox.stories.d.ts +1 -1
  16. package/dist/checkbox.styles.js +43 -6
  17. package/dist/checkbox.test.basics.js +15 -6
  18. package/dist/checkbox.test.events.js +12 -4
  19. package/dist/checkbox.test.focus.js +1 -1
  20. package/dist/checkbox.test.form.js +17 -0
  21. package/dist/checkbox.test.interactions.js +52 -7
  22. package/dist/drawer.d.ts +5 -5
  23. package/dist/drawer.js +1 -1
  24. package/dist/drawer.stories.d.ts +0 -1
  25. package/dist/dropdown.d.ts +7 -4
  26. package/dist/dropdown.js +1 -1
  27. package/dist/dropdown.option.js +1 -1
  28. package/dist/dropdown.option.styles.js +1 -0
  29. package/dist/dropdown.styles.js +47 -26
  30. package/dist/dropdown.test.focus.filterable.js +20 -0
  31. package/dist/dropdown.test.focus.js +1 -0
  32. package/dist/dropdown.test.form.js +23 -112
  33. package/dist/dropdown.test.interactions.filterable.js +121 -17
  34. package/dist/dropdown.test.interactions.multiple.js +15 -22
  35. package/dist/dropdown.test.interactions.single.js +44 -22
  36. package/dist/icon-button.d.ts +2 -0
  37. package/dist/icon-button.styles.js +2 -4
  38. package/dist/icons/checked.d.ts +5 -0
  39. package/dist/icons/checked.js +1 -1
  40. package/dist/input.d.ts +5 -4
  41. package/dist/input.js +1 -1
  42. package/dist/input.stories.d.ts +0 -4
  43. package/dist/input.styles.d.ts +1 -1
  44. package/dist/input.styles.js +93 -93
  45. package/dist/input.test.basics.js +45 -45
  46. package/dist/input.test.form.js +17 -0
  47. package/dist/label.styles.js +11 -13
  48. package/dist/library/localize.d.ts +1 -0
  49. package/dist/library/localize.test.js +45 -0
  50. package/dist/menu.button.styles.js +1 -0
  51. package/dist/menu.js +1 -1
  52. package/dist/menu.link.styles.js +1 -0
  53. package/dist/menu.styles.js +3 -1
  54. package/dist/menu.test.events.js +101 -7
  55. package/dist/menu.test.focus.js +26 -3
  56. package/dist/menu.test.interactions.js +5 -2
  57. package/dist/modal.d.ts +0 -7
  58. package/dist/modal.icon-button.test.basics.js +9 -9
  59. package/dist/modal.stories.d.ts +1 -0
  60. package/dist/modal.styles.js +2 -4
  61. package/dist/modal.tertiary-icon.test.basics.js +15 -15
  62. package/dist/modal.test.accessibility.js +16 -27
  63. package/dist/modal.test.basics.js +64 -68
  64. package/dist/modal.test.close.js +12 -16
  65. package/dist/modal.test.events.js +32 -44
  66. package/dist/modal.test.lock-scroll.js +15 -25
  67. package/dist/modal.test.methods.js +8 -12
  68. package/dist/modal.test.scrollbars.js +2 -4
  69. package/dist/radio-group.d.ts +4 -3
  70. package/dist/radio-group.js +1 -1
  71. package/dist/radio-group.stories.d.ts +1 -1
  72. package/dist/radio-group.test.basics.js +3 -3
  73. package/dist/radio-group.test.events.js +6 -6
  74. package/dist/radio-group.test.form.js +19 -0
  75. package/dist/radio.d.ts +1 -2
  76. package/dist/radio.js +1 -1
  77. package/dist/radio.styles.js +2 -6
  78. package/dist/split-button.styles.js +2 -4
  79. package/dist/split-container.d.ts +1 -1
  80. package/dist/split-container.styles.js +2 -4
  81. package/dist/status-indicator.d.ts +1 -1
  82. package/dist/styles/focus-outline.d.ts +1 -1
  83. package/dist/styles/focus-outline.js +7 -1
  84. package/dist/styles/menu-opening-animation.d.ts +2 -0
  85. package/dist/styles/menu-opening-animation.js +26 -0
  86. package/dist/styles/variables.css +1 -1
  87. package/dist/styles/visually-hidden.d.ts +1 -1
  88. package/dist/styles/visually-hidden.js +14 -1
  89. package/dist/tab.group.d.ts +6 -6
  90. package/dist/tab.group.js +1 -1
  91. package/dist/tab.group.styles.js +46 -5
  92. package/dist/tab.group.test.basics.js +9 -2
  93. package/dist/tab.group.test.interactions.js +70 -93
  94. package/dist/tab.js +1 -1
  95. package/dist/tab.panel.styles.js +3 -9
  96. package/dist/tab.styles.js +6 -13
  97. package/dist/tab.test.basics.js +15 -17
  98. package/dist/tabs.stories.d.ts +1 -0
  99. package/dist/tag.d.ts +3 -6
  100. package/dist/tag.js +1 -1
  101. package/dist/tag.styles.js +2 -4
  102. package/dist/tag.test.basics.js +28 -27
  103. package/dist/tag.test.events.js +3 -3
  104. package/dist/tag.test.focus.js +4 -4
  105. package/dist/textarea.d.ts +5 -4
  106. package/dist/textarea.stories.d.ts +0 -4
  107. package/dist/textarea.styles.d.ts +1 -1
  108. package/dist/textarea.styles.js +63 -67
  109. package/dist/textarea.test.basics.js +52 -52
  110. package/dist/toasts.d.ts +5 -0
  111. package/dist/toasts.styles.js +1 -1
  112. package/dist/toggle.d.ts +3 -3
  113. package/dist/toggle.js +1 -1
  114. package/dist/toggle.stories.d.ts +1 -1
  115. package/dist/toggle.styles.js +2 -1
  116. package/dist/toggle.test.interactions.js +37 -0
  117. package/dist/tooltip.d.ts +2 -2
  118. package/dist/tooltip.js +1 -1
  119. package/dist/tooltip.styles.js +22 -18
  120. package/dist/tooltip.test.interactions.js +6 -6
  121. package/dist/translations/en.js +1 -1
  122. package/dist/translations/fr.d.ts +3 -1
  123. package/dist/translations/fr.js +1 -1
  124. package/dist/translations/ja.d.ts +3 -1
  125. package/dist/translations/ja.js +1 -1
  126. package/dist/tree.d.ts +1 -1
  127. package/dist/tree.item.d.ts +0 -3
  128. package/dist/tree.item.icon-button.d.ts +1 -0
  129. package/dist/tree.item.icon-button.js +1 -1
  130. package/dist/tree.item.icon-button.test.basics.js +9 -0
  131. package/dist/tree.item.js +1 -1
  132. package/dist/tree.item.menu.d.ts +2 -0
  133. package/dist/tree.item.menu.js +1 -1
  134. package/dist/tree.item.menu.test.basics.js +15 -0
  135. package/dist/tree.item.styles.js +13 -3
  136. package/dist/tree.item.test.basics.d.ts +2 -1
  137. package/dist/tree.item.test.basics.js +16 -4
  138. package/dist/tree.js +1 -1
  139. package/dist/tree.test.focus.js +91 -4
  140. package/package.json +2 -1
  141. package/dist/button.test.form.d.ts +0 -1
  142. package/dist/button.test.form.js +0 -50
  143. package/dist/input.test.translations.js +0 -38
  144. package/dist/tag.test.translations.d.ts +0 -1
  145. package/dist/tag.test.translations.js +0 -25
  146. package/dist/textarea.test.translations.d.ts +0 -1
  147. package/dist/textarea.test.translations.js +0 -34
  148. /package/dist/{input.test.translations.d.ts → library/localize.test.d.ts} +0 -0
@@ -9,8 +9,8 @@ import GlideCoreTabPanel from './tab.panel.js';
9
9
  import sinon from 'sinon';
10
10
  GlideCoreTabGroup.shadowRootOptions.mode = 'open';
11
11
  GlideCoreTabPanel.shadowRootOptions.mode = 'open';
12
- it('renders an end overflow button on end overflow', async () => {
13
- const element = await fixture(html `
12
+ it('does not render overflow buttons when there is no overflow', async () => {
13
+ const component = await fixture(html `
14
14
  <div style="width:25rem">
15
15
  <glide-core-tab-group>
16
16
  <glide-core-tab slot="nav" panel="1">Tab 1</glide-core-tab>
@@ -29,13 +29,15 @@ it('renders an end overflow button on end overflow', async () => {
29
29
  </glide-core-tab-group>
30
30
  </div>
31
31
  `);
32
- const tabGroup = element.querySelector('glide-core-tab-group');
32
+ const tabGroup = component.querySelector('glide-core-tab-group');
33
+ const startOverflowButton = tabGroup?.shadowRoot?.querySelector('[data-test="overflow-start-button"]');
34
+ expect(startOverflowButton).to.be.null;
33
35
  const endOverflowButton = tabGroup?.shadowRoot?.querySelector('[data-test="overflow-end-button"]');
34
- expect(endOverflowButton).to.be.not.null;
36
+ expect(endOverflowButton).to.be.null;
35
37
  });
36
- it('does not render an end overflow button when there is no end overflow', async () => {
37
- const element = await fixture(html `
38
- <div style="width:25rem">
38
+ it('renders overflow buttons when there is overflow', async () => {
39
+ const component = await fixture(html `
40
+ <div style="width:23rem">
39
41
  <glide-core-tab-group>
40
42
  <glide-core-tab slot="nav" panel="1">Tab 1</glide-core-tab>
41
43
  <glide-core-tab slot="nav" panel="2">Tab 2</glide-core-tab>
@@ -53,15 +55,15 @@ it('does not render an end overflow button when there is no end overflow', async
53
55
  </glide-core-tab-group>
54
56
  </div>
55
57
  `);
56
- const tabGroup = element.querySelector('glide-core-tab-group');
57
- const endOverflowButton = tabGroup?.shadowRoot?.querySelector('[data-test="overflow-end-button"]');
58
- expect(endOverflowButton).to.be.not.null;
59
- endOverflowButton?.click();
60
- await waitUntil(() => tabGroup?.shadowRoot?.querySelector('[data-test="overflow-end-button"]') === null);
58
+ const tabGroup = component.querySelector('glide-core-tab-group');
59
+ await waitUntil(() => {
60
+ return (tabGroup?.shadowRoot?.querySelector('[data-test="overflow-start-button"]') !== null &&
61
+ tabGroup?.shadowRoot?.querySelector('[data-test="overflow-end-button"]') !== null);
62
+ });
61
63
  });
62
- it('renders a start overflow button on start overflow', async () => {
63
- const element = await fixture(html `
64
- <div style="width:25rem">
64
+ it('renders a disabled start-overflow button when there is only overflow towards the end', async () => {
65
+ const component = await fixture(html `
66
+ <div style="width:23rem">
65
67
  <glide-core-tab-group>
66
68
  <glide-core-tab slot="nav" panel="1">Tab 1</glide-core-tab>
67
69
  <glide-core-tab slot="nav" panel="2">Tab 2</glide-core-tab>
@@ -79,17 +81,19 @@ it('renders a start overflow button on start overflow', async () => {
79
81
  </glide-core-tab-group>
80
82
  </div>
81
83
  `);
82
- const tabGroup = element.querySelector('glide-core-tab-group');
83
- // Need to get the tab group into a state where there
84
- // is overflow on the right -- do this by first scrolling to the right
84
+ const tabGroup = component.querySelector('glide-core-tab-group');
85
+ await waitUntil(() => {
86
+ return (tabGroup?.shadowRoot?.querySelector('[data-test="overflow-start-button"]') !== null &&
87
+ tabGroup?.shadowRoot?.querySelector('[data-test="overflow-end-button"]') !== null);
88
+ });
89
+ const startOverflowButton = tabGroup?.shadowRoot?.querySelector('[data-test="overflow-start-button"]');
90
+ expect(startOverflowButton?.disabled).to.be.true;
85
91
  const endOverflowButton = tabGroup?.shadowRoot?.querySelector('[data-test="overflow-end-button"]');
86
- expect(endOverflowButton).to.be.not.null;
87
- endOverflowButton?.click();
88
- await waitUntil(() => tabGroup?.shadowRoot?.querySelector('[data-test="overflow-start-button"]'));
92
+ expect(endOverflowButton?.disabled).to.be.false;
89
93
  });
90
- it('does not render a start overflow button when there is no start overflow', async () => {
91
- const element = await fixture(html `
92
- <div style="width:25rem">
94
+ it('renders a disabled end-overflow button when there is only overflow at the start', async () => {
95
+ const component = await fixture(html `
96
+ <div style="width:23rem">
93
97
  <glide-core-tab-group>
94
98
  <glide-core-tab slot="nav" panel="1">Tab 1</glide-core-tab>
95
99
  <glide-core-tab slot="nav" panel="2">Tab 2</glide-core-tab>
@@ -107,21 +111,27 @@ it('does not render a start overflow button when there is no start overflow', as
107
111
  </glide-core-tab-group>
108
112
  </div>
109
113
  `);
110
- const tabGroup = element.querySelector('glide-core-tab-group');
114
+ const tabGroup = component.querySelector('glide-core-tab-group');
115
+ await waitUntil(() => {
116
+ return (tabGroup?.shadowRoot?.querySelector('[data-test="overflow-start-button"]') !== null &&
117
+ tabGroup?.shadowRoot?.querySelector('[data-test="overflow-end-button"]') !== null);
118
+ });
119
+ // Need to get the tab group into a state where there
120
+ // is overflow at the start -- do this by first scrolling to the end
121
+ const startOverflowButton = tabGroup?.shadowRoot?.querySelector('[data-test="overflow-start-button"]');
122
+ expect(startOverflowButton?.disabled).to.be.true;
111
123
  const endOverflowButton = tabGroup?.shadowRoot?.querySelector('[data-test="overflow-end-button"]');
112
- let startOverflowButton = tabGroup?.shadowRoot?.querySelector('[data-test="overflow-start-button"]');
113
- expect(endOverflowButton).to.be.not.null;
114
- expect(startOverflowButton).to.be.null;
124
+ expect(endOverflowButton?.disabled).to.be.false;
115
125
  endOverflowButton?.click();
116
- await waitUntil(() => tabGroup?.shadowRoot?.querySelector('[data-test="overflow-start-button"]'));
117
- startOverflowButton = tabGroup?.shadowRoot?.querySelector('[data-test="overflow-start-button"]');
118
- startOverflowButton?.click();
119
- await waitUntil(() => tabGroup?.shadowRoot?.querySelector('[data-test="overflow-start-button"]') === null);
126
+ await waitUntil(() => {
127
+ return (tabGroup?.shadowRoot?.querySelector('[data-test="overflow-end-button"]')?.disabled === true);
128
+ });
129
+ expect(startOverflowButton?.disabled).to.be.false;
120
130
  });
121
131
  it('scrolls tabs when overflow buttons are clicked', async () => {
122
132
  const spy = sinon.spy();
123
- const element = await fixture(html `
124
- <div style="width:25rem">
133
+ const component = await fixture(html `
134
+ <div style="width:23rem">
125
135
  <glide-core-tab-group>
126
136
  <glide-core-tab slot="nav" panel="1">Tab 1</glide-core-tab>
127
137
  <glide-core-tab slot="nav" panel="2">Tab 2</glide-core-tab>
@@ -139,25 +149,31 @@ it('scrolls tabs when overflow buttons are clicked', async () => {
139
149
  </glide-core-tab-group>
140
150
  </div>
141
151
  `);
142
- const tabGroup = element.querySelector('glide-core-tab-group');
152
+ const tabGroup = component.querySelector('glide-core-tab-group');
153
+ await waitUntil(() => {
154
+ return (tabGroup?.shadowRoot?.querySelector('[data-test="overflow-start-button"]') !== null &&
155
+ tabGroup?.shadowRoot?.querySelector('[data-test="overflow-end-button"]') !== null);
156
+ });
143
157
  tabGroup?.shadowRoot
144
158
  ?.querySelector('[role="tablist"]')
145
159
  ?.addEventListener('scroll', spy);
146
160
  const endOverflowButton = tabGroup?.shadowRoot?.querySelector('[data-test="overflow-end-button"]');
147
- expect(endOverflowButton).to.be.not.null;
148
161
  endOverflowButton?.click();
149
- await waitUntil(() => tabGroup?.shadowRoot?.querySelector('[data-test="overflow-end-button"]') === null);
150
- expect(spy.called).to.be.true;
162
+ await waitUntil(() => tabGroup?.shadowRoot?.querySelector('[data-test="overflow-end-button"]')?.disabled === true);
163
+ expect(spy.callCount).to.equal(1);
151
164
  spy.resetHistory();
152
165
  const startOverflowButton = tabGroup?.shadowRoot?.querySelector('[data-test="overflow-start-button"]');
153
166
  expect(startOverflowButton).to.be.not.null;
167
+ expect(startOverflowButton?.disabled).to.be.false;
154
168
  startOverflowButton?.click();
155
- await waitUntil(() => tabGroup?.shadowRoot?.querySelector('[data-test="overflow-start-button"]') === null);
156
- expect(spy.called).to.be.true;
169
+ await waitUntil(() => tabGroup?.shadowRoot?.querySelector('[data-test="overflow-start-button"]')?.disabled === true);
170
+ expect(spy.callCount).to.equal(1);
171
+ expect(startOverflowButton?.disabled).to.be.true;
172
+ expect(endOverflowButton?.disabled).to.be.false;
157
173
  });
158
174
  it('removes overflow buttons when the component is resized and there is no overflow', async () => {
159
- const element = await fixture(html `
160
- <div style="width:25rem" data-test="test-parent">
175
+ const component = await fixture(html `
176
+ <div style="width:23rem" data-test="test-parent">
161
177
  <glide-core-tab-group>
162
178
  <glide-core-tab slot="nav" panel="1">Tab 1</glide-core-tab>
163
179
  <glide-core-tab slot="nav" panel="2">Tab 2</glide-core-tab>
@@ -175,9 +191,11 @@ it('removes overflow buttons when the component is resized and there is no overf
175
191
  </glide-core-tab-group>
176
192
  </div>
177
193
  `);
178
- const tabGroup = element.querySelector('glide-core-tab-group');
179
- const endOverflowButton = tabGroup?.shadowRoot?.querySelector('[data-test="overflow-end-button"]');
180
- expect(endOverflowButton).to.be.not.null;
194
+ const tabGroup = component.querySelector('glide-core-tab-group');
195
+ await waitUntil(() => {
196
+ return (tabGroup?.shadowRoot?.querySelector('[data-test="overflow-start-button"]') !== null &&
197
+ tabGroup?.shadowRoot?.querySelector('[data-test="overflow-end-button"]') !== null);
198
+ });
181
199
  const container = document?.querySelector('[data-test="test-parent"]');
182
200
  expect(container).to.be.not.null;
183
201
  container.style.width = 'auto';
@@ -185,7 +203,7 @@ it('removes overflow buttons when the component is resized and there is no overf
185
203
  tabGroup?.shadowRoot?.querySelector('[data-test="overflow-end-button"]') === null);
186
204
  });
187
205
  it('renders overflow buttons when the component is resized and there is overflow', async () => {
188
- const element = await fixture(html `
206
+ const component = await fixture(html `
189
207
  <div data-test="test-parent">
190
208
  <glide-core-tab-group>
191
209
  <glide-core-tab slot="nav" panel="1">Tab 1</glide-core-tab>
@@ -204,57 +222,16 @@ it('renders overflow buttons when the component is resized and there is overflow
204
222
  </glide-core-tab-group>
205
223
  </div>
206
224
  `);
207
- const tabGroup = element.querySelector('glide-core-tab-group');
225
+ const tabGroup = component.querySelector('glide-core-tab-group');
226
+ const startOverflowButton = tabGroup?.shadowRoot?.querySelector('[data-test="overflow-start-button"]');
208
227
  const endOverflowButton = tabGroup?.shadowRoot?.querySelector('[data-test="overflow-end-button"]');
228
+ expect(startOverflowButton).to.be.null;
209
229
  expect(endOverflowButton).to.be.null;
210
230
  const container = document?.querySelector('[data-test="test-parent"]');
211
231
  expect(container).to.be.not.null;
212
- container.style.width = '25rem';
213
- await waitUntil(() => tabGroup?.shadowRoot?.querySelector('[data-test="overflow-start-button"]') === null &&
214
- tabGroup?.shadowRoot?.querySelector('[data-test="overflow-end-button"]'));
215
- });
216
- it('scrolls using keyboard when there is overflow and only a few pixels of overflowed tabs are on-screen', async () => {
217
- const spy = sinon.spy();
218
- const element = await fixture(html `
219
- <div style="width: 17rem;">
220
- <glide-core-tab-group>
221
- <glide-core-tab slot="nav" panel="1">Tab 1</glide-core-tab>
222
- <glide-core-tab slot="nav" panel="2">Tab 2</glide-core-tab>
223
- <glide-core-tab slot="nav" panel="3">Tab 3</glide-core-tab>
224
- <glide-core-tab slot="nav" panel="4">Tab 4</glide-core-tab>
225
-
226
- <glide-core-tab-panel name="1">Content for tab 1 </glide-core-tab-panel>
227
- <glide-core-tab-panel name="2">
228
- Content for tab 2
229
- </glide-core-tab-panel>
230
- <glide-core-tab-panel name="3">
231
- Content for tab 3
232
- </glide-core-tab-panel>
233
- <glide-core-tab-panel name="4">
234
- Content for tab 4
235
- </glide-core-tab-panel>
236
- </glide-core-tab-group>
237
- </div>
238
- `);
239
- const tabGroup = element.querySelector('glide-core-tab-group');
240
- expect(tabGroup).to.be.not.null;
241
- tabGroup?.shadowRoot
242
- ?.querySelector('[role="tablist"]')
243
- ?.addEventListener('scroll', spy);
244
- tabGroup?.tabElements[0].focus();
245
- await sendKeys({ press: 'ArrowRight' });
246
- await sendKeys({ press: 'ArrowRight' });
247
- await sendKeys({ press: 'ArrowRight' });
248
- await waitUntil(() => tabGroup?.shadowRoot?.querySelector('[data-test="overflow-end-button"]') === null);
249
- expect(tabGroup?.tabElements[3]).to.have.focus;
250
- expect(spy.callCount).to.equal(1);
251
- spy.resetHistory();
252
- await sendKeys({ press: 'ArrowLeft' });
253
- await sendKeys({ press: 'ArrowLeft' });
254
- await sendKeys({ press: 'ArrowLeft' });
255
- await waitUntil(() => tabGroup?.shadowRoot?.querySelector('[data-test="overflow-start-button"]') === null);
256
- expect(tabGroup?.tabElements[0]).to.have.focus;
257
- expect(spy.callCount).to.equal(1);
232
+ container.style.width = '23rem';
233
+ await waitUntil(() => tabGroup?.shadowRoot?.querySelector('[data-test="overflow-start-button"]') !== null &&
234
+ tabGroup?.shadowRoot?.querySelector('[data-test="overflow-end-button"]') !== null);
258
235
  });
259
236
  it('has only one active tab that is tabbable after pressing the Enter key', async () => {
260
237
  const tabGroup = await fixture(html `
package/dist/tab.js CHANGED
@@ -1 +1 @@
1
- var __decorate=this&&this.__decorate||function(t,e,i,o){var s,r=arguments.length,a=r<3?e:null===o?o=Object.getOwnPropertyDescriptor(e,i):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(t,e,i,o);else for(var l=t.length-1;l>=0;l--)(s=t[l])&&(a=(r<3?s(a):r>3?s(e,i,a):s(e,i))||a);return r>3&&a&&Object.defineProperty(e,i,a),a};import{LitElement,html}from"lit";import{classMap}from"lit/directives/class-map.js";import{customElement,property}from"lit/decorators.js";import{nanoid}from"nanoid";import styles from"./tab.styles.js";let GlideCoreTab=class GlideCoreTab extends LitElement{constructor(){super(...arguments),this.panel="",this.active=!1,this.disabled=!1,this.#t=nanoid()}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}firstUpdated(){this.setAttribute("role","tab"),this.id=this.#t}render(){return html`<div class="${classMap({component:!0,active:this.active,disabled:this.disabled})}"><span class="container"><slot name="icon"></slot><div class="default-slot"><slot></slot></div></span></div>`}updated(t){t.has("active")&&this.setAttribute("aria-selected",this.active?"true":"false"),t.has("disabled")&&(this.disabled?(this.setAttribute("aria-disabled","true"),this.setAttribute("tabindex","-1")):this.removeAttribute("aria-disabled"))}#t};__decorate([property({reflect:!0})],GlideCoreTab.prototype,"panel",void 0),__decorate([property({type:Boolean,reflect:!0})],GlideCoreTab.prototype,"active",void 0),__decorate([property({type:Boolean,reflect:!0})],GlideCoreTab.prototype,"disabled",void 0),GlideCoreTab=__decorate([customElement("glide-core-tab")],GlideCoreTab);export default GlideCoreTab;
1
+ var __decorate=this&&this.__decorate||function(t,e,i,o){var s,r=arguments.length,a=r<3?e:null===o?o=Object.getOwnPropertyDescriptor(e,i):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(t,e,i,o);else for(var d=t.length-1;d>=0;d--)(s=t[d])&&(a=(r<3?s(a):r>3?s(e,i,a):s(e,i))||a);return r>3&&a&&Object.defineProperty(e,i,a),a};import{LitElement,html}from"lit";import{classMap}from"lit/directives/class-map.js";import{customElement,property}from"lit/decorators.js";import{nanoid}from"nanoid";import styles from"./tab.styles.js";let GlideCoreTab=class GlideCoreTab extends LitElement{constructor(){super(...arguments),this.panel="",this.active=!1,this.disabled=!1,this.#t=nanoid()}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:"closed"}}static{this.styles=styles}firstUpdated(){this.setAttribute("role","tab"),this.id=this.#t}render(){return html`<div class="${classMap({component:!0,active:this.active,disabled:this.disabled})}"><div class="container"><slot name="icon"></slot><div class="default-slot"><slot></slot></div></div></div>`}updated(t){t.has("active")&&this.setAttribute("aria-selected",this.active?"true":"false"),t.has("disabled")&&(this.disabled?(this.setAttribute("aria-disabled","true"),this.setAttribute("tabindex","-1")):this.removeAttribute("aria-disabled"))}#t};__decorate([property({reflect:!0})],GlideCoreTab.prototype,"panel",void 0),__decorate([property({type:Boolean,reflect:!0})],GlideCoreTab.prototype,"active",void 0),__decorate([property({type:Boolean,reflect:!0})],GlideCoreTab.prototype,"disabled",void 0),GlideCoreTab=__decorate([customElement("glide-core-tab")],GlideCoreTab);export default GlideCoreTab;
@@ -1,19 +1,13 @@
1
1
  import{css}from"lit";import focusOutline from"./styles/focus-outline.js";import visuallyHidden from"./styles/visually-hidden.js";export default[css`
2
+ ${focusOutline(":host(:focus-visible) .component")}
3
+ ${visuallyHidden(".hidden")}
4
+ `,css`
2
5
  :host(:focus-visible) {
3
6
  outline: none;
4
7
  }
5
8
 
6
- /* stylelint-disable-next-line csstools/use-nesting */
7
- :host(:focus-visible) .component {
8
- ${focusOutline};
9
- }
10
-
11
9
  .component {
12
10
  font-family: var(--glide-core-font-sans);
13
11
  outline: none;
14
12
  }
15
-
16
- .hidden {
17
- ${visuallyHidden};
18
- }
19
13
  `];
@@ -1,30 +1,22 @@
1
1
  import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export default[css`
2
+ ${focusOutline(":host(:focus-visible) .container")}
3
+ `,css`
2
4
  :host {
3
5
  outline: none;
4
6
  }
5
7
 
6
- /* Using nesting creates an issue on Safari with :host */
7
- /* stylelint-disable-next-line csstools/use-nesting */
8
- :host(:focus-visible) .component .container {
9
- ${focusOutline};
10
- }
11
-
12
8
  .component {
13
9
  align-items: center;
10
+ box-sizing: border-box;
14
11
  cursor: pointer;
12
+ display: flex;
15
13
  font-family: var(--glide-core-heading-xxs-font-family);
16
14
  font-size: var(--glide-core-heading-xxxs-font-size);
17
15
  font-style: var(--glide-core-heading-xxs-font-style);
18
16
  font-weight: var(--glide-core-body-sm-font-weight);
19
17
  gap: 0.4375rem;
20
18
  justify-content: center;
21
- line-height: 1.1875rem;
22
- padding-block: var(--glide-core-spacing-xs);
23
- padding-inline: var(--glide-core-spacing-md);
24
-
25
- &.active {
26
- border-block-end: 2px solid var(--glide-core-border-focus);
27
- }
19
+ padding-block: 0.4375rem;
28
20
 
29
21
  &:hover {
30
22
  color: var(--glide-core-text-primary);
@@ -37,6 +29,7 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export
37
29
  }
38
30
 
39
31
  & .container {
32
+ align-items: center;
40
33
  border-radius: 0.0625rem;
41
34
  display: flex;
42
35
  flex-shrink: 0;
@@ -6,44 +6,42 @@ it('registers', async () => {
6
6
  expect(window.customElements.get('glide-core-tab')).to.equal(GlideCoreTab);
7
7
  });
8
8
  it('renders correct markup and sets correct attributes for the default case', async () => {
9
- const element = await fixture(html `
9
+ const component = await fixture(html `
10
10
  <glide-core-tab>Tab</glide-core-tab>
11
11
  `);
12
- await expect(element).to.not.be.accessible();
13
- expect(element.active).to.equal(false, 'active defaults to false');
14
- expect(element.disabled).to.equal(false, 'disabled defaults to false');
15
- expect(element.getAttribute('aria-disabled')).to.equal(null, 'does not set aria-disabled');
16
- expect([...element.shadowRoot.firstElementChild.classList]).to.deep.equal([
17
- 'component',
18
- ]);
12
+ await expect(component).to.not.be.accessible();
13
+ expect(component.active).to.equal(false, 'active defaults to false');
14
+ expect(component.disabled).to.equal(false, 'disabled defaults to false');
15
+ expect(component.getAttribute('aria-disabled')).to.equal(null, 'does not set aria-disabled');
16
+ expect([...component.shadowRoot.firstElementChild.classList]).to.deep.equal(['component']);
19
17
  });
20
18
  it('sets the panel attribute', async () => {
21
- const element = await fixture(html `
19
+ const component = await fixture(html `
22
20
  <glide-core-tab panel="details">Tab</glide-core-tab>
23
21
  `);
24
- expect(element.panel).to.equal('details');
22
+ expect(component.panel).to.equal('details');
25
23
  });
26
24
  it('sets the active attribute', async () => {
27
- const element = await fixture(html `
25
+ const component = await fixture(html `
28
26
  <glide-core-tab active>Tab</glide-core-tab>
29
27
  `);
30
- expect(element.active).to.equal(true);
28
+ expect(component.active).to.equal(true);
31
29
  });
32
30
  it('sets the disabled attribute', async () => {
33
- const element = await fixture(html `
31
+ const component = await fixture(html `
34
32
  <glide-core-tab disabled>Tab</glide-core-tab>
35
33
  `);
36
- expect(element.disabled).to.equal(true);
37
- expect(element).to.have.attribute('aria-disabled', 'true');
34
+ expect(component.disabled).to.equal(true);
35
+ expect(component).to.have.attribute('aria-disabled', 'true');
38
36
  });
39
37
  it('renders the icon slot', async () => {
40
- const element = await fixture(html `
38
+ const component = await fixture(html `
41
39
  <glide-core-tab>
42
40
  <span slot="icon">Icon</span>
43
41
  <span>Tab</span>
44
42
  </glide-core-tab>
45
43
  `);
46
- const slotNodes = element
44
+ const slotNodes = component
47
45
  .shadowRoot.querySelector('slot[name="icon"]')
48
46
  ?.assignedNodes();
49
47
  expect(slotNodes?.length).to.equal(1);
@@ -1,3 +1,4 @@
1
+ import './icons/storybook.js';
1
2
  import './tab.group.js';
2
3
  import './tab.js';
3
4
  import './tab.panel.js';
package/dist/tag.d.ts CHANGED
@@ -5,13 +5,10 @@ declare global {
5
5
  }
6
6
  }
7
7
  /**
8
- * @description A tag component to categorize information.
8
+ * @event remove - Emitted when the tag is removed.
9
9
  *
10
- * @event remove - Emitted when `glide-core-tag` is removed
11
- *
12
- * @slot - The content of the tag
13
- *
14
- * @slot prefix - A slot for an optional icon
10
+ * @slot - The content of the tag.
11
+ * @slot prefix - A slot for an optional icon.
15
12
  */
16
13
  export default class GlideCoreTag extends LitElement {
17
14
  #private;
package/dist/tag.js CHANGED
@@ -1 +1 @@
1
- var __decorate=this&&this.__decorate||function(e,t,o,l){var i,r=arguments.length,s=r<3?t:null===l?l=Object.getOwnPropertyDescriptor(t,o):l;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,o,l);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(r<3?i(s):r>3?i(t,o,s):i(t,o))||s);return r>3&&s&&Object.defineProperty(t,o,s),s};import{LitElement,html}from"lit";import{LocalizeController}from"./library/localize.js";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property}from"lit/decorators.js";import{owSlot}from"./library/ow.js";import{when}from"lit/directives/when.js";import styles from"./tag.styles.js";let GlideCoreTag=class GlideCoreTag extends LitElement{constructor(){super(...arguments),this.size="medium",this.removableLabel="",this.#e=createRef(),this.#t=createRef(),this.#o=createRef(),this.#l=new LocalizeController(this),this.#i=createRef(),this.#r=200,this.#s=()=>{new Promise((()=>setTimeout((()=>{this.remove()}),this.#r))),this.#t.value?.classList.toggle("activate"),this.#t.value?.classList.toggle("deactivate"),this.dispatchEvent(new Event("remove"))}}static{this.shadowRootOptions={...LitElement.shadowRootOptions,delegatesFocus:!0,mode:"closed"}}static{this.styles=styles}click(){this.#e.value?.click()}firstUpdated(){owSlot(this.#o.value)}render(){return html`<div class="${classMap({component:!0,activate:!0,[this.size]:!0})}" ${ref(this.#t)}><slot name="prefix" ${ref(this.#i)}></slot><slot @slotchange="${this.#a}" ${ref(this.#o)}></slot>${when(this.removableLabel,(()=>html`<button type="button" class="${classMap({[this.size]:!0})}" aria-label="${this.#l.term("removeTag",this.removableLabel)}" data-test="button" ${ref(this.#e)} @click="${this.#s}"><svg width="12" height="12" viewBox="0 0 24 24" fill="none"><path d="M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M18 6L6 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></button>`))}</div>`}#e;#t;#o;#l;#i;#r;#s;#a(){owSlot(this.#o.value)}};__decorate([property({reflect:!0})],GlideCoreTag.prototype,"size",void 0),__decorate([property({attribute:"removable-label"})],GlideCoreTag.prototype,"removableLabel",void 0),GlideCoreTag=__decorate([customElement("glide-core-tag")],GlideCoreTag);export default GlideCoreTag;
1
+ var __decorate=this&&this.__decorate||function(e,t,o,l){var i,r=arguments.length,s=r<3?t:null===l?l=Object.getOwnPropertyDescriptor(t,o):l;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,o,l);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(r<3?i(s):r>3?i(t,o,s):i(t,o))||s);return r>3&&s&&Object.defineProperty(t,o,s),s};import{LitElement,html}from"lit";import{LocalizeController}from"./library/localize.js";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property}from"lit/decorators.js";import{owSlot}from"./library/ow.js";import{when}from"lit/directives/when.js";import styles from"./tag.styles.js";let GlideCoreTag=class GlideCoreTag extends LitElement{constructor(){super(...arguments),this.size="medium",this.removableLabel="",this.#e=createRef(),this.#t=createRef(),this.#o=createRef(),this.#l=new LocalizeController(this),this.#i=createRef(),this.#r=200,this.#s=()=>{new Promise((()=>setTimeout((()=>{this.remove()}),this.#r))),this.#t.value?.classList.toggle("activate"),this.#t.value?.classList.toggle("deactivate"),this.dispatchEvent(new Event("remove"))}}static{this.shadowRootOptions={...LitElement.shadowRootOptions,delegatesFocus:!0,mode:"closed"}}static{this.styles=styles}click(){this.#e.value?.click()}firstUpdated(){owSlot(this.#o.value)}render(){return html`<div class="${classMap({component:!0,activate:!0,[this.size]:!0})}" data-test="component" ${ref(this.#t)}><slot name="prefix" ${ref(this.#i)}></slot><slot @slotchange="${this.#a}" ${ref(this.#o)}></slot>${when(this.removableLabel,(()=>html`<button type="button" class="${classMap({[this.size]:!0})}" aria-label="${this.#l.term("removeTag",this.removableLabel)}" data-test="button" ${ref(this.#e)} @click="${this.#s}"><svg width="12" height="12" viewBox="0 0 24 24" fill="none"><path d="M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M18 6L6 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></button>`))}</div>`}#e;#t;#o;#l;#i;#r;#s;#a(){owSlot(this.#o.value)}};__decorate([property({reflect:!0})],GlideCoreTag.prototype,"size",void 0),__decorate([property({attribute:"removable-label"})],GlideCoreTag.prototype,"removableLabel",void 0),GlideCoreTag=__decorate([customElement("glide-core-tag")],GlideCoreTag);export default GlideCoreTag;
@@ -1,4 +1,6 @@
1
1
  import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export default[css`
2
+ ${focusOutline("button:focus-visible")}
3
+ `,css`
2
4
  .component {
3
5
  align-items: center;
4
6
  background: var(--glide-core-surface-base);
@@ -126,9 +128,5 @@ import{css}from"lit";import focusOutline from"./styles/focus-outline.js";export
126
128
  &:focus {
127
129
  outline: none;
128
130
  }
129
-
130
- &:focus-visible {
131
- ${focusOutline};
132
- }
133
131
  }
134
132
  `];
@@ -8,64 +8,64 @@ it('registers', async () => {
8
8
  expect(window.customElements.get('glide-core-tag')).to.equal(GlideCoreTag);
9
9
  });
10
10
  it('is accessible', async () => {
11
- const element = await fixture(html `<glide-core-tag>Tag</glide-core-tag>`);
11
+ const component = await fixture(html `<glide-core-tag>Tag</glide-core-tag>`);
12
12
  // Wait for the animation to complete
13
13
  await aTimeout(200);
14
- await expect(element).to.be.accessible();
14
+ await expect(component).to.be.accessible();
15
15
  });
16
16
  it('renders with default slot content', async () => {
17
- const element = await fixture(html `<glide-core-tag><span data-content>Tag</span></glide-core-tag>`);
18
- expect(element).to.be.not.null;
19
- const container = element.shadowRoot?.querySelector('.component');
17
+ const component = await fixture(html `<glide-core-tag><span data-content>Tag</span></glide-core-tag>`);
18
+ expect(component).to.be.not.null;
19
+ const container = component.shadowRoot?.querySelector('[data-test="component"]');
20
20
  expect(container).to.be.not.null;
21
- const contentRendered = element.querySelector('[data-content]');
21
+ const contentRendered = component.querySelector('[data-content]');
22
22
  expect(contentRendered).to.be.not.null;
23
23
  expect(contentRendered?.textContent).to.be.equal('Tag');
24
24
  });
25
25
  it('does not render an icon button when "removable-label" attribute is not set', async () => {
26
- const element = await fixture(html `<glide-core-tag><span data-content>Tag</span></glide-core-tag>`);
27
- expect(element).to.not.have.attribute('removable-label');
28
- const iconButton = element.shadowRoot?.querySelector('button');
26
+ const component = await fixture(html `<glide-core-tag><span data-content>Tag</span></glide-core-tag>`);
27
+ expect(component).to.not.have.attribute('removable-label');
28
+ const iconButton = component.shadowRoot?.querySelector('[data-test="button"]');
29
29
  expect(iconButton).to.be.null;
30
30
  });
31
31
  it('renders an icon button with aria-label when "removable-label" attribute is set', async () => {
32
- const element = await fixture(html `<glide-core-tag removable-label="test-aria-label"
32
+ const component = await fixture(html `<glide-core-tag removable-label="test-aria-label"
33
33
  ><span slot="prefix">Prefix</span
34
34
  ><span data-content>Tag</span></glide-core-tag
35
35
  >`);
36
- expect(element).to.be.not.null;
37
- expect(element).to.have.attribute('removable-label', 'test-aria-label');
38
- const iconButton = element.shadowRoot?.querySelector('button');
36
+ expect(component).to.be.not.null;
37
+ expect(component).to.have.attribute('removable-label', 'test-aria-label');
38
+ const iconButton = component.shadowRoot?.querySelector('[data-test="button"]');
39
39
  expect(iconButton).to.be.not.null;
40
40
  expect(iconButton).to.have.attribute('aria-label', `Remove tag: test-aria-label`);
41
41
  expect(iconButton).to.have.attribute('type', 'button');
42
42
  });
43
43
  it('renders the "prefix" slot and its content', async () => {
44
- const element = await fixture(html `<glide-core-tag
44
+ const component = await fixture(html `<glide-core-tag
45
45
  ><span slot="prefix" data-prefix>test-prefix</span>Tag</glide-core-tag
46
46
  >`);
47
- const prefixSlot = element.shadowRoot?.querySelector('slot[name="prefix"]');
47
+ const prefixSlot = component.shadowRoot?.querySelector('slot[name="prefix"]');
48
48
  expect(prefixSlot?.assignedNodes()?.length).to.be.equal(1);
49
49
  expect(document.querySelector('[data-prefix]')).to.be.not.null;
50
50
  expect(document.querySelector('[data-prefix]')?.textContent).to.be.equal('test-prefix');
51
51
  });
52
52
  it('renders correctly when the "size" attribute is set to "small"', async () => {
53
- const element = await fixture(html `<glide-core-tag removable-label="test-aria-label" size="small"
53
+ const component = await fixture(html `<glide-core-tag removable-label="test-aria-label" size="small"
54
54
  ><span slot="prefix">Prefix</span
55
55
  ><span data-content>Tag</span></glide-core-tag
56
56
  >`);
57
- const container = element.shadowRoot?.querySelector('.component');
58
- const iconButton = element.shadowRoot?.querySelector('button');
57
+ const container = component.shadowRoot?.querySelector('[data-test="component"]');
58
+ const iconButton = component.shadowRoot?.querySelector('[data-test="button"]');
59
59
  expect(container).to.have.class('small');
60
60
  expect(iconButton).to.have.class('small');
61
61
  });
62
62
  it('renders correctly when the "size" attribute is set to "large"', async () => {
63
- const element = await fixture(html `<glide-core-tag removable-label="test-aria-label" size="large"
63
+ const component = await fixture(html `<glide-core-tag removable-label="test-aria-label" size="large"
64
64
  ><span slot="prefix">Prefix</span
65
65
  ><span data-content>Tag</span></glide-core-tag
66
66
  >`);
67
- const container = element.shadowRoot?.querySelector('.component');
68
- const iconButton = element.shadowRoot?.querySelector('button');
67
+ const container = component.shadowRoot?.querySelector('[data-test="component"]');
68
+ const iconButton = component.shadowRoot?.querySelector('[data-test="button"]');
69
69
  expect(container).to.have.class('large');
70
70
  expect(iconButton).to.have.class('large');
71
71
  });
@@ -94,23 +94,24 @@ it('does not throw an error when the default slot is non-empty', async () => {
94
94
  expect(spy.callCount).to.equal(0);
95
95
  });
96
96
  it('toggles the "activate" and "deactivate" clases when the button is clicked', async () => {
97
- const element = await fixture(html `<glide-core-tag removable-label="test-aria-label"
97
+ const component = await fixture(html `<glide-core-tag removable-label="test-aria-label"
98
98
  ><span slot="prefix">Prefix</span>Tag</glide-core-tag
99
99
  >`);
100
- const container = element.shadowRoot?.querySelector('.component');
101
- const iconButton = element.shadowRoot?.querySelector('button');
100
+ const container = component.shadowRoot?.querySelector('[data-test="component"]');
101
+ const iconButton = component.shadowRoot?.querySelector('[data-test="button"]');
102
102
  expect(container).to.have.class('activate');
103
103
  iconButton?.click();
104
104
  expect(container).to.have.class('deactivate');
105
105
  });
106
106
  it('removes the tag from the DOM when the button is clicked', async () => {
107
- const element = await fixture(html `<glide-core-tag removable-label="test-aria-label"
107
+ const component = await fixture(html `<glide-core-tag removable-label="test-aria-label"
108
108
  ><span slot="prefix">Prefix</span
109
109
  ><span data-content>Tag</span></glide-core-tag
110
110
  >`);
111
- expect(element.shadowRoot?.querySelector('.component')).to.be.not.null;
111
+ expect(component.shadowRoot?.querySelector('[data-test="component"]')).to.be
112
+ .not.null;
112
113
  expect(document.querySelector('[data-content]')).to.be.not.null;
113
- element?.click();
114
+ component?.click();
114
115
  // Wait for the animation to complete
115
116
  await aTimeout(300);
116
117
  // the tag and its contents should be removed
@@ -3,14 +3,14 @@ import { expect, fixture, html, oneEvent } from '@open-wc/testing';
3
3
  import GlideCoreTag from './tag.js';
4
4
  GlideCoreTag.shadowRootOptions.mode = 'open';
5
5
  it('dispatches a "remove" event when the icon button is clicked', async () => {
6
- const element = await fixture(html `<glide-core-tag removable-label="test-aria-label"
6
+ const component = await fixture(html `<glide-core-tag removable-label="test-aria-label"
7
7
  ><span slot="prefix">Prefix</span
8
8
  ><span data-content>Tag</span></glide-core-tag
9
9
  >`);
10
- const iconButton = element.shadowRoot?.querySelector('button');
10
+ const iconButton = component.shadowRoot?.querySelector('[data-test="button"]');
11
11
  setTimeout(() => {
12
12
  iconButton?.click();
13
13
  });
14
- const event = await oneEvent(element, 'remove');
14
+ const event = await oneEvent(component, 'remove');
15
15
  expect(event?.type).to.be.equal('remove');
16
16
  });
@@ -2,10 +2,10 @@ import { expect, fixture, html } from '@open-wc/testing';
2
2
  import GlideCoreTag from './tag.js';
3
3
  GlideCoreTag.shadowRootOptions.mode = 'open';
4
4
  it('calling `focus()` focuses the button', async () => {
5
- const element = await fixture(html `<glide-core-tag removable-label="Removable Label"
5
+ const component = await fixture(html `<glide-core-tag removable-label="Removable Label"
6
6
  >Tag</glide-core-tag
7
7
  >`);
8
- element.focus();
9
- const button = element.shadowRoot?.querySelector('[data-test="button"]');
10
- expect(element.shadowRoot?.activeElement).to.equal(button);
8
+ component.focus();
9
+ const button = component.shadowRoot?.querySelector('[data-test="button"]');
10
+ expect(component.shadowRoot?.activeElement).to.equal(button);
11
11
  });
@@ -6,10 +6,11 @@ declare global {
6
6
  }
7
7
  }
8
8
  /**
9
- * @description A textarea with a label and optional description and toolip. Participates in forms and validation via `FormData` and various methods.
9
+ * @description A text area with a label and optional description and tooltip. Participates in forms and validation via `FormData` and various methods.
10
10
  *
11
- * @event change - (same as native textarea's `change` event)
12
- * @event input - (same as native textarea's `input` event)
11
+ * @event change - `(event: Event) => void`
12
+ * @event input - `(event: Event) => void`
13
+ * @event invalid - `(event: Event) => void`
13
14
  *
14
15
  * @slot tooltip - Content for the tooltip.
15
16
  * @slot description - Additional information or context.
@@ -18,7 +19,7 @@ export default class GlideCoreTextarea extends LitElement {
18
19
  #private;
19
20
  static formAssociated: boolean;
20
21
  static shadowRootOptions: ShadowRootInit;
21
- static styles: import("lit").CSSResult;
22
+ static styles: import("lit").CSSResult[];
22
23
  value: string;
23
24
  label?: string;
24
25
  hideLabel?: boolean | undefined;