@spectrum-web-components/button 0.50.0-beta.7 → 0.50.0-beta.9

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 (56) hide show
  1. package/package.json +11 -10
  2. package/src/Button.d.ts +0 -5
  3. package/src/Button.dev.js +0 -19
  4. package/src/Button.dev.js.map +2 -2
  5. package/src/Button.js +2 -2
  6. package/src/Button.js.map +3 -3
  7. package/src/ClearButton.dev.js +7 -1
  8. package/src/ClearButton.dev.js.map +2 -2
  9. package/src/ClearButton.js +3 -3
  10. package/src/ClearButton.js.map +3 -3
  11. package/src/CloseButton.dev.js +7 -1
  12. package/src/CloseButton.dev.js.map +2 -2
  13. package/src/CloseButton.js +2 -2
  14. package/src/CloseButton.js.map +3 -3
  15. package/src/button-overrides.css.d.ts +2 -0
  16. package/src/button-overrides.css.dev.js +7 -0
  17. package/src/button-overrides.css.dev.js.map +7 -0
  18. package/src/button-overrides.css.js +4 -0
  19. package/src/button-overrides.css.js.map +7 -0
  20. package/src/button.css.dev.js +1 -1
  21. package/src/button.css.dev.js.map +1 -1
  22. package/src/button.css.js +1 -1
  23. package/src/button.css.js.map +1 -1
  24. package/src/spectrum-button.css.dev.js +1 -1
  25. package/src/spectrum-button.css.dev.js.map +1 -1
  26. package/src/spectrum-button.css.js +3 -3
  27. package/src/spectrum-button.css.js.map +1 -1
  28. package/src/spectrum-config.js +1 -0
  29. package/stories/button-accent-fill.stories.js +0 -2
  30. package/stories/button-accent-fill.stories.js.map +2 -2
  31. package/stories/button-accent-outline.stories.js +0 -2
  32. package/stories/button-accent-outline.stories.js.map +2 -2
  33. package/stories/button-black-fill.stories.js +0 -2
  34. package/stories/button-black-fill.stories.js.map +2 -2
  35. package/stories/button-black-outline.stories.js +0 -2
  36. package/stories/button-black-outline.stories.js.map +2 -2
  37. package/stories/button-negative-fill.stories.js +0 -2
  38. package/stories/button-negative-fill.stories.js.map +2 -2
  39. package/stories/button-negative-outline.stories.js +0 -2
  40. package/stories/button-negative-outline.stories.js.map +2 -2
  41. package/stories/button-primary-fill.stories.js +0 -2
  42. package/stories/button-primary-fill.stories.js.map +2 -2
  43. package/stories/button-primary-outline.stories.js +0 -2
  44. package/stories/button-primary-outline.stories.js.map +2 -2
  45. package/stories/button-secondary-fill.stories.js +0 -2
  46. package/stories/button-secondary-fill.stories.js.map +2 -2
  47. package/stories/button-secondary-outline.stories.js +0 -2
  48. package/stories/button-secondary-outline.stories.js.map +2 -2
  49. package/stories/button-white-fill.stories.js +0 -2
  50. package/stories/button-white-fill.stories.js.map +2 -2
  51. package/stories/button-white-outline.stories.js +0 -2
  52. package/stories/button-white-outline.stories.js.map +2 -2
  53. package/stories/index.js +0 -18
  54. package/stories/index.js.map +2 -2
  55. package/test/button.test.js +539 -566
  56. package/test/button.test.js.map +2 -2
@@ -18,7 +18,7 @@ import { spy, stub } from "sinon";
18
18
  describe("Button", () => {
19
19
  testForLitDevWarnings(
20
20
  async () => await fixture(html`
21
- <sp-button tabindex="0">Button</sp-button>
21
+ <sp-button>Button</sp-button>
22
22
  `)
23
23
  );
24
24
  describe("dev mode", () => {
@@ -36,7 +36,7 @@ describe("Button", () => {
36
36
  });
37
37
  it("warns in devMode when white/black variant is provided", async () => {
38
38
  const el = await fixture(html`
39
- <sp-button tabindex="0" variant="white">Button</sp-button>
39
+ <sp-button variant="white">Button</sp-button>
40
40
  `);
41
41
  await elementUpdated(el);
42
42
  expect(consoleWarnStub.called).to.be.true;
@@ -53,606 +53,579 @@ describe("Button", () => {
53
53
  }
54
54
  });
55
55
  });
56
- it("warns in devMode when white/black static is provided", async () => {
56
+ it("loads default", async () => {
57
57
  const el = await fixture(html`
58
- <sp-button tabindex="0" static="black">Button</sp-button>
58
+ <sp-button>Button</sp-button>
59
59
  `);
60
60
  await elementUpdated(el);
61
- expect(consoleWarnStub.called).to.be.true;
62
- const spyCall = consoleWarnStub.getCall(0);
63
- expect(
64
- spyCall.args.at(0).includes("deprecated"),
65
- "confirm deprecated static warning"
66
- ).to.be.true;
67
- expect(spyCall.args.at(-1), "confirm `data` shape").to.deep.equal({
68
- data: {
69
- localName: "sp-button",
70
- type: "api",
71
- level: "deprecation"
72
- }
73
- });
61
+ expect(el).to.not.be.undefined;
62
+ expect(el.textContent).to.include("Button");
63
+ await expect(el).to.be.accessible();
64
+ expect(el.variant).to.equal("accent");
65
+ expect(el.getAttribute("variant")).to.equal("accent");
74
66
  });
75
- it("warns in devMode when white/black static is provided", async () => {
67
+ it("loads default w/ an icon", async () => {
76
68
  const el = await fixture(html`
77
- <sp-button tabindex="0" static="white">Button</sp-button>
69
+ <sp-button label="">
70
+ Button
71
+ <svg slot="icon"></svg>
72
+ </sp-button>
78
73
  `);
79
74
  await elementUpdated(el);
80
- expect(consoleWarnStub.called).to.be.true;
81
- const spyCall = consoleWarnStub.getCall(0);
82
- expect(
83
- spyCall.args.at(0).includes("deprecated"),
84
- "confirm deprecated static warning"
85
- ).to.be.true;
86
- expect(spyCall.args.at(-1), "confirm `data` shape").to.deep.equal({
87
- data: {
88
- localName: "sp-button",
89
- type: "api",
90
- level: "deprecation"
91
- }
75
+ expect(el).to.not.be.undefined;
76
+ expect(el.textContent).to.include("Button");
77
+ expect(!el.hasIcon);
78
+ await expect(el).to.be.accessible();
79
+ });
80
+ it("loads default only icon", async () => {
81
+ const el = await fixture(html`
82
+ <sp-button label="Button" icon-only>
83
+ <svg slot="icon"></svg>
84
+ </sp-button>
85
+ `);
86
+ await elementUpdated(el);
87
+ expect(el).to.not.be.undefined;
88
+ await expect(el).to.be.accessible();
89
+ });
90
+ it("has a stable/predictable `updateComplete`", async () => {
91
+ const test = await fixture(html`
92
+ <div></div>
93
+ `);
94
+ let keydownTime = -1;
95
+ let updateComplete1 = -1;
96
+ let updateComplete2 = -1;
97
+ const el = document.createElement("sp-button");
98
+ el.autofocus = true;
99
+ el.addEventListener("keydown", () => {
100
+ keydownTime = performance.now();
101
+ });
102
+ el.updateComplete.then(() => {
103
+ updateComplete1 = performance.now();
104
+ });
105
+ el.updateComplete.then(() => {
106
+ updateComplete2 = performance.now();
92
107
  });
108
+ test.append(el);
109
+ await nextFrame();
110
+ await nextFrame();
111
+ await nextFrame();
112
+ await nextFrame();
113
+ expect(keydownTime, "keydown happened").to.not.eq(-1);
114
+ expect(updateComplete1, "first update complete happened").to.not.eq(
115
+ -1
116
+ );
117
+ expect(updateComplete2, "first update complete happened").to.not.eq(
118
+ -1
119
+ );
120
+ expect(updateComplete1).lte(updateComplete2);
121
+ expect(updateComplete2).lte(keydownTime);
93
122
  });
94
- });
95
- it("loads default", async () => {
96
- const el = await fixture(html`
97
- <sp-button tabindex="0">Button</sp-button>
98
- `);
99
- await elementUpdated(el);
100
- expect(el).to.not.be.undefined;
101
- expect(el.textContent).to.include("Button");
102
- await expect(el).to.be.accessible();
103
- expect(el.variant).to.equal("accent");
104
- expect(el.getAttribute("variant")).to.equal("accent");
105
- });
106
- it("loads default w/ element content", async () => {
107
- const el = await fixture(html`
108
- <sp-button label="Button"><svg></svg></sp-button>
109
- `);
110
- await elementUpdated(el);
111
- expect(el).to.not.be.undefined;
112
- await expect(el).to.be.accessible();
113
- });
114
- it("loads default w/ an icon", async () => {
115
- const el = await fixture(html`
116
- <sp-button label="">
117
- Button
118
- <svg slot="icon"></svg>
119
- </sp-button>
120
- `);
121
- await elementUpdated(el);
122
- expect(el).to.not.be.undefined;
123
- expect(el.textContent).to.include("Button");
124
- expect(!el.hasIcon);
125
- await expect(el).to.be.accessible();
126
- });
127
- it("loads default only icon", async () => {
128
- const el = await fixture(html`
129
- <sp-button label="Button" icon-only>
130
- <svg slot="icon"></svg>
131
- </sp-button>
132
- `);
133
- await elementUpdated(el);
134
- expect(el).to.not.be.undefined;
135
- await expect(el).to.be.accessible();
136
- });
137
- it("has a stable/predictable `updateComplete`", async () => {
138
- const test = await fixture(html`
139
- <div></div>
140
- `);
141
- let keydownTime = -1;
142
- let updateComplete1 = -1;
143
- let updateComplete2 = -1;
144
- const el = document.createElement("sp-button");
145
- el.autofocus = true;
146
- el.addEventListener("keydown", () => {
147
- keydownTime = performance.now();
123
+ it('manages "role"', async () => {
124
+ const el = await fixture(html`
125
+ <sp-button>Button</sp-button>
126
+ `);
127
+ await elementUpdated(el);
128
+ expect(el.getAttribute("role")).to.equal("button");
129
+ el.setAttribute("href", "#");
130
+ await elementUpdated(el);
131
+ expect(el.getAttribute("role")).to.equal("link");
132
+ el.removeAttribute("href");
133
+ await elementUpdated(el);
134
+ expect(el.getAttribute("role")).to.equal("button");
148
135
  });
149
- el.updateComplete.then(() => {
150
- updateComplete1 = performance.now();
136
+ it("allows label to be toggled", async () => {
137
+ const testNode = document.createTextNode("Button");
138
+ const el = await fixture(html`
139
+ <sp-button>
140
+ ${testNode}
141
+ <svg slot="icon"></svg>
142
+ </sp-button>
143
+ `);
144
+ await elementUpdated(el);
145
+ const labelTestableEl = el;
146
+ expect(labelTestableEl.hasLabel, "starts with label").to.be.true;
147
+ testNode.textContent = "";
148
+ await elementUpdated(el);
149
+ await waitUntil(
150
+ () => !labelTestableEl.hasLabel,
151
+ "label is removed"
152
+ );
153
+ testNode.textContent = "Button";
154
+ await elementUpdated(el);
155
+ expect(labelTestableEl.hasLabel, "label is returned").to.be.true;
151
156
  });
152
- el.updateComplete.then(() => {
153
- updateComplete2 = performance.now();
157
+ it("loads with href", async () => {
158
+ const el = await fixture(html`
159
+ <sp-button href="test_url">With Href</sp-button>
160
+ `);
161
+ await elementUpdated(el);
162
+ expect(el).to.not.be.undefined;
163
+ expect(el.textContent).to.include("With Href");
154
164
  });
155
- test.append(el);
156
- await nextFrame();
157
- await nextFrame();
158
- await nextFrame();
159
- await nextFrame();
160
- expect(keydownTime, "keydown happened").to.not.eq(-1);
161
- expect(updateComplete1, "first update complete happened").to.not.eq(-1);
162
- expect(updateComplete2, "first update complete happened").to.not.eq(-1);
163
- expect(updateComplete1).lte(updateComplete2);
164
- expect(updateComplete2).lte(keydownTime);
165
- });
166
- it('manages "role"', async () => {
167
- const el = await fixture(html`
168
- <sp-button>Button</sp-button>
169
- `);
170
- await elementUpdated(el);
171
- expect(el.getAttribute("role")).to.equal("button");
172
- el.setAttribute("href", "#");
173
- await elementUpdated(el);
174
- expect(el.getAttribute("role")).to.equal("link");
175
- el.removeAttribute("href");
176
- await elementUpdated(el);
177
- expect(el.getAttribute("role")).to.equal("button");
178
- });
179
- it("allows label to be toggled", async () => {
180
- const testNode = document.createTextNode("Button");
181
- const el = await fixture(html`
182
- <sp-button>
183
- ${testNode}
184
- <svg slot="icon"></svg>
185
- </sp-button>
186
- `);
187
- await elementUpdated(el);
188
- const labelTestableEl = el;
189
- expect(labelTestableEl.hasLabel, "starts with label").to.be.true;
190
- testNode.textContent = "";
191
- await elementUpdated(el);
192
- await waitUntil(() => !labelTestableEl.hasLabel, "label is removed");
193
- testNode.textContent = "Button";
194
- await elementUpdated(el);
195
- expect(labelTestableEl.hasLabel, "label is returned").to.be.true;
196
- });
197
- it("loads with href", async () => {
198
- const el = await fixture(html`
199
- <sp-button href="test_url">With Href</sp-button>
200
- `);
201
- await elementUpdated(el);
202
- expect(el).to.not.be.undefined;
203
- expect(el.textContent).to.include("With Href");
204
- });
205
- it("loads with href and target", async () => {
206
- const el = await fixture(html`
207
- <sp-button href="test_url" target="_blank">With Target</sp-button>
208
- `);
209
- await elementUpdated(el);
210
- expect(el).to.not.be.undefined;
211
- expect(el.textContent).to.include("With Target");
212
- });
213
- it("accepts shit+tab interactions", async () => {
214
- let focusedCount = 0;
215
- const el = await fixture(html`
216
- <sp-button href="test_url" target="_blank">With Target</sp-button>
217
- `);
218
- await elementUpdated(el);
219
- const input = document.createElement("input");
220
- el.insertAdjacentElement("beforebegin", input);
221
- input.focus();
222
- expect(document.activeElement === input).to.be.true;
223
- el.addEventListener("focus", () => {
224
- focusedCount += 1;
165
+ it("loads with href and target", async () => {
166
+ const el = await fixture(html`
167
+ <sp-button href="test_url" target="_blank">
168
+ With Target
169
+ </sp-button>
170
+ `);
171
+ await elementUpdated(el);
172
+ expect(el).to.not.be.undefined;
173
+ expect(el.textContent).to.include("With Target");
225
174
  });
226
- expect(focusedCount).to.equal(0);
227
- await sendKeys({
228
- press: "Tab"
175
+ it("accepts shift+tab interactions", async () => {
176
+ let focusedCount = 0;
177
+ const el = await fixture(html`
178
+ <sp-button href="test_url" target="_blank">
179
+ With Target
180
+ </sp-button>
181
+ `);
182
+ await elementUpdated(el);
183
+ const input = document.createElement("input");
184
+ el.insertAdjacentElement("beforebegin", input);
185
+ input.focus();
186
+ expect(document.activeElement === input).to.be.true;
187
+ el.addEventListener("focus", () => {
188
+ focusedCount += 1;
189
+ });
190
+ expect(focusedCount).to.equal(0);
191
+ await sendKeys({
192
+ press: "Tab"
193
+ });
194
+ await elementUpdated(el);
195
+ expect(document.activeElement === el).to.be.true;
196
+ expect(focusedCount).to.equal(1);
197
+ await sendKeys({
198
+ press: "Shift+Tab"
199
+ });
200
+ await elementUpdated(el);
201
+ expect(focusedCount).to.equal(1);
202
+ expect(document.activeElement === input).to.be.true;
229
203
  });
230
- await elementUpdated(el);
231
- expect(document.activeElement === el).to.be.true;
232
- expect(focusedCount).to.equal(1);
233
- await sendKeys({
234
- press: "Shift+Tab"
204
+ it("manages `disabled`", async () => {
205
+ const clickSpy = spy();
206
+ const el = await fixture(html`
207
+ <sp-button @click=${() => clickSpy()}>Button</sp-button>
208
+ `);
209
+ await elementUpdated(el);
210
+ el.click();
211
+ await elementUpdated(el);
212
+ expect(clickSpy.calledOnce).to.be.true;
213
+ clickSpy.resetHistory();
214
+ el.disabled = true;
215
+ await elementUpdated(el);
216
+ el.click();
217
+ await elementUpdated(el);
218
+ expect(clickSpy.callCount).to.equal(0);
219
+ clickSpy.resetHistory();
220
+ await elementUpdated(el);
221
+ el.dispatchEvent(new Event("click", {}));
222
+ await elementUpdated(el);
223
+ expect(clickSpy.callCount).to.equal(0);
224
+ clickSpy.resetHistory();
225
+ el.disabled = false;
226
+ el.click();
227
+ await elementUpdated(el);
228
+ expect(clickSpy.calledOnce).to.be.true;
235
229
  });
236
- await elementUpdated(el);
237
- expect(focusedCount).to.equal(1);
238
- expect(document.activeElement === input).to.be.true;
239
- });
240
- it("manages `disabled`", async () => {
241
- const clickSpy = spy();
242
- const el = await fixture(html`
243
- <sp-button @click=${() => clickSpy()}>Button</sp-button>
244
- `);
245
- await elementUpdated(el);
246
- el.click();
247
- await elementUpdated(el);
248
- expect(clickSpy.calledOnce).to.be.true;
249
- clickSpy.resetHistory();
250
- el.disabled = true;
251
- await elementUpdated(el);
252
- el.click();
253
- await elementUpdated(el);
254
- expect(clickSpy.callCount).to.equal(0);
255
- clickSpy.resetHistory();
256
- await elementUpdated(el);
257
- el.dispatchEvent(new Event("click", {}));
258
- await elementUpdated(el);
259
- expect(clickSpy.callCount).to.equal(0);
260
- clickSpy.resetHistory();
261
- el.disabled = false;
262
- el.click();
263
- await elementUpdated(el);
264
- expect(clickSpy.calledOnce).to.be.true;
265
- });
266
- it("`disabled` manages `tabindex`", async () => {
267
- const el = await fixture(html`
268
- <sp-button disabled>Button</sp-button>
269
- `);
270
- await elementUpdated(el);
271
- expect(el.tabIndex).to.equal(-1);
272
- expect(el.getAttribute("tabindex")).to.equal("-1");
273
- el.disabled = false;
274
- await elementUpdated(el);
275
- expect(el.tabIndex).to.equal(0);
276
- expect(el.getAttribute("tabindex")).to.equal("0");
277
- el.disabled = true;
278
- await elementUpdated(el);
279
- expect(el.tabIndex).to.equal(-1);
280
- expect(el.getAttribute("tabindex")).to.equal("-1");
281
- });
282
- it("manages `aria-disabled`", async () => {
283
- const el = await fixture(html`
284
- <sp-button href="test_url" target="_blank">With Target</sp-button>
285
- `);
286
- await elementUpdated(el);
287
- expect(el.hasAttribute("aria-disabled"), "initially not").to.be.false;
288
- el.disabled = true;
289
- await elementUpdated(el);
290
- expect(el.getAttribute("aria-disabled")).to.equal("true");
291
- el.disabled = false;
292
- await elementUpdated(el);
293
- expect(el.hasAttribute("aria-disabled"), "finally not").to.be.false;
294
- });
295
- it("manages aria-label from disabled state", async () => {
296
- const el = await fixture(html`
297
- <sp-button
298
- href="test_url"
299
- target="_blank"
300
- label="clickable"
301
- disabled
302
- pending-label="Pending Button"
303
- >
304
- Click me
305
- </sp-button>
306
- `);
307
- await elementUpdated(el);
308
- expect(el.getAttribute("aria-label")).to.equal("clickable");
309
- el.pending = true;
310
- await elementUpdated(el);
311
- expect(el.getAttribute("aria-label")).to.equal("clickable");
312
- el.disabled = false;
313
- await elementUpdated(el);
314
- expect(el.getAttribute("aria-label")).to.equal("Pending Button");
315
- el.pending = false;
316
- await elementUpdated(el);
317
- expect(el.getAttribute("aria-label")).to.equal("clickable");
318
- });
319
- it("manages aria-label from pending state", async () => {
320
- const el = await fixture(html`
321
- <sp-button
322
- href="test_url"
323
- target="_blank"
324
- label="clickable"
325
- pending
326
- >
327
- Click me
328
- </sp-button>
329
- `);
330
- await elementUpdated(el);
331
- expect(el.getAttribute("aria-label")).to.equal("Pending");
332
- el.disabled = true;
333
- await elementUpdated(el);
334
- expect(el.getAttribute("aria-label")).to.equal("clickable");
335
- el.pending = false;
336
- await elementUpdated(el);
337
- expect(el.getAttribute("aria-label")).to.equal("clickable");
338
- el.disabled = false;
339
- await elementUpdated(el);
340
- expect(el.getAttribute("aria-label")).to.equal("clickable");
341
- });
342
- it("manages aria-label set from outside", async () => {
343
- const el = await fixture(html`
344
- <sp-button
345
- href="test_url"
346
- target="_blank"
347
- aria-label="test"
348
- pending-label="Pending Button"
349
- >
350
- Click me
351
- </sp-button>
352
- `);
353
- await elementUpdated(el);
354
- expect(el.getAttribute("aria-label")).to.equal("test");
355
- el.pending = true;
356
- await elementUpdated(el);
357
- expect(el.getAttribute("aria-label")).to.equal("Pending Button");
358
- el.disabled = true;
359
- await elementUpdated(el);
360
- expect(el.getAttribute("aria-label")).to.equal("test");
361
- el.disabled = false;
362
- await elementUpdated(el);
363
- expect(el.getAttribute("aria-label")).to.equal("Pending Button");
364
- el.pending = false;
365
- await elementUpdated(el);
366
- expect(el.getAttribute("aria-label")).to.equal("test");
367
- });
368
- it("updates pending label accessibly", async () => {
369
- const el = await fixture(html`
370
- <sp-button href="test_url" target="_blank">Button</sp-button>
371
- `);
372
- await elementUpdated(el);
373
- el.pending = true;
374
- await elementUpdated(el);
375
- await nextFrame();
376
- let snapshot = await a11ySnapshot({});
377
- expect(
378
- findAccessibilityNode(
379
- snapshot,
380
- (node) => node.name === "Pending"
381
- ),
382
- "`Pending` is the label text"
383
- ).to.not.be.null;
384
- expect(el.pending).to.be.true;
385
- el.pending = false;
386
- await elementUpdated(el);
387
- await nextFrame();
388
- snapshot = await a11ySnapshot({});
389
- expect(
390
- findAccessibilityNode(
391
- snapshot,
392
- (node) => node.name === "Button"
393
- ),
394
- "`Button` is the label text"
395
- ).to.not.be.null;
396
- expect(el.pending).to.be.false;
397
- });
398
- it("manages tabIndex while disabled", async () => {
399
- const el = await fixture(html`
400
- <sp-button href="test_url" target="_blank">With Target</sp-button>
401
- `);
402
- await elementUpdated(el);
403
- expect(el.tabIndex).to.equal(0);
404
- el.disabled = true;
405
- await elementUpdated(el);
406
- expect(el.tabIndex).to.equal(-1);
407
- el.tabIndex = 2;
408
- await elementUpdated(el);
409
- expect(el.tabIndex).to.equal(-1);
410
- el.disabled = false;
411
- await elementUpdated(el);
412
- expect(el.tabIndex).to.equal(2);
413
- });
414
- it("swallows `click` interaction when `[disabled]`", async () => {
415
- const clickSpy = spy();
416
- const el = await fixture(html`
417
- <sp-button disabled @click=${() => clickSpy()}>Button</sp-button>
418
- `);
419
- await elementUpdated(el);
420
- expect(clickSpy.callCount).to.equal(0);
421
- el.click();
422
- await elementUpdated(el);
423
- expect(clickSpy.callCount).to.equal(0);
424
- });
425
- it("translates keyboard interactions to click", async () => {
426
- const clickSpy = spy();
427
- const el = await fixture(html`
428
- <sp-button @click=${() => clickSpy()}>Button</sp-button>
429
- `);
430
- await elementUpdated(el);
431
- el.dispatchEvent(
432
- new KeyboardEvent("keypress", {
433
- bubbles: true,
434
- composed: true,
435
- cancelable: true,
436
- code: "Enter",
437
- key: "Enter"
438
- })
439
- );
440
- await elementUpdated(el);
441
- expect(clickSpy.callCount).to.equal(1);
442
- clickSpy.resetHistory();
443
- el.dispatchEvent(
444
- new KeyboardEvent("keypress", {
445
- bubbles: true,
446
- composed: true,
447
- cancelable: true,
448
- code: "NumpadEnter",
449
- key: "NumpadEnter"
450
- })
451
- );
452
- await elementUpdated(el);
453
- expect(clickSpy.callCount).to.equal(1);
454
- clickSpy.resetHistory();
455
- el.dispatchEvent(
456
- new KeyboardEvent("keypress", {
457
- bubbles: true,
458
- composed: true,
459
- cancelable: true,
460
- code: "Space",
461
- key: "Space"
462
- })
463
- );
464
- await elementUpdated(el);
465
- expect(clickSpy.callCount).to.equal(0);
466
- clickSpy.resetHistory();
467
- el.dispatchEvent(
468
- new KeyboardEvent("keydown", {
469
- bubbles: true,
470
- composed: true,
471
- cancelable: true,
472
- code: "Space",
473
- key: "Space"
474
- })
475
- );
476
- el.dispatchEvent(
477
- new KeyboardEvent("keyup", {
478
- bubbles: true,
479
- composed: true,
480
- cancelable: true,
481
- code: "Space",
482
- key: "Space"
483
- })
484
- );
485
- await elementUpdated(el);
486
- expect(clickSpy.callCount).to.equal(1);
487
- clickSpy.resetHistory();
488
- el.dispatchEvent(
489
- new KeyboardEvent("keydown", {
490
- bubbles: true,
491
- composed: true,
492
- cancelable: true,
493
- code: "Space",
494
- key: "Space"
495
- })
496
- );
497
- el.dispatchEvent(
498
- new KeyboardEvent("keyup", {
499
- bubbles: true,
500
- composed: true,
501
- cancelable: true,
502
- code: "KeyG",
503
- key: "g"
504
- })
505
- );
506
- await elementUpdated(el);
507
- expect(clickSpy.callCount).to.equal(0);
508
- el.dispatchEvent(
509
- new KeyboardEvent("keyup", {
510
- bubbles: true,
511
- composed: true,
512
- cancelable: true,
513
- code: "Space",
514
- key: "Space"
515
- })
516
- );
517
- clickSpy.resetHistory();
518
- el.dispatchEvent(
519
- new KeyboardEvent("keydown", {
520
- bubbles: true,
521
- composed: true,
522
- cancelable: true,
523
- code: "KeyG",
524
- key: "g"
525
- })
526
- );
527
- el.dispatchEvent(
528
- new KeyboardEvent("keyup", {
529
- bubbles: true,
530
- composed: true,
531
- cancelable: true,
532
- code: "Space",
533
- key: "Space"
534
- })
535
- );
536
- await elementUpdated(el);
537
- expect(clickSpy.callCount).to.equal(0);
538
- });
539
- it('proxies clicks by "type"', async () => {
540
- const submitSpy = spy();
541
- const resetSpy = spy();
542
- const test = await fixture(html`
543
- <form
544
- @submit=${(event) => {
545
- event.preventDefault();
546
- submitSpy();
547
- }}
548
- @reset=${(event) => {
549
- event.preventDefault();
550
- resetSpy();
551
- }}
552
- >
553
- <sp-button>Button</sp-button>
554
- </form>
555
- `);
556
- const el = test.querySelector("sp-button");
557
- await elementUpdated(el);
558
- el.type = "submit";
559
- await elementUpdated(el);
560
- el.click();
561
- expect(submitSpy.callCount).to.equal(1);
562
- expect(resetSpy.callCount).to.equal(0);
563
- el.type = "reset";
564
- await elementUpdated(el);
565
- el.click();
566
- expect(submitSpy.callCount).to.equal(1);
567
- expect(resetSpy.callCount).to.equal(1);
568
- el.type = "button";
569
- await elementUpdated(el);
570
- el.click();
571
- expect(submitSpy.callCount).to.equal(1);
572
- expect(resetSpy.callCount).to.equal(1);
573
- });
574
- it("proxies click by [href]", async () => {
575
- const clickSpy = spy();
576
- const el = await fixture(html`
577
- <sp-button href="test_url">With Href</sp-button>
578
- `);
579
- await elementUpdated(el);
580
- el.anchorElement.addEventListener("click", (event) => {
581
- event.preventDefault();
582
- event.stopPropagation();
583
- clickSpy();
230
+ it("`disabled` manages `tabindex`", async () => {
231
+ const el = await fixture(html`
232
+ <sp-button disabled>Button</sp-button>
233
+ `);
234
+ await elementUpdated(el);
235
+ expect(el.tabIndex).to.equal(-1);
236
+ expect(el.getAttribute("tabindex")).to.equal("-1");
237
+ el.disabled = false;
238
+ await elementUpdated(el);
239
+ expect(el.tabIndex).to.equal(0);
240
+ expect(el.getAttribute("tabindex")).to.equal("0");
241
+ el.disabled = true;
242
+ await elementUpdated(el);
243
+ expect(el.tabIndex).to.equal(-1);
244
+ expect(el.getAttribute("tabindex")).to.equal("-1");
584
245
  });
585
- expect(clickSpy.callCount).to.equal(0);
586
- el.click();
587
- await elementUpdated(el);
588
- expect(clickSpy.callCount).to.equal(1);
589
- });
590
- it('manages "active" while focused', async () => {
591
- const el = await fixture(html`
592
- <sp-button label="Button">
593
- <svg slot="icon"></svg>
594
- </sp-button>
595
- `);
596
- await elementUpdated(el);
597
- el.focus();
598
- await elementUpdated(el);
599
- await sendKeys({
600
- down: "Space"
246
+ it("manages `aria-disabled`", async () => {
247
+ const el = await fixture(html`
248
+ <sp-button href="test_url" target="_blank">
249
+ With Target
250
+ </sp-button>
251
+ `);
252
+ await elementUpdated(el);
253
+ expect(el.hasAttribute("aria-disabled"), "initially not").to.be.false;
254
+ el.disabled = true;
255
+ await elementUpdated(el);
256
+ expect(el.getAttribute("aria-disabled")).to.equal("true");
257
+ el.disabled = false;
258
+ await elementUpdated(el);
259
+ expect(el.hasAttribute("aria-disabled"), "finally not").to.be.false;
601
260
  });
602
- await elementUpdated(el);
603
- expect(el.active).to.be.true;
604
- await sendKeys({
605
- up: "Space"
261
+ it("manages aria-label from disabled state", async () => {
262
+ const el = await fixture(html`
263
+ <sp-button
264
+ href="test_url"
265
+ target="_blank"
266
+ label="clickable"
267
+ disabled
268
+ pending-label="Pending Button"
269
+ >
270
+ Click me
271
+ </sp-button>
272
+ `);
273
+ await elementUpdated(el);
274
+ expect(el.getAttribute("aria-label")).to.equal("clickable");
275
+ el.pending = true;
276
+ await elementUpdated(el);
277
+ expect(el.getAttribute("aria-label")).to.equal("clickable");
278
+ el.disabled = false;
279
+ await elementUpdated(el);
280
+ expect(el.getAttribute("aria-label")).to.equal("Pending Button");
281
+ el.pending = false;
282
+ await elementUpdated(el);
283
+ expect(el.getAttribute("aria-label")).to.equal("clickable");
606
284
  });
607
- await elementUpdated(el);
608
- expect(el.active).to.be.false;
609
- });
610
- describe("deprecated variants and attributes", () => {
611
- it("manages [quiet]", async () => {
285
+ it("manages aria-label from pending state", async () => {
612
286
  const el = await fixture(html`
613
- <sp-button quiet>Button</sp-button>
287
+ <sp-button
288
+ href="test_url"
289
+ target="_blank"
290
+ label="clickable"
291
+ pending
292
+ >
293
+ Click me
294
+ </sp-button>
614
295
  `);
615
296
  await elementUpdated(el);
616
- expect(el.treatment).to.equal("outline");
617
- el.quiet = false;
297
+ expect(el.getAttribute("aria-label")).to.equal("Pending");
298
+ el.disabled = true;
299
+ await elementUpdated(el);
300
+ expect(el.getAttribute("aria-label")).to.equal("clickable");
301
+ el.pending = false;
302
+ await elementUpdated(el);
303
+ expect(el.getAttribute("aria-label")).to.equal("clickable");
304
+ el.disabled = false;
618
305
  await elementUpdated(el);
619
- expect(el.treatment).to.equal("fill");
306
+ expect(el.getAttribute("aria-label")).to.equal("clickable");
620
307
  });
621
- it('upgrades [variant="cta"] to [variant="accent"]', async () => {
308
+ it("manages aria-label set from outside", async () => {
622
309
  const el = await fixture(html`
623
- <sp-button variant="cta">Button</sp-button>
310
+ <sp-button
311
+ href="test_url"
312
+ target="_blank"
313
+ aria-label="test"
314
+ pending-label="Pending Button"
315
+ >
316
+ Click me
317
+ </sp-button>
624
318
  `);
625
319
  await elementUpdated(el);
626
- expect(el.variant).to.equal("accent");
320
+ expect(el.getAttribute("aria-label")).to.equal("test");
321
+ el.pending = true;
322
+ await elementUpdated(el);
323
+ expect(el.getAttribute("aria-label")).to.equal("Pending Button");
324
+ el.disabled = true;
325
+ await elementUpdated(el);
326
+ expect(el.getAttribute("aria-label")).to.equal("test");
327
+ el.disabled = false;
328
+ await elementUpdated(el);
329
+ expect(el.getAttribute("aria-label")).to.equal("Pending Button");
330
+ el.pending = false;
331
+ await elementUpdated(el);
332
+ expect(el.getAttribute("aria-label")).to.equal("test");
627
333
  });
628
- it('manages [variant="overBackground"]', async () => {
334
+ it("updates pending label accessibly", async () => {
629
335
  const el = await fixture(html`
630
- <sp-button variant="overBackground">Button</sp-button>
336
+ <sp-button href="test_url" target="_blank">Button</sp-button>
631
337
  `);
632
338
  await elementUpdated(el);
633
- expect(el.getAttribute("variant")).to.not.equal("overBackground");
634
- expect(el.treatment).to.equal("outline");
635
- expect(el.staticColor).to.equal("white");
339
+ el.pending = true;
340
+ await elementUpdated(el);
341
+ await nextFrame();
342
+ let snapshot = await a11ySnapshot({});
343
+ expect(
344
+ findAccessibilityNode(
345
+ snapshot,
346
+ (node) => node.name === "Pending"
347
+ ),
348
+ "`Pending` is the label text"
349
+ ).to.not.be.null;
350
+ expect(el.pending).to.be.true;
351
+ el.pending = false;
352
+ await elementUpdated(el);
353
+ await nextFrame();
354
+ snapshot = await a11ySnapshot({});
355
+ expect(
356
+ findAccessibilityNode(
357
+ snapshot,
358
+ (node) => node.name === "Button"
359
+ ),
360
+ "`Button` is the label text"
361
+ ).to.not.be.null;
362
+ expect(el.pending).to.be.false;
636
363
  });
637
- ["white", "black"].forEach((variant) => {
638
- it(`manages [variant="${variant}"]`, async () => {
639
- const el = await fixture(html`
640
- <sp-button variant="${variant}">
641
- Button
642
- </sp-button>
643
- `);
644
- await elementUpdated(el);
645
- expect(el.hasAttribute("variant")).to.not.equal(variant);
646
- expect(el.staticColor).to.equal(variant);
647
- expect(el.getAttribute("static-color")).to.equal(variant);
364
+ it("manages tabIndex while disabled", async () => {
365
+ const el = await fixture(html`
366
+ <sp-button href="test_url" target="_blank">
367
+ With Target
368
+ </sp-button>
369
+ `);
370
+ await elementUpdated(el);
371
+ expect(el.tabIndex).to.equal(0);
372
+ el.disabled = true;
373
+ await elementUpdated(el);
374
+ expect(el.tabIndex).to.equal(-1);
375
+ el.tabIndex = 2;
376
+ await elementUpdated(el);
377
+ expect(el.tabIndex).to.equal(-1);
378
+ el.disabled = false;
379
+ await elementUpdated(el);
380
+ expect(el.tabIndex).to.equal(2);
381
+ });
382
+ it("swallows `click` interaction when `[disabled]`", async () => {
383
+ const clickSpy = spy();
384
+ const el = await fixture(html`
385
+ <sp-button disabled @click=${() => clickSpy()}>
386
+ Button
387
+ </sp-button>
388
+ `);
389
+ await elementUpdated(el);
390
+ expect(clickSpy.callCount).to.equal(0);
391
+ el.click();
392
+ await elementUpdated(el);
393
+ expect(clickSpy.callCount).to.equal(0);
394
+ });
395
+ it("translates keyboard interactions to click", async () => {
396
+ const clickSpy = spy();
397
+ const el = await fixture(html`
398
+ <sp-button @click=${() => clickSpy()}>Button</sp-button>
399
+ `);
400
+ await elementUpdated(el);
401
+ el.dispatchEvent(
402
+ new KeyboardEvent("keypress", {
403
+ bubbles: true,
404
+ composed: true,
405
+ cancelable: true,
406
+ code: "Enter",
407
+ key: "Enter"
408
+ })
409
+ );
410
+ await elementUpdated(el);
411
+ expect(clickSpy.callCount).to.equal(1);
412
+ clickSpy.resetHistory();
413
+ el.dispatchEvent(
414
+ new KeyboardEvent("keypress", {
415
+ bubbles: true,
416
+ composed: true,
417
+ cancelable: true,
418
+ code: "NumpadEnter",
419
+ key: "NumpadEnter"
420
+ })
421
+ );
422
+ await elementUpdated(el);
423
+ expect(clickSpy.callCount).to.equal(1);
424
+ clickSpy.resetHistory();
425
+ el.dispatchEvent(
426
+ new KeyboardEvent("keypress", {
427
+ bubbles: true,
428
+ composed: true,
429
+ cancelable: true,
430
+ code: "Space",
431
+ key: "Space"
432
+ })
433
+ );
434
+ await elementUpdated(el);
435
+ expect(clickSpy.callCount).to.equal(0);
436
+ clickSpy.resetHistory();
437
+ el.dispatchEvent(
438
+ new KeyboardEvent("keydown", {
439
+ bubbles: true,
440
+ composed: true,
441
+ cancelable: true,
442
+ code: "Space",
443
+ key: "Space"
444
+ })
445
+ );
446
+ el.dispatchEvent(
447
+ new KeyboardEvent("keyup", {
448
+ bubbles: true,
449
+ composed: true,
450
+ cancelable: true,
451
+ code: "Space",
452
+ key: "Space"
453
+ })
454
+ );
455
+ await elementUpdated(el);
456
+ expect(clickSpy.callCount).to.equal(1);
457
+ clickSpy.resetHistory();
458
+ el.dispatchEvent(
459
+ new KeyboardEvent("keydown", {
460
+ bubbles: true,
461
+ composed: true,
462
+ cancelable: true,
463
+ code: "Space",
464
+ key: "Space"
465
+ })
466
+ );
467
+ el.dispatchEvent(
468
+ new KeyboardEvent("keyup", {
469
+ bubbles: true,
470
+ composed: true,
471
+ cancelable: true,
472
+ code: "KeyG",
473
+ key: "g"
474
+ })
475
+ );
476
+ await elementUpdated(el);
477
+ expect(clickSpy.callCount).to.equal(0);
478
+ el.dispatchEvent(
479
+ new KeyboardEvent("keyup", {
480
+ bubbles: true,
481
+ composed: true,
482
+ cancelable: true,
483
+ code: "Space",
484
+ key: "Space"
485
+ })
486
+ );
487
+ clickSpy.resetHistory();
488
+ el.dispatchEvent(
489
+ new KeyboardEvent("keydown", {
490
+ bubbles: true,
491
+ composed: true,
492
+ cancelable: true,
493
+ code: "KeyG",
494
+ key: "g"
495
+ })
496
+ );
497
+ el.dispatchEvent(
498
+ new KeyboardEvent("keyup", {
499
+ bubbles: true,
500
+ composed: true,
501
+ cancelable: true,
502
+ code: "Space",
503
+ key: "Space"
504
+ })
505
+ );
506
+ await elementUpdated(el);
507
+ expect(clickSpy.callCount).to.equal(0);
508
+ });
509
+ it('proxies clicks by "type"', async () => {
510
+ const submitSpy = spy();
511
+ const resetSpy = spy();
512
+ const test = await fixture(html`
513
+ <form
514
+ @submit=${(event) => {
515
+ event.preventDefault();
516
+ submitSpy();
517
+ }}
518
+ @reset=${(event) => {
519
+ event.preventDefault();
520
+ resetSpy();
521
+ }}
522
+ >
523
+ <sp-button>Button</sp-button>
524
+ </form>
525
+ `);
526
+ const el = test.querySelector("sp-button");
527
+ await elementUpdated(el);
528
+ el.type = "submit";
529
+ await elementUpdated(el);
530
+ el.click();
531
+ expect(submitSpy.callCount).to.equal(1);
532
+ expect(resetSpy.callCount).to.equal(0);
533
+ el.type = "reset";
534
+ await elementUpdated(el);
535
+ el.click();
536
+ expect(submitSpy.callCount).to.equal(1);
537
+ expect(resetSpy.callCount).to.equal(1);
538
+ el.type = "button";
539
+ await elementUpdated(el);
540
+ el.click();
541
+ expect(submitSpy.callCount).to.equal(1);
542
+ expect(resetSpy.callCount).to.equal(1);
543
+ });
544
+ it("proxies click by [href]", async () => {
545
+ const clickSpy = spy();
546
+ const el = await fixture(html`
547
+ <sp-button href="test_url">With Href</sp-button>
548
+ `);
549
+ await elementUpdated(el);
550
+ el.anchorElement.addEventListener("click", (event) => {
551
+ event.preventDefault();
552
+ event.stopPropagation();
553
+ clickSpy();
648
554
  });
555
+ expect(clickSpy.callCount).to.equal(0);
556
+ el.click();
557
+ await elementUpdated(el);
558
+ expect(clickSpy.callCount).to.equal(1);
649
559
  });
650
- it('forces [variant="accent"]', async () => {
560
+ it('manages "active" while focused', async () => {
651
561
  const el = await fixture(html`
652
- <sp-button variant="not-supported">Button</sp-button>
562
+ <sp-button label="Button">
563
+ <svg slot="icon"></svg>
564
+ </sp-button>
653
565
  `);
654
566
  await elementUpdated(el);
655
- expect(el.variant).to.equal("accent");
567
+ el.focus();
568
+ await elementUpdated(el);
569
+ await sendKeys({
570
+ down: "Space"
571
+ });
572
+ await elementUpdated(el);
573
+ expect(el.active).to.be.true;
574
+ await sendKeys({
575
+ up: "Space"
576
+ });
577
+ await elementUpdated(el);
578
+ expect(el.active).to.be.false;
579
+ });
580
+ describe("deprecated variants and attributes", () => {
581
+ it("manages [quiet]", async () => {
582
+ const el = await fixture(html`
583
+ <sp-button quiet>Button</sp-button>
584
+ `);
585
+ await elementUpdated(el);
586
+ expect(el.treatment).to.equal("outline");
587
+ el.quiet = false;
588
+ await elementUpdated(el);
589
+ expect(el.treatment).to.equal("fill");
590
+ });
591
+ it('upgrades [variant="cta"] to [variant="accent"]', async () => {
592
+ const el = await fixture(html`
593
+ <sp-button variant="cta">Button</sp-button>
594
+ `);
595
+ await elementUpdated(el);
596
+ expect(el.variant).to.equal("accent");
597
+ });
598
+ it('manages [variant="overBackground"]', async () => {
599
+ const el = await fixture(html`
600
+ <sp-button variant="overBackground">Button</sp-button>
601
+ `);
602
+ await elementUpdated(el);
603
+ expect(el.getAttribute("variant")).to.not.equal(
604
+ "overBackground"
605
+ );
606
+ expect(el.treatment).to.equal("outline");
607
+ expect(el.staticColor).to.equal("white");
608
+ });
609
+ ["white", "black"].forEach((variant) => {
610
+ it(`manages [variant="${variant}"]`, async () => {
611
+ const el = await fixture(html`
612
+ <sp-button variant="${variant}">
613
+ Button
614
+ </sp-button>
615
+ `);
616
+ await elementUpdated(el);
617
+ expect(el.hasAttribute("variant")).to.not.equal(variant);
618
+ expect(el.staticColor).to.equal(variant);
619
+ expect(el.getAttribute("static-color")).to.equal(variant);
620
+ });
621
+ });
622
+ it('forces [variant="accent"]', async () => {
623
+ const el = await fixture(html`
624
+ <sp-button variant="not-supported">Button</sp-button>
625
+ `);
626
+ await elementUpdated(el);
627
+ expect(el.variant).to.equal("accent");
628
+ });
656
629
  });
657
630
  });
658
631
  });