@crowdstrike/glide-core 0.5.2 → 0.6.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/README.md +11 -1
- package/dist/accordion.styles.js +1 -0
- package/dist/button-group.button.js +1 -1
- package/dist/button-group.button.styles.js +2 -1
- package/dist/button.d.ts +3 -2
- package/dist/button.js +1 -1
- package/dist/button.styles.js +1 -1
- package/dist/button.test.basics.js +6 -0
- package/dist/checkbox.js +1 -1
- package/dist/checkbox.styles.js +4 -1
- package/dist/drawer.js +1 -1
- package/dist/drawer.styles.js +1 -5
- package/dist/drawer.test.floating-components.d.ts +1 -0
- package/dist/drawer.test.floating-components.js +51 -0
- package/dist/dropdown.js +1 -1
- package/dist/dropdown.option.js +1 -1
- package/dist/dropdown.option.test.interactions.multiple.js +1 -6
- package/dist/dropdown.styles.js +1 -0
- package/dist/dropdown.test.focus.js +11 -1
- package/dist/dropdown.test.interactions.filterable.js +64 -0
- package/dist/icon-button.d.ts +3 -2
- package/dist/icon-button.js +1 -1
- package/dist/icon-button.styles.js +9 -9
- package/dist/icon-button.test.basics.js +13 -6
- package/dist/input.js +1 -1
- package/dist/input.styles.js +1 -0
- package/dist/label.js +1 -1
- package/dist/label.styles.js +11 -13
- package/dist/library/localize.d.ts +17 -0
- package/dist/library/localize.js +1 -0
- package/dist/library/set-containing-block.d.ts +15 -0
- package/dist/library/set-containing-block.js +1 -0
- package/dist/menu.button.js +1 -1
- package/dist/menu.d.ts +5 -4
- package/dist/menu.js +1 -1
- package/dist/menu.link.js +1 -1
- package/dist/menu.options.d.ts +22 -0
- package/dist/menu.options.js +1 -0
- package/dist/menu.options.styles.d.ts +2 -0
- package/dist/menu.options.styles.js +33 -0
- package/dist/menu.options.test.basics.d.ts +2 -0
- package/dist/menu.options.test.basics.js +43 -0
- package/dist/menu.stories.d.ts +1 -0
- package/dist/menu.styles.js +3 -27
- package/dist/menu.test.basics.d.ts +1 -0
- package/dist/menu.test.basics.js +67 -45
- package/dist/menu.test.focus.js +34 -16
- package/dist/menu.test.interactions.d.ts +1 -0
- package/dist/menu.test.interactions.js +315 -173
- package/dist/modal.js +1 -1
- package/dist/modal.styles.js +1 -4
- package/dist/modal.tertiary-icon.d.ts +1 -0
- package/dist/modal.tertiary-icon.js +1 -1
- package/dist/modal.test.floating-components.d.ts +1 -0
- package/dist/modal.test.floating-components.js +62 -0
- package/dist/radio-group.js +1 -1
- package/dist/radio-group.styles.js +18 -22
- package/dist/radio.styles.js +11 -28
- package/dist/split-button.d.ts +3 -0
- package/dist/split-button.js +1 -1
- package/dist/split-button.styles.js +0 -1
- package/dist/split-button.test.basics.js +16 -1
- package/dist/split-container.d.ts +1 -0
- package/dist/split-container.js +1 -1
- package/dist/split-container.styles.js +2 -0
- package/dist/split-container.test.basics.js +11 -16
- package/dist/styles/focus-outline.js +1 -1
- package/dist/styles/variables.css +1 -1
- package/dist/tab.js +1 -1
- package/dist/tab.styles.js +79 -54
- package/dist/tag.js +1 -1
- package/dist/tag.styles.js +1 -0
- package/dist/tag.test.basics.js +1 -1
- package/dist/tag.test.translations.d.ts +1 -0
- package/dist/tag.test.translations.js +25 -0
- package/dist/textarea.styles.js +2 -1
- package/dist/toasts.js +1 -1
- package/dist/toasts.toast.js +1 -1
- package/dist/toggle.js +1 -1
- package/dist/toggle.test.basics.js +4 -0
- package/dist/toggle.test.states.js +8 -0
- package/dist/tooltip.d.ts +2 -0
- package/dist/tooltip.js +1 -1
- package/dist/tooltip.styles.js +2 -0
- package/dist/translations/en.d.ts +3 -0
- package/dist/translations/en.js +1 -0
- package/dist/translations/fr.d.ts +3 -0
- package/dist/translations/fr.js +1 -0
- package/dist/translations/ja.d.ts +3 -0
- package/dist/translations/ja.js +1 -0
- package/dist/tree.d.ts +1 -0
- package/dist/tree.item.d.ts +3 -1
- package/dist/tree.item.js +1 -1
- package/dist/tree.item.menu.d.ts +2 -0
- package/dist/tree.item.menu.js +1 -1
- package/dist/tree.item.menu.test.basics.js +6 -7
- package/dist/tree.item.styles.js +22 -7
- package/dist/tree.js +1 -1
- package/dist/tree.stories.d.ts +1 -0
- package/package.json +19 -13
@@ -1,4 +1,5 @@
|
|
1
1
|
import './menu.link.js';
|
2
|
+
import './menu.options.js';
|
2
3
|
import { elementUpdated, expect, fixture, html } from '@open-wc/testing';
|
3
4
|
import { sendKeys } from '@web/test-runner-commands';
|
4
5
|
import GlideCoreMenu from './menu.js';
|
@@ -6,138 +7,179 @@ GlideCoreMenu.shadowRootOptions.mode = 'open';
|
|
6
7
|
it('opens when clicked', async () => {
|
7
8
|
const component = await fixture(html `<glide-core-menu>
|
8
9
|
<button slot="target">Target</button>
|
9
|
-
|
10
|
+
|
11
|
+
<glide-core-menu-options>
|
12
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
13
|
+
</glide-core-menu-options>
|
10
14
|
</glide-core-menu>`);
|
11
15
|
component.querySelector('button')?.click();
|
12
16
|
await elementUpdated(component);
|
13
|
-
const
|
17
|
+
const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
|
18
|
+
const target = component.querySelector('button');
|
14
19
|
expect(component.open).to.be.true;
|
15
|
-
expect(
|
20
|
+
expect(defaultSlot?.checkVisibility({ checkVisibilityCSS: true })).to.be.true;
|
21
|
+
expect(target?.ariaExpanded).to.equal('true');
|
16
22
|
});
|
17
23
|
it('does not open when clicked when its target is `disabled`', async () => {
|
18
24
|
const component = await fixture(html `<glide-core-menu>
|
19
25
|
<button slot="target" disabled>Target</button>
|
20
|
-
|
26
|
+
|
27
|
+
<glide-core-menu-options>
|
28
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
29
|
+
</glide-core-menu-options>
|
21
30
|
</glide-core-menu>`);
|
22
31
|
component.querySelector('button')?.click();
|
23
|
-
const
|
32
|
+
const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
|
33
|
+
const options = component.querySelector('glide-core-menu-options');
|
24
34
|
const target = component.querySelector('button');
|
25
35
|
expect(component.open).to.be.false;
|
26
|
-
expect(
|
27
|
-
expect(
|
36
|
+
expect(defaultSlot?.checkVisibility({ checkVisibilityCSS: true })).not.ok;
|
37
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal('');
|
28
38
|
expect(target?.ariaExpanded).to.equal('false');
|
29
39
|
});
|
30
40
|
it('does not open when clicked when its target is `aria-disabled`', async () => {
|
31
41
|
const component = await fixture(html `<glide-core-menu>
|
32
42
|
<button aria-disabled="true" slot="target">Target</button>
|
33
|
-
|
43
|
+
|
44
|
+
<glide-core-menu-options>
|
45
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
46
|
+
</glide-core-menu-options>
|
34
47
|
</glide-core-menu>`);
|
35
48
|
component.querySelector('button')?.click();
|
36
|
-
const
|
49
|
+
const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
|
50
|
+
const options = component.querySelector('glide-core-menu-options');
|
37
51
|
const target = component.querySelector('button');
|
38
52
|
expect(component.open).to.be.false;
|
39
|
-
expect(
|
40
|
-
expect(
|
53
|
+
expect(defaultSlot?.checkVisibility({ checkVisibilityCSS: true })).not.ok;
|
54
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal('');
|
41
55
|
expect(target?.ariaExpanded).to.equal('false');
|
42
56
|
});
|
43
57
|
it('opens on Enter', async () => {
|
44
58
|
const component = await fixture(html `<glide-core-menu>
|
45
59
|
<button slot="target">Target</button>
|
46
|
-
|
60
|
+
|
61
|
+
<glide-core-menu-options>
|
62
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
63
|
+
</glide-core-menu-options>
|
47
64
|
</glide-core-menu>`);
|
48
65
|
component.querySelector('button')?.focus();
|
49
66
|
await sendKeys({ press: 'Enter' });
|
50
|
-
const
|
67
|
+
const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
|
68
|
+
const options = component.querySelector('glide-core-menu-options');
|
51
69
|
const target = component.querySelector('button');
|
52
70
|
const link = component.querySelector('glide-core-menu-link');
|
53
71
|
expect(component.open).to.be.true;
|
54
|
-
expect(
|
55
|
-
expect(
|
72
|
+
expect(defaultSlot?.checkVisibility({ checkVisibilityCSS: true })).to.be.true;
|
73
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal(link?.id);
|
56
74
|
expect(target?.ariaExpanded).to.equal('true');
|
57
75
|
});
|
58
76
|
it('opens on ArrowUp', async () => {
|
59
77
|
const component = await fixture(html `<glide-core-menu>
|
60
78
|
<button slot="target">Target</button>
|
61
|
-
|
79
|
+
|
80
|
+
<glide-core-menu-options>
|
81
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
82
|
+
</glide-core-menu-options>
|
62
83
|
</glide-core-menu>`);
|
63
84
|
component.querySelector('button')?.focus();
|
64
85
|
await sendKeys({ press: 'ArrowUp' });
|
65
|
-
const
|
86
|
+
const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
|
87
|
+
const options = component.querySelector('glide-core-menu-options');
|
66
88
|
const target = component.querySelector('button');
|
67
89
|
const link = component.querySelector('glide-core-menu-link');
|
68
90
|
expect(component.open).to.be.true;
|
69
|
-
expect(
|
70
|
-
expect(
|
91
|
+
expect(defaultSlot?.checkVisibility({ checkVisibilityCSS: true })).to.be.true;
|
92
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal(link?.id);
|
71
93
|
expect(target?.ariaExpanded).to.equal('true');
|
72
94
|
});
|
73
95
|
it('opens on ArrowDown', async () => {
|
74
96
|
const component = await fixture(html `<glide-core-menu>
|
75
97
|
<button slot="target">Target</button>
|
76
|
-
|
98
|
+
|
99
|
+
<glide-core-menu-options>
|
100
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
101
|
+
</glide-core-menu-options>
|
77
102
|
</glide-core-menu>`);
|
78
103
|
component.querySelector('button')?.focus();
|
79
104
|
await sendKeys({ press: 'ArrowDown' });
|
80
|
-
const
|
105
|
+
const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
|
106
|
+
const options = component.querySelector('glide-core-menu-options');
|
81
107
|
const target = component.querySelector('button');
|
82
108
|
const link = component.querySelector('glide-core-menu-link');
|
83
109
|
expect(component.open).to.be.true;
|
84
|
-
expect(
|
85
|
-
expect(
|
110
|
+
expect(defaultSlot?.checkVisibility({ checkVisibilityCSS: true })).to.be.true;
|
111
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal(link?.id);
|
86
112
|
expect(target?.ariaExpanded).to.equal('true');
|
87
113
|
});
|
88
114
|
it('opens on Space', async () => {
|
89
115
|
const component = await fixture(html `<glide-core-menu>
|
90
116
|
<button slot="target">Target</button>
|
91
|
-
|
117
|
+
|
118
|
+
<glide-core-menu-options>
|
119
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
120
|
+
</glide-core-menu-options>
|
92
121
|
</glide-core-menu>`);
|
93
122
|
component.querySelector('button')?.focus();
|
94
123
|
await sendKeys({ press: ' ' });
|
95
|
-
const
|
124
|
+
const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
|
125
|
+
const options = component.querySelector('glide-core-menu-options');
|
96
126
|
const target = component.querySelector('button');
|
97
127
|
const link = component.querySelector('glide-core-menu-link');
|
98
128
|
expect(component.open).to.be.true;
|
99
|
-
expect(
|
100
|
-
expect(
|
129
|
+
expect(defaultSlot?.checkVisibility({ checkVisibilityCSS: true })).to.be.true;
|
130
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal(link?.id);
|
101
131
|
expect(target?.ariaExpanded).to.equal('true');
|
102
132
|
});
|
103
133
|
it('opens when opened programmatically', async () => {
|
104
134
|
const component = await fixture(html `<glide-core-menu>
|
105
135
|
<button slot="target">Target</button>
|
106
|
-
|
136
|
+
|
137
|
+
<glide-core-menu-options>
|
138
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
139
|
+
</glide-core-menu-options>
|
107
140
|
</glide-core-menu>`);
|
108
141
|
component.open = true;
|
109
142
|
await elementUpdated(component);
|
110
|
-
const
|
143
|
+
const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
|
144
|
+
const options = component.querySelector('glide-core-menu-options');
|
111
145
|
const target = component.querySelector('button');
|
112
146
|
const link = component.querySelector('glide-core-menu-link');
|
113
|
-
expect(
|
114
|
-
expect(
|
147
|
+
expect(defaultSlot?.checkVisibility({ checkVisibilityCSS: true })).to.be.true;
|
148
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal(link?.id);
|
115
149
|
expect(target?.ariaExpanded).to.equal('true');
|
116
150
|
});
|
117
151
|
it('does not open when opened programmatically and its target is `disabled`', async () => {
|
118
152
|
const component = await fixture(html `<glide-core-menu>
|
119
153
|
<button slot="target" disabled>Target</button>
|
120
|
-
|
154
|
+
|
155
|
+
<glide-core-menu-options>
|
156
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
157
|
+
</glide-core-menu-options>
|
121
158
|
</glide-core-menu>`);
|
122
159
|
component.open = true;
|
123
160
|
await elementUpdated(component);
|
124
|
-
const
|
161
|
+
const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
|
162
|
+
const options = component.querySelector('glide-core-menu-options');
|
125
163
|
const target = component.querySelector('button');
|
126
|
-
expect(
|
127
|
-
expect(
|
164
|
+
expect(defaultSlot?.checkVisibility({ checkVisibilityCSS: true })).not.ok;
|
165
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal('');
|
128
166
|
expect(target?.ariaExpanded).to.equal('false');
|
129
167
|
});
|
130
168
|
it('does not open when opened programmatically and its target is `aria-disabled`', async () => {
|
131
169
|
const component = await fixture(html `<glide-core-menu>
|
132
170
|
<button aria-disabled="true" slot="target">Target</button>
|
133
|
-
|
171
|
+
|
172
|
+
<glide-core-menu-options>
|
173
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
174
|
+
</glide-core-menu-options>
|
134
175
|
</glide-core-menu>`);
|
135
176
|
component.open = true;
|
136
177
|
await elementUpdated(component);
|
137
|
-
const
|
178
|
+
const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
|
179
|
+
const options = component.querySelector('glide-core-menu-options');
|
138
180
|
const target = component.querySelector('button');
|
139
|
-
expect(
|
140
|
-
expect(
|
181
|
+
expect(defaultSlot?.checkVisibility({ checkVisibilityCSS: true })).not.ok;
|
182
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal('');
|
141
183
|
expect(target?.ariaExpanded).to.equal('false');
|
142
184
|
});
|
143
185
|
// See the `document` click listener comment in `menu.ts` for an explanation.
|
@@ -145,79 +187,116 @@ it('opens when opened programmatically via the click handler of another element'
|
|
145
187
|
const div = document.createElement('div');
|
146
188
|
const component = await fixture(html `<glide-core-menu>
|
147
189
|
<button slot="target">Target</button>
|
148
|
-
|
190
|
+
|
191
|
+
<glide-core-menu-options>
|
192
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
193
|
+
</glide-core-menu-options>
|
149
194
|
</glide-core-menu>`, { parentNode: div });
|
150
195
|
const anotherElement = document.createElement('button');
|
151
196
|
anotherElement.addEventListener('click', () => (component.open = true));
|
152
197
|
div.append(anotherElement);
|
153
198
|
anotherElement.click();
|
154
199
|
await elementUpdated(component);
|
155
|
-
const
|
200
|
+
const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
|
201
|
+
const options = component.querySelector('glide-core-menu-options');
|
156
202
|
const target = component.querySelector('button');
|
157
203
|
const link = component.querySelector('glide-core-menu-link');
|
158
204
|
expect(component.open).to.be.true;
|
159
|
-
expect(
|
160
|
-
expect(
|
205
|
+
expect(defaultSlot?.checkVisibility({ checkVisibilityCSS: true })).to.be.true;
|
206
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal(link?.id);
|
161
207
|
expect(target?.ariaExpanded).to.equal('true');
|
162
208
|
});
|
209
|
+
it('sets `privateSize` on the options component when `size` is changed programmatically', async () => {
|
210
|
+
const component = await fixture(html `<glide-core-menu>
|
211
|
+
<button slot="target">Target</button>
|
212
|
+
|
213
|
+
<glide-core-menu-options>
|
214
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
215
|
+
</glide-core-menu-options>
|
216
|
+
</glide-core-menu>`);
|
217
|
+
component.size = 'small';
|
218
|
+
const options = component.querySelector('glide-core-menu-options');
|
219
|
+
expect(options?.privateSize).to.equal('small');
|
220
|
+
});
|
163
221
|
it('closes when clicked', async () => {
|
164
222
|
const component = await fixture(html `<glide-core-menu open>
|
165
223
|
<button slot="target">Target</button>
|
166
|
-
|
224
|
+
|
225
|
+
<glide-core-menu-options>
|
226
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
227
|
+
</glide-core-menu-options>
|
167
228
|
</glide-core-menu>`);
|
168
229
|
component.querySelector('button')?.click();
|
169
230
|
await elementUpdated(component);
|
170
|
-
const
|
231
|
+
const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
|
232
|
+
const options = component.querySelector('glide-core-menu-options');
|
171
233
|
const target = component.querySelector('button');
|
172
234
|
expect(component.open).to.be.false;
|
173
|
-
expect(
|
174
|
-
expect(
|
235
|
+
expect(defaultSlot?.checkVisibility({ checkVisibilityCSS: true })).not.ok;
|
236
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal('');
|
175
237
|
expect(target?.ariaExpanded).to.equal('false');
|
176
238
|
});
|
177
239
|
it('closes when something outside of it is clicked', async () => {
|
178
240
|
const component = await fixture(html `<glide-core-menu>
|
179
241
|
<button slot="target">Target</button>
|
180
|
-
|
242
|
+
|
243
|
+
<glide-core-menu-options>
|
244
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
245
|
+
</glide-core-menu-options>
|
181
246
|
</glide-core-menu>`);
|
182
247
|
component.querySelector('button')?.click();
|
183
248
|
document.body.click();
|
184
|
-
const
|
249
|
+
const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
|
250
|
+
const options = component.querySelector('glide-core-menu-options');
|
185
251
|
const target = component.querySelector('button');
|
186
252
|
expect(component.open).to.be.false;
|
187
|
-
expect(
|
253
|
+
expect(defaultSlot?.checkVisibility({ checkVisibilityCSS: true })).not.ok;
|
254
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal('');
|
188
255
|
expect(target?.ariaExpanded).to.equal('false');
|
189
256
|
});
|
190
257
|
it('closes on Escape when the button has focus', async () => {
|
191
258
|
const component = await fixture(html `<glide-core-menu open>
|
192
259
|
<button slot="target">Target</button>
|
193
|
-
|
260
|
+
|
261
|
+
<glide-core-menu-options>
|
262
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
263
|
+
</glide-core-menu-options>
|
194
264
|
</glide-core-menu>`);
|
195
265
|
component.querySelector('button')?.click();
|
196
266
|
await sendKeys({ press: 'Escape' });
|
197
|
-
const
|
267
|
+
const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
|
268
|
+
const options = component.querySelector('glide-core-menu-options');
|
198
269
|
const target = component.querySelector('button');
|
199
270
|
expect(component.open).to.be.false;
|
200
|
-
expect(
|
271
|
+
expect(defaultSlot?.checkVisibility({ checkVisibilityCSS: true })).not.ok;
|
272
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal('');
|
201
273
|
expect(target?.ariaExpanded).to.equal('false');
|
202
274
|
});
|
203
275
|
it('closes when an option is selected via click', async () => {
|
204
276
|
const component = await fixture(html `<glide-core-menu open>
|
205
277
|
<button slot="target">Target</button>
|
206
|
-
|
278
|
+
|
279
|
+
<glide-core-menu-options>
|
280
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
281
|
+
</glide-core-menu-options>
|
207
282
|
</glide-core-menu>`);
|
208
283
|
component.querySelector('glide-core-menu-link')?.click();
|
209
284
|
await elementUpdated(component);
|
210
|
-
const
|
285
|
+
const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
|
286
|
+
const options = component.querySelector('glide-core-menu-options');
|
211
287
|
const target = component.querySelector('button');
|
212
288
|
expect(component.open).to.be.false;
|
213
|
-
expect(
|
214
|
-
expect(
|
289
|
+
expect(defaultSlot?.checkVisibility({ checkVisibilityCSS: true })).not.ok;
|
290
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal('');
|
215
291
|
expect(target?.ariaExpanded).to.equal('false');
|
216
292
|
});
|
217
293
|
it('closes when an option is selected via Enter', async () => {
|
218
294
|
const component = await fixture(html `<glide-core-menu open>
|
219
295
|
<button slot="target">Target</button>
|
220
|
-
|
296
|
+
|
297
|
+
<glide-core-menu-options>
|
298
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
299
|
+
</glide-core-menu-options>
|
221
300
|
</glide-core-menu>`);
|
222
301
|
component.focus();
|
223
302
|
component
|
@@ -225,280 +304,340 @@ it('closes when an option is selected via Enter', async () => {
|
|
225
304
|
?.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
|
226
305
|
await sendKeys({ press: 'Enter' });
|
227
306
|
await elementUpdated(component);
|
228
|
-
const
|
307
|
+
const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
|
308
|
+
const options = component.querySelector('glide-core-menu-options');
|
229
309
|
const target = component.querySelector('button');
|
230
310
|
expect(component.open).to.be.false;
|
231
|
-
expect(
|
311
|
+
expect(defaultSlot?.checkVisibility({ checkVisibilityCSS: true })).not.ok;
|
312
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal('');
|
232
313
|
expect(target?.ariaExpanded).to.equal('false');
|
233
314
|
});
|
234
315
|
it('closes when an option is selected via Space', async () => {
|
235
316
|
const component = await fixture(html `<glide-core-menu open>
|
236
317
|
<button slot="target">Target</button>
|
237
|
-
|
318
|
+
|
319
|
+
<glide-core-menu-options>
|
320
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
321
|
+
</glide-core-menu-options>
|
238
322
|
</glide-core-menu>`);
|
239
323
|
component.focus();
|
240
324
|
await sendKeys({ press: ' ' });
|
241
|
-
const
|
325
|
+
const defaultSlot = component?.shadowRoot?.querySelector('slot:not([name])');
|
326
|
+
const options = component.querySelector('glide-core-menu-options');
|
242
327
|
const target = component.querySelector('button');
|
243
328
|
expect(component.open).to.be.false;
|
244
|
-
expect(
|
329
|
+
expect(defaultSlot?.checkVisibility({ checkVisibilityCSS: true })).not.ok;
|
330
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal('');
|
245
331
|
expect(target?.ariaExpanded).to.equal('false');
|
246
332
|
});
|
247
333
|
it('activates the first menu link by default', async () => {
|
248
334
|
const component = await fixture(html `
|
249
335
|
<glide-core-menu>
|
250
336
|
<button slot="target">Target</button>
|
251
|
-
|
252
|
-
<glide-core-menu-
|
337
|
+
|
338
|
+
<glide-core-menu-options>
|
339
|
+
<glide-core-menu-link label="One"></glide-core-menu-link>
|
340
|
+
<glide-core-menu-link label="Two"></glide-core-menu-link>
|
341
|
+
</glide-core-menu-options>
|
253
342
|
</glide-core-menu>
|
254
343
|
`);
|
255
344
|
component.querySelector('button')?.click();
|
256
345
|
await elementUpdated(component);
|
257
|
-
const
|
258
|
-
const
|
259
|
-
expect(
|
260
|
-
expect(
|
261
|
-
expect(
|
346
|
+
const links = component.querySelectorAll('glide-core-menu-link');
|
347
|
+
const options = component.querySelector('glide-core-menu-options');
|
348
|
+
expect(links[0].privateActive).to.be.true;
|
349
|
+
expect(links[1].privateActive).to.be.false;
|
350
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal(links[0]?.id);
|
262
351
|
});
|
263
352
|
it('activates the first menu button by default', async () => {
|
264
353
|
const component = await fixture(html `
|
265
354
|
<glide-core-menu>
|
266
355
|
<button slot="target">Target</button>
|
267
|
-
|
268
|
-
<glide-core-menu-
|
356
|
+
|
357
|
+
<glide-core-menu-options>
|
358
|
+
<glide-core-menu-button label="One"></glide-core-menu-button>
|
359
|
+
<glide-core-menu-button label="Two"></glide-core-menu-button>
|
360
|
+
</glide-core-menu-options>
|
269
361
|
</glide-core-menu>
|
270
362
|
`);
|
271
363
|
component.querySelector('button')?.click();
|
272
364
|
await elementUpdated(component);
|
273
|
-
const
|
274
|
-
const
|
275
|
-
expect(
|
276
|
-
expect(
|
277
|
-
expect(
|
365
|
+
const buttons = component.querySelectorAll('glide-core-menu-button');
|
366
|
+
const options = component.querySelector('glide-core-menu-options');
|
367
|
+
expect(buttons[0].privateActive).to.be.true;
|
368
|
+
expect(buttons[1].privateActive).to.be.false;
|
369
|
+
expect(options?.getAttribute('aria-activedescendant')).equal(buttons[0]?.id);
|
278
370
|
});
|
279
371
|
it('activates a menu link on "mouseover"', async () => {
|
280
372
|
const component = await fixture(html `
|
281
373
|
<glide-core-menu open>
|
282
374
|
<button slot="target">Target</button>
|
283
|
-
|
284
|
-
<glide-core-menu-
|
375
|
+
|
376
|
+
<glide-core-menu-options>
|
377
|
+
<glide-core-menu-link label="One"></glide-core-menu-link>
|
378
|
+
<glide-core-menu-link label="Two"></glide-core-menu-link>
|
379
|
+
</glide-core-menu-options>
|
285
380
|
</glide-core-menu>
|
286
381
|
`);
|
287
|
-
const
|
288
|
-
const
|
289
|
-
|
382
|
+
const links = component.querySelectorAll('glide-core-menu-link');
|
383
|
+
const options = component.querySelector('glide-core-menu-options');
|
384
|
+
links[1].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
|
290
385
|
await elementUpdated(component);
|
291
|
-
expect(
|
292
|
-
expect(
|
293
|
-
expect(
|
386
|
+
expect(links[0].privateActive).to.be.false;
|
387
|
+
expect(links[1].privateActive).to.be.true;
|
388
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal(links[1].id);
|
294
389
|
});
|
295
390
|
it('activates a menu button on "mouseover"', async () => {
|
296
391
|
const component = await fixture(html `
|
297
392
|
<glide-core-menu open>
|
298
393
|
<button slot="target">Target</button>
|
299
|
-
|
300
|
-
<glide-core-menu-
|
394
|
+
|
395
|
+
<glide-core-menu-options>
|
396
|
+
<glide-core-menu-button label="One"></glide-core-menu-button>
|
397
|
+
<glide-core-menu-button label="Two"></glide-core-menu-button>
|
398
|
+
</glide-core-menu-options>
|
301
399
|
</glide-core-menu>
|
302
400
|
`);
|
303
|
-
const
|
304
|
-
const
|
305
|
-
|
401
|
+
const buttons = component.querySelectorAll('glide-core-menu-button');
|
402
|
+
const options = component.querySelector('glide-core-menu-options');
|
403
|
+
buttons[1].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
|
306
404
|
await elementUpdated(component);
|
307
|
-
expect(
|
308
|
-
expect(
|
309
|
-
expect(
|
405
|
+
expect(buttons[0].privateActive).to.be.false;
|
406
|
+
expect(buttons[1].privateActive).to.be.true;
|
407
|
+
expect(options?.getAttribute('aria-activedescendant')).equal(buttons[1].id);
|
310
408
|
});
|
311
409
|
it('activates the next option on ArrowDown', async () => {
|
312
410
|
const component = await fixture(html `
|
313
411
|
<glide-core-menu>
|
314
412
|
<button slot="target">Target</button>
|
315
|
-
|
316
|
-
<glide-core-menu-
|
317
|
-
|
413
|
+
|
414
|
+
<glide-core-menu-options>
|
415
|
+
<glide-core-menu-link label="One"></glide-core-menu-link>
|
416
|
+
<glide-core-menu-link label="Two"></glide-core-menu-link>
|
417
|
+
<glide-core-menu-link label="Three"></glide-core-menu-link>
|
418
|
+
</glide-core-menu-options>
|
318
419
|
</glide-core-menu>
|
319
420
|
`);
|
320
421
|
component.querySelector('button')?.click();
|
321
422
|
component.focus();
|
322
|
-
const
|
323
|
-
const
|
324
|
-
|
423
|
+
const links = component.querySelectorAll('glide-core-menu-link');
|
424
|
+
const options = component.querySelector('glide-core-menu-options');
|
425
|
+
links[1].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
|
325
426
|
await sendKeys({ press: 'ArrowDown' });
|
326
|
-
expect(
|
327
|
-
expect(
|
328
|
-
expect(
|
329
|
-
expect(
|
427
|
+
expect(links[0].privateActive).to.be.false;
|
428
|
+
expect(links[1].privateActive).to.be.false;
|
429
|
+
expect(links[2].privateActive).to.be.true;
|
430
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal(links[2].id);
|
330
431
|
});
|
331
432
|
it('activates the previous option on ArrowUp', async () => {
|
332
433
|
const component = await fixture(html `
|
333
434
|
<glide-core-menu>
|
334
435
|
<button slot="target">Target</button>
|
335
|
-
|
336
|
-
<glide-core-menu-
|
436
|
+
|
437
|
+
<glide-core-menu-options>
|
438
|
+
<glide-core-menu-link label="One"></glide-core-menu-link>
|
439
|
+
<glide-core-menu-link label="Two"></glide-core-menu-link>
|
440
|
+
</glide-core-menu-options>
|
337
441
|
</glide-core-menu>
|
338
442
|
`);
|
339
443
|
component.querySelector('button')?.click();
|
340
444
|
component.focus();
|
341
|
-
const
|
342
|
-
const
|
343
|
-
|
445
|
+
const links = component.querySelectorAll('glide-core-menu-link');
|
446
|
+
const options = component.querySelector('glide-core-menu-options');
|
447
|
+
links[1].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
|
344
448
|
await sendKeys({ press: 'ArrowUp' });
|
345
|
-
expect(
|
346
|
-
expect(
|
347
|
-
expect(
|
449
|
+
expect(links[0].privateActive).to.be.true;
|
450
|
+
expect(links[1].privateActive).to.be.false;
|
451
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal(links[0].id);
|
348
452
|
});
|
349
453
|
it('activates the first option on Home', async () => {
|
350
454
|
const component = await fixture(html `
|
351
455
|
<glide-core-menu>
|
352
456
|
<button slot="target">Target</button>
|
353
|
-
|
354
|
-
<glide-core-menu-
|
457
|
+
|
458
|
+
<glide-core-menu-options>
|
459
|
+
<glide-core-menu-link label="One"></glide-core-menu-link>
|
460
|
+
<glide-core-menu-link label="Two"></glide-core-menu-link>
|
461
|
+
</glide-core-menu-options>
|
355
462
|
</glide-core-menu>
|
356
463
|
`);
|
357
464
|
component.querySelector('button')?.click();
|
358
465
|
component.focus();
|
359
|
-
const
|
360
|
-
const
|
361
|
-
|
466
|
+
const links = component.querySelectorAll('glide-core-menu-link');
|
467
|
+
const options = component.querySelector('glide-core-menu-options');
|
468
|
+
links[1].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
|
362
469
|
await sendKeys({ press: 'Home' });
|
363
|
-
expect(
|
364
|
-
expect(
|
365
|
-
expect(
|
470
|
+
expect(links[0].privateActive).to.be.true;
|
471
|
+
expect(links[1].privateActive).to.be.false;
|
472
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal(links[0].id);
|
366
473
|
});
|
367
474
|
it('activates the first option on PageUp', async () => {
|
368
475
|
const component = await fixture(html `
|
369
476
|
<glide-core-menu>
|
370
477
|
<button slot="target">Target</button>
|
371
|
-
|
372
|
-
<glide-core-menu-
|
478
|
+
|
479
|
+
<glide-core-menu-options>
|
480
|
+
<glide-core-menu-link label="One"></glide-core-menu-link>
|
481
|
+
<glide-core-menu-link label="Two"></glide-core-menu-link>
|
482
|
+
</glide-core-menu-options>
|
373
483
|
</glide-core-menu>
|
374
484
|
`);
|
375
485
|
component.querySelector('button')?.click();
|
376
486
|
component.focus();
|
377
|
-
const
|
378
|
-
const
|
379
|
-
|
487
|
+
const links = component.querySelectorAll('glide-core-menu-link');
|
488
|
+
const options = component.querySelector('glide-core-menu-options');
|
489
|
+
links[1].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
|
380
490
|
await sendKeys({ press: 'PageUp' });
|
381
|
-
expect(
|
382
|
-
expect(
|
383
|
-
expect(
|
491
|
+
expect(links[0].privateActive).to.be.true;
|
492
|
+
expect(links[1].privateActive).to.be.false;
|
493
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal(links[0].id);
|
384
494
|
});
|
385
495
|
it('activates the first option on ArrowUp + Meta', async () => {
|
386
496
|
const component = await fixture(html `
|
387
497
|
<glide-core-menu>
|
388
498
|
<button slot="target">Target</button>
|
389
|
-
|
390
|
-
<glide-core-menu-
|
499
|
+
|
500
|
+
<glide-core-menu-options>
|
501
|
+
<glide-core-menu-link label="One"></glide-core-menu-link>
|
502
|
+
<glide-core-menu-link label="Two"></glide-core-menu-link>
|
503
|
+
</glide-core-menu-options>
|
391
504
|
</glide-core-menu>
|
392
505
|
`);
|
393
506
|
component.querySelector('button')?.click();
|
394
507
|
component.focus();
|
395
|
-
const
|
396
|
-
const
|
397
|
-
|
508
|
+
const links = component.querySelectorAll('glide-core-menu-link');
|
509
|
+
const options = component.querySelector('glide-core-menu-options');
|
510
|
+
links[1].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
|
398
511
|
await sendKeys({ down: 'Meta' });
|
399
512
|
await sendKeys({ press: 'ArrowUp' });
|
400
|
-
expect(
|
401
|
-
expect(
|
402
|
-
expect(
|
513
|
+
expect(links[0].privateActive).to.be.true;
|
514
|
+
expect(links[1].privateActive).to.be.false;
|
515
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal(links[0].id);
|
403
516
|
});
|
404
517
|
it('activates the last option on End', async () => {
|
405
518
|
const component = await fixture(html `
|
406
519
|
<glide-core-menu>
|
407
520
|
<button slot="target">Target</button>
|
408
|
-
|
409
|
-
<glide-core-menu-
|
521
|
+
|
522
|
+
<glide-core-menu-options>
|
523
|
+
<glide-core-menu-link label="One"></glide-core-menu-link>
|
524
|
+
<glide-core-menu-link label="Two"></glide-core-menu-link>
|
525
|
+
</glide-core-menu-options>
|
410
526
|
</glide-core-menu>
|
411
527
|
`);
|
412
528
|
component.querySelector('button')?.click();
|
413
529
|
component.focus();
|
414
530
|
await sendKeys({ press: 'End' });
|
415
|
-
const
|
416
|
-
const
|
417
|
-
expect(
|
418
|
-
expect(
|
419
|
-
expect(
|
531
|
+
const links = component.querySelectorAll('glide-core-menu-link');
|
532
|
+
const options = component.querySelector('glide-core-menu-options');
|
533
|
+
expect(links[0].privateActive).to.be.false;
|
534
|
+
expect(links[1].privateActive).to.be.true;
|
535
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal(links[1].id);
|
420
536
|
});
|
421
537
|
it('activates the last option on PageDown', async () => {
|
422
538
|
const component = await fixture(html `
|
423
539
|
<glide-core-menu>
|
424
540
|
<button slot="target">Target</button>
|
425
|
-
|
426
|
-
<glide-core-menu-
|
541
|
+
|
542
|
+
<glide-core-menu-options>
|
543
|
+
<glide-core-menu-link label="One"></glide-core-menu-link>
|
544
|
+
<glide-core-menu-link label="Two"></glide-core-menu-link>
|
545
|
+
</glide-core-menu-options>
|
427
546
|
</glide-core-menu>
|
428
547
|
`);
|
429
548
|
component.querySelector('button')?.click();
|
430
549
|
component.focus();
|
431
|
-
const
|
432
|
-
const
|
433
|
-
|
550
|
+
const links = component.querySelectorAll('glide-core-menu-link');
|
551
|
+
const options = component.querySelector('glide-core-menu-options');
|
552
|
+
links[0].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
|
434
553
|
await sendKeys({ press: 'PageDown' });
|
435
|
-
expect(
|
436
|
-
expect(
|
437
|
-
expect(
|
554
|
+
expect(links[0].privateActive).to.be.false;
|
555
|
+
expect(links[1].privateActive).to.be.true;
|
556
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal(links[1].id);
|
438
557
|
});
|
439
558
|
it('activates the last option on Meta + ArrowDown', async () => {
|
440
559
|
const component = await fixture(html `
|
441
560
|
<glide-core-menu>
|
442
561
|
<button slot="target">Target</button>
|
443
|
-
|
444
|
-
<glide-core-menu-
|
562
|
+
|
563
|
+
<glide-core-menu-options>
|
564
|
+
<glide-core-menu-link label="One"></glide-core-menu-link>
|
565
|
+
<glide-core-menu-link label="Two"></glide-core-menu-link>
|
566
|
+
</glide-core-menu-options>
|
445
567
|
</glide-core-menu>
|
446
568
|
`);
|
447
569
|
component.querySelector('button')?.click();
|
448
570
|
component.focus();
|
449
|
-
const
|
450
|
-
const
|
451
|
-
|
571
|
+
const links = component.querySelectorAll('glide-core-menu-link');
|
572
|
+
const options = component.querySelector('glide-core-menu-options');
|
573
|
+
links[0].dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
|
452
574
|
await sendKeys({ down: 'Meta' });
|
453
575
|
await sendKeys({ press: 'ArrowDown' });
|
454
576
|
await sendKeys({ up: 'Meta' });
|
455
|
-
expect(
|
456
|
-
expect(
|
457
|
-
expect(
|
577
|
+
expect(links[0].privateActive).to.be.false;
|
578
|
+
expect(links[1].privateActive).to.be.true;
|
579
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal(links[1].id);
|
458
580
|
});
|
459
581
|
it('sets `aria-activedescendant` on open', async () => {
|
460
582
|
const component = await fixture(html `<glide-core-menu>
|
461
583
|
<button slot="target">Target</button>
|
462
|
-
|
584
|
+
|
585
|
+
<glide-core-menu-options>
|
586
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
587
|
+
</glide-core-menu-options>
|
463
588
|
</glide-core-menu>`);
|
464
589
|
component.querySelector('button')?.click();
|
465
590
|
await elementUpdated(component);
|
466
|
-
const
|
467
|
-
const
|
468
|
-
expect(
|
591
|
+
const link = component.querySelector('glide-core-menu-link');
|
592
|
+
const options = component.querySelector('glide-core-menu-options');
|
593
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal(link?.id);
|
469
594
|
});
|
470
595
|
it('sets `aria-activedescendant` on close', async () => {
|
471
596
|
const component = await fixture(html `<glide-core-menu open>
|
472
597
|
<button slot="target">Target</button>
|
473
|
-
|
598
|
+
|
599
|
+
<glide-core-menu-options>
|
600
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
601
|
+
</glide-core-menu-options>
|
474
602
|
</glide-core-menu>`);
|
475
603
|
component.querySelector('button')?.click();
|
476
604
|
await elementUpdated(component);
|
477
|
-
const
|
478
|
-
expect(
|
605
|
+
const options = component.querySelector('glide-core-menu-options');
|
606
|
+
expect(options?.getAttribute('aria-activedescendant')).to.equal('');
|
479
607
|
});
|
480
608
|
it('sets `aria-expanded` on open', async () => {
|
481
609
|
const component = await fixture(html `<glide-core-menu>
|
482
610
|
<button slot="target">Target</button>
|
483
|
-
|
611
|
+
|
612
|
+
<glide-core-menu-options>
|
613
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
614
|
+
</glide-core-menu-options>
|
484
615
|
</glide-core-menu>`);
|
485
616
|
component.querySelector('button')?.click();
|
486
|
-
|
617
|
+
const button = component.querySelector('button');
|
618
|
+
expect(button?.getAttribute('aria-expanded')).to.equal('true');
|
487
619
|
});
|
488
620
|
it('sets `aria-expanded` on close', async () => {
|
489
621
|
const component = await fixture(html `<glide-core-menu open>
|
490
622
|
<button slot="target">Target</button>
|
491
|
-
|
623
|
+
|
624
|
+
<glide-core-menu-options>
|
625
|
+
<glide-core-menu-link label="Link"></glide-core-menu-link>
|
626
|
+
</glide-core-menu-options>
|
492
627
|
</glide-core-menu>`);
|
493
628
|
component.querySelector('button')?.click();
|
494
|
-
|
629
|
+
const button = component.querySelector('button');
|
630
|
+
expect(button?.getAttribute('aria-expanded')).to.equal('false');
|
495
631
|
});
|
496
632
|
it('does not wrap on ArrowUp', async () => {
|
497
633
|
const component = await fixture(html `
|
498
634
|
<glide-core-menu>
|
499
635
|
<button slot="target">Target</button>
|
500
|
-
|
501
|
-
<glide-core-menu-
|
636
|
+
|
637
|
+
<glide-core-menu-options>
|
638
|
+
<glide-core-menu-link label="One"></glide-core-menu-link>
|
639
|
+
<glide-core-menu-link label="Two"></glide-core-menu-link>
|
640
|
+
</glide-core-menu-options>
|
502
641
|
</glide-core-menu>
|
503
642
|
`);
|
504
643
|
component.querySelector('button')?.click();
|
@@ -510,8 +649,11 @@ it('does not wrap on ArrowDown', async () => {
|
|
510
649
|
const component = await fixture(html `
|
511
650
|
<glide-core-menu>
|
512
651
|
<button slot="target">Target</button>
|
513
|
-
|
514
|
-
<glide-core-menu-
|
652
|
+
|
653
|
+
<glide-core-menu-options>
|
654
|
+
<glide-core-menu-link label="One"></glide-core-menu-link>
|
655
|
+
<glide-core-menu-link label="Two"></glide-core-menu-link>
|
656
|
+
</glide-core-menu-options>
|
515
657
|
</glide-core-menu>
|
516
658
|
`);
|
517
659
|
component.querySelector('button')?.click();
|