@waggylabs/yumekit 0.4.1-beta.78 → 0.4.1-beta.79

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/CHANGELOG.md CHANGED
@@ -31,6 +31,14 @@ Delete any empty sections before publishing.
31
31
  <!-- ### Security -->
32
32
  <!-- Vulnerability patches or hardening changes -->
33
33
 
34
+ ## [Unreleased]
35
+
36
+ ### Added
37
+
38
+ - `href`, `target`, and `rel` attributes on `y-button`. When `href` is set the internal element switches from `<button>` to `<a>`, preserving all visual styles and size/color/style-type variants. Disabled state is handled via `aria-disabled` and `pointer-events: none` since `<a>` has no native disabled.
39
+ - `navigate` custom event on `y-appbar`, `y-panel`, and `y-menu`. Fires before any navigation when an item with an `href` / `url` is clicked. The event is cancelable (`e.preventDefault()`) and carries `event.detail.href` — React Router and other SPA routers can intercept it without any framework-specific glue.
40
+ - `history` attribute on `y-appbar` and `y-menu` (already present on `y-panel`). When omitted (default), navigation uses `history.pushState` + a synthetic `popstate` event so all `popstate`-based routers (React Router `BrowserRouter`, Vue Router, etc.) respond automatically. Set `history="false"` to opt back in to full-page `window.location.href` navigation.
41
+
34
42
  ## [0.4.2] - 2026-04-11
35
43
 
36
44
  ### Changed
@@ -34,6 +34,12 @@ export class YumeAppbar extends HTMLElement {
34
34
  set size(val: string);
35
35
  /** Size variant: "small" | "medium" | "large" (default "medium"). */
36
36
  get size(): string;
37
+ set history(val: string);
38
+ /**
39
+ * Navigation mode: omit for pushState (SPA-friendly), set to "false" for full-page navigation.
40
+ * Regardless of this setting, a cancelable "navigate" event is always dispatched first.
41
+ */
42
+ get history(): string;
37
43
  set sticky(val: string | false);
38
44
  /** Sticky position: "start" | "end" | false. */
39
45
  get sticky(): string | false;
@@ -79,7 +79,12 @@ export namespace Sizes {
79
79
  export function render_2(): string;
80
80
  export { render_2 as render };
81
81
  }
82
- export namespace WithFooter {
83
- export function render_3(): string;
82
+ export namespace NavigateEvent {
83
+ export let name: string;
84
+ export function render_3(): HTMLDivElement;
84
85
  export { render_3 as render };
85
86
  }
87
+ export namespace WithFooter {
88
+ export function render_4(): string;
89
+ export { render_4 as render };
90
+ }
@@ -8,6 +8,7 @@ class YumeButton extends HTMLElement {
8
8
  "disabled", "name", "value", "autofocus", "form", "formaction",
9
9
  "formenctype", "formmethod", "formnovalidate", "formtarget",
10
10
  "aria-label", "aria-pressed", "aria-hidden",
11
+ "href", "target", "rel",
11
12
  ];
12
13
  }
13
14
 
@@ -49,6 +50,27 @@ class YumeButton extends HTMLElement {
49
50
  // Getters / Setters
50
51
  // -------------------------------------------------------------------------
51
52
 
53
+ /** URL to navigate to. When set, the internal element renders as an <a> instead of <button>. */
54
+ get href() { return this.getAttribute("href"); }
55
+ set href(val) {
56
+ if (val != null) this.setAttribute("href", val);
57
+ else this.removeAttribute("href");
58
+ }
59
+
60
+ /** Anchor target (e.g. "_blank"). Only applies when href is set. */
61
+ get target() { return this.getAttribute("target"); }
62
+ set target(val) {
63
+ if (val != null) this.setAttribute("target", val);
64
+ else this.removeAttribute("target");
65
+ }
66
+
67
+ /** Anchor rel attribute (e.g. "noopener noreferrer"). Only applies when href is set. */
68
+ get rel() { return this.getAttribute("rel"); }
69
+ set rel(val) {
70
+ if (val != null) this.setAttribute("rel", val);
71
+ else this.removeAttribute("rel");
72
+ }
73
+
52
74
  /** Color theme for the button (default "base"). */
53
75
  get color() { return this.getAttribute("color") || "base"; }
54
76
  set color(val) { this.setAttribute("color", val); }
@@ -287,9 +309,15 @@ class YumeButton extends HTMLElement {
287
309
  line-height: 1;
288
310
  }
289
311
 
290
- .button:disabled {
312
+ .button {
313
+ text-decoration: none;
314
+ }
315
+
316
+ .button:disabled,
317
+ .button[aria-disabled="true"] {
291
318
  opacity: 0.5;
292
319
  cursor: not-allowed;
320
+ pointer-events: none;
293
321
  }
294
322
 
295
323
  .button:hover:not(:disabled),
@@ -419,23 +447,49 @@ class YumeButton extends HTMLElement {
419
447
  }
420
448
 
421
449
  _render() {
450
+ const needsAnchor = this.hasAttribute("href");
451
+ const isAnchor = this.button?.tagName === "A";
452
+
453
+ if (this.button && needsAnchor !== isAnchor) {
454
+ this.button.remove();
455
+ this.button = null;
456
+ }
457
+
422
458
  if (!this.button) {
423
- this.button = document.createElement("button");
459
+ this.button = needsAnchor
460
+ ? document.createElement("a")
461
+ : document.createElement("button");
424
462
  this.button.classList.add("button");
425
- this.button.setAttribute("role", "button");
426
- this.button.setAttribute("tabindex", "0");
427
463
  this.button.setAttribute("part", "button");
464
+ if (!needsAnchor) {
465
+ this.button.setAttribute("role", "button");
466
+ this.button.setAttribute("tabindex", "0");
467
+ }
428
468
  this.shadowRoot.appendChild(this.button);
429
469
  }
430
470
 
431
471
  this._updateButtonAttributes();
432
472
 
433
- if (this.hasAttribute("disabled")) {
434
- this.button.setAttribute("disabled", "");
435
- this.button.setAttribute("aria-disabled", "true");
473
+ const disabled = this.hasAttribute("disabled");
474
+ if (needsAnchor) {
475
+ // <a> has no native disabled — manage via aria and href removal
476
+ if (disabled) {
477
+ this.button.removeAttribute("href");
478
+ this.button.setAttribute("aria-disabled", "true");
479
+ this.button.setAttribute("tabindex", "-1");
480
+ } else {
481
+ this.button.setAttribute("href", this.getAttribute("href"));
482
+ this.button.setAttribute("aria-disabled", "false");
483
+ this.button.removeAttribute("tabindex");
484
+ }
436
485
  } else {
437
- this.button.removeAttribute("disabled");
438
- this.button.setAttribute("aria-disabled", "false");
486
+ if (disabled) {
487
+ this.button.setAttribute("disabled", "");
488
+ this.button.setAttribute("aria-disabled", "true");
489
+ } else {
490
+ this.button.removeAttribute("disabled");
491
+ this.button.setAttribute("aria-disabled", "false");
492
+ }
439
493
  }
440
494
 
441
495
  this.button.innerHTML = `
@@ -450,9 +504,17 @@ class YumeButton extends HTMLElement {
450
504
  }
451
505
 
452
506
  _updateButtonAttributes() {
453
- const attributes = YumeButton.observedAttributes;
507
+ const isAnchor = this.button?.tagName === "A";
508
+ // These are only meaningful on <button>
509
+ const buttonOnlyAttrs = new Set(["type", "disabled", "name", "value", "autofocus", "form", "formaction", "formenctype", "formmethod", "formnovalidate", "formtarget"]);
510
+ // These are only meaningful on <a>; href is managed separately in _render
511
+ const anchorOnlyAttrs = new Set(["href", "target", "rel"]);
512
+
513
+ YumeButton.observedAttributes.forEach((attr) => {
514
+ if (isAnchor && buttonOnlyAttrs.has(attr)) return;
515
+ if (isAnchor && attr === "href") return; // handled in _render (disabled-aware)
516
+ if (!isAnchor && anchorOnlyAttrs.has(attr)) return;
454
517
 
455
- attributes.forEach((attr) => {
456
518
  if (this.hasAttribute(attr)) {
457
519
  this.button.setAttribute(attr, this.getAttribute(attr));
458
520
  } else {
@@ -732,7 +794,7 @@ var menu = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill
732
794
 
733
795
  class YumeMenu extends HTMLElement {
734
796
  static get observedAttributes() {
735
- return ["items", "anchor", "visible", "direction", "size"];
797
+ return ["items", "anchor", "visible", "direction", "size", "history"];
736
798
  }
737
799
 
738
800
  // -------------------------------------------------------------------------
@@ -810,6 +872,16 @@ class YumeMenu extends HTMLElement {
810
872
  this.setAttribute("items", Array.isArray(val) ? JSON.stringify(val) : (val ?? "[]"));
811
873
  }
812
874
 
875
+ /**
876
+ * Navigation mode: omit for pushState (SPA-friendly), set to "false" for full-page navigation.
877
+ * Regardless of this setting, a cancelable "navigate" event is always dispatched first.
878
+ */
879
+ get history() { return this.getAttribute("history"); }
880
+ set history(val) {
881
+ if (val != null) this.setAttribute("history", val);
882
+ else this.removeAttribute("history");
883
+ }
884
+
813
885
  /** Size: "small" | "medium" | "large" (default "medium"). */
814
886
  get size() {
815
887
  const sz = this.getAttribute("size");
@@ -962,7 +1034,20 @@ class YumeMenu extends HTMLElement {
962
1034
 
963
1035
  if (item.url) {
964
1036
  li.addEventListener("click", () => {
965
- window.location.href = item.url;
1037
+ const event = new CustomEvent("navigate", {
1038
+ bubbles: true,
1039
+ composed: true,
1040
+ cancelable: true,
1041
+ detail: { href: item.url },
1042
+ });
1043
+ const cancelled = !this.dispatchEvent(event);
1044
+ if (cancelled) return;
1045
+ if (this.getAttribute("history") !== "false") {
1046
+ history.pushState({}, "", item.url);
1047
+ window.dispatchEvent(new PopStateEvent("popstate", { state: {} }));
1048
+ } else {
1049
+ window.location.href = item.url;
1050
+ }
966
1051
  });
967
1052
  }
968
1053
 
@@ -1143,6 +1228,7 @@ class YumeAppbar extends HTMLElement {
1143
1228
  "menu-direction",
1144
1229
  "sticky",
1145
1230
  "mobile-breakpoint",
1231
+ "history",
1146
1232
  ];
1147
1233
  }
1148
1234
 
@@ -1229,6 +1315,16 @@ class YumeAppbar extends HTMLElement {
1229
1315
  get size() { return this.getAttribute("size") || "medium"; }
1230
1316
  set size(val) { this.setAttribute("size", val); }
1231
1317
 
1318
+ /**
1319
+ * Navigation mode: omit for pushState (SPA-friendly), set to "false" for full-page navigation.
1320
+ * Regardless of this setting, a cancelable "navigate" event is always dispatched first.
1321
+ */
1322
+ get history() { return this.getAttribute("history"); }
1323
+ set history(val) {
1324
+ if (val != null) this.setAttribute("history", val);
1325
+ else this.removeAttribute("history");
1326
+ }
1327
+
1232
1328
  /** Sticky position: "start" | "end" | false. */
1233
1329
  get sticky() {
1234
1330
  const val = this.getAttribute("sticky");
@@ -1346,7 +1442,20 @@ class YumeAppbar extends HTMLElement {
1346
1442
 
1347
1443
  if (item.href && !hasChildren) {
1348
1444
  btn.addEventListener("click", () => {
1349
- window.location.href = item.href;
1445
+ const event = new CustomEvent("navigate", {
1446
+ bubbles: true,
1447
+ composed: true,
1448
+ cancelable: true,
1449
+ detail: { href: item.href },
1450
+ });
1451
+ const cancelled = !this.dispatchEvent(event);
1452
+ if (cancelled) return;
1453
+ if (this.getAttribute("history") !== "false") {
1454
+ history.pushState({}, "", item.href);
1455
+ window.dispatchEvent(new PopStateEvent("popstate", { state: {} }));
1456
+ } else {
1457
+ window.location.href = item.href;
1458
+ }
1350
1459
  });
1351
1460
  }
1352
1461
 
@@ -3,6 +3,15 @@ export class YumeButton extends HTMLElement {
3
3
  selectedValues: Set<any>;
4
4
  connectedCallback(): void;
5
5
  attributeChangedCallback(name: any, oldValue: any, newValue: any): void;
6
+ set href(val: string);
7
+ /** URL to navigate to. When set, the internal element renders as an <a> instead of <button>. */
8
+ get href(): string;
9
+ set target(val: string);
10
+ /** Anchor target (e.g. "_blank"). Only applies when href is set. */
11
+ get target(): string;
12
+ set rel(val: string);
13
+ /** Anchor rel attribute (e.g. "noopener noreferrer"). Only applies when href is set. */
14
+ get rel(): string;
6
15
  set color(val: string);
7
16
  /** Color theme for the button (default "base"). */
8
17
  get color(): string;
@@ -50,7 +59,7 @@ export class YumeButton extends HTMLElement {
50
59
  _manageSlotVisibility(slotName: any, selector: any): void;
51
60
  _proxyNativeOnClick(): void;
52
61
  _render(): void;
53
- button: HTMLButtonElement;
62
+ button: any;
54
63
  _updateButtonAttributes(): void;
55
64
  _updateStyles(): void;
56
65
  }
@@ -129,3 +129,8 @@ export namespace Disabled {
129
129
  }
130
130
  export { args_1 as args };
131
131
  }
132
+ export namespace AsLink {
133
+ export let name: string;
134
+ export function render_5(): string;
135
+ export { render_5 as render };
136
+ }
@@ -7,6 +7,7 @@ class YumeButton extends HTMLElement {
7
7
  "disabled", "name", "value", "autofocus", "form", "formaction",
8
8
  "formenctype", "formmethod", "formnovalidate", "formtarget",
9
9
  "aria-label", "aria-pressed", "aria-hidden",
10
+ "href", "target", "rel",
10
11
  ];
11
12
  }
12
13
 
@@ -48,6 +49,27 @@ class YumeButton extends HTMLElement {
48
49
  // Getters / Setters
49
50
  // -------------------------------------------------------------------------
50
51
 
52
+ /** URL to navigate to. When set, the internal element renders as an <a> instead of <button>. */
53
+ get href() { return this.getAttribute("href"); }
54
+ set href(val) {
55
+ if (val != null) this.setAttribute("href", val);
56
+ else this.removeAttribute("href");
57
+ }
58
+
59
+ /** Anchor target (e.g. "_blank"). Only applies when href is set. */
60
+ get target() { return this.getAttribute("target"); }
61
+ set target(val) {
62
+ if (val != null) this.setAttribute("target", val);
63
+ else this.removeAttribute("target");
64
+ }
65
+
66
+ /** Anchor rel attribute (e.g. "noopener noreferrer"). Only applies when href is set. */
67
+ get rel() { return this.getAttribute("rel"); }
68
+ set rel(val) {
69
+ if (val != null) this.setAttribute("rel", val);
70
+ else this.removeAttribute("rel");
71
+ }
72
+
51
73
  /** Color theme for the button (default "base"). */
52
74
  get color() { return this.getAttribute("color") || "base"; }
53
75
  set color(val) { this.setAttribute("color", val); }
@@ -286,9 +308,15 @@ class YumeButton extends HTMLElement {
286
308
  line-height: 1;
287
309
  }
288
310
 
289
- .button:disabled {
311
+ .button {
312
+ text-decoration: none;
313
+ }
314
+
315
+ .button:disabled,
316
+ .button[aria-disabled="true"] {
290
317
  opacity: 0.5;
291
318
  cursor: not-allowed;
319
+ pointer-events: none;
292
320
  }
293
321
 
294
322
  .button:hover:not(:disabled),
@@ -418,23 +446,49 @@ class YumeButton extends HTMLElement {
418
446
  }
419
447
 
420
448
  _render() {
449
+ const needsAnchor = this.hasAttribute("href");
450
+ const isAnchor = this.button?.tagName === "A";
451
+
452
+ if (this.button && needsAnchor !== isAnchor) {
453
+ this.button.remove();
454
+ this.button = null;
455
+ }
456
+
421
457
  if (!this.button) {
422
- this.button = document.createElement("button");
458
+ this.button = needsAnchor
459
+ ? document.createElement("a")
460
+ : document.createElement("button");
423
461
  this.button.classList.add("button");
424
- this.button.setAttribute("role", "button");
425
- this.button.setAttribute("tabindex", "0");
426
462
  this.button.setAttribute("part", "button");
463
+ if (!needsAnchor) {
464
+ this.button.setAttribute("role", "button");
465
+ this.button.setAttribute("tabindex", "0");
466
+ }
427
467
  this.shadowRoot.appendChild(this.button);
428
468
  }
429
469
 
430
470
  this._updateButtonAttributes();
431
471
 
432
- if (this.hasAttribute("disabled")) {
433
- this.button.setAttribute("disabled", "");
434
- this.button.setAttribute("aria-disabled", "true");
472
+ const disabled = this.hasAttribute("disabled");
473
+ if (needsAnchor) {
474
+ // <a> has no native disabled — manage via aria and href removal
475
+ if (disabled) {
476
+ this.button.removeAttribute("href");
477
+ this.button.setAttribute("aria-disabled", "true");
478
+ this.button.setAttribute("tabindex", "-1");
479
+ } else {
480
+ this.button.setAttribute("href", this.getAttribute("href"));
481
+ this.button.setAttribute("aria-disabled", "false");
482
+ this.button.removeAttribute("tabindex");
483
+ }
435
484
  } else {
436
- this.button.removeAttribute("disabled");
437
- this.button.setAttribute("aria-disabled", "false");
485
+ if (disabled) {
486
+ this.button.setAttribute("disabled", "");
487
+ this.button.setAttribute("aria-disabled", "true");
488
+ } else {
489
+ this.button.removeAttribute("disabled");
490
+ this.button.setAttribute("aria-disabled", "false");
491
+ }
438
492
  }
439
493
 
440
494
  this.button.innerHTML = `
@@ -449,9 +503,17 @@ class YumeButton extends HTMLElement {
449
503
  }
450
504
 
451
505
  _updateButtonAttributes() {
452
- const attributes = YumeButton.observedAttributes;
506
+ const isAnchor = this.button?.tagName === "A";
507
+ // These are only meaningful on <button>
508
+ const buttonOnlyAttrs = new Set(["type", "disabled", "name", "value", "autofocus", "form", "formaction", "formenctype", "formmethod", "formnovalidate", "formtarget"]);
509
+ // These are only meaningful on <a>; href is managed separately in _render
510
+ const anchorOnlyAttrs = new Set(["href", "target", "rel"]);
511
+
512
+ YumeButton.observedAttributes.forEach((attr) => {
513
+ if (isAnchor && buttonOnlyAttrs.has(attr)) return;
514
+ if (isAnchor && attr === "href") return; // handled in _render (disabled-aware)
515
+ if (!isAnchor && anchorOnlyAttrs.has(attr)) return;
453
516
 
454
- attributes.forEach((attr) => {
455
517
  if (this.hasAttribute(attr)) {
456
518
  this.button.setAttribute(attr, this.getAttribute(attr));
457
519
  } else {
@@ -8,6 +8,7 @@ class YumeButton extends HTMLElement {
8
8
  "disabled", "name", "value", "autofocus", "form", "formaction",
9
9
  "formenctype", "formmethod", "formnovalidate", "formtarget",
10
10
  "aria-label", "aria-pressed", "aria-hidden",
11
+ "href", "target", "rel",
11
12
  ];
12
13
  }
13
14
 
@@ -49,6 +50,27 @@ class YumeButton extends HTMLElement {
49
50
  // Getters / Setters
50
51
  // -------------------------------------------------------------------------
51
52
 
53
+ /** URL to navigate to. When set, the internal element renders as an <a> instead of <button>. */
54
+ get href() { return this.getAttribute("href"); }
55
+ set href(val) {
56
+ if (val != null) this.setAttribute("href", val);
57
+ else this.removeAttribute("href");
58
+ }
59
+
60
+ /** Anchor target (e.g. "_blank"). Only applies when href is set. */
61
+ get target() { return this.getAttribute("target"); }
62
+ set target(val) {
63
+ if (val != null) this.setAttribute("target", val);
64
+ else this.removeAttribute("target");
65
+ }
66
+
67
+ /** Anchor rel attribute (e.g. "noopener noreferrer"). Only applies when href is set. */
68
+ get rel() { return this.getAttribute("rel"); }
69
+ set rel(val) {
70
+ if (val != null) this.setAttribute("rel", val);
71
+ else this.removeAttribute("rel");
72
+ }
73
+
52
74
  /** Color theme for the button (default "base"). */
53
75
  get color() { return this.getAttribute("color") || "base"; }
54
76
  set color(val) { this.setAttribute("color", val); }
@@ -287,9 +309,15 @@ class YumeButton extends HTMLElement {
287
309
  line-height: 1;
288
310
  }
289
311
 
290
- .button:disabled {
312
+ .button {
313
+ text-decoration: none;
314
+ }
315
+
316
+ .button:disabled,
317
+ .button[aria-disabled="true"] {
291
318
  opacity: 0.5;
292
319
  cursor: not-allowed;
320
+ pointer-events: none;
293
321
  }
294
322
 
295
323
  .button:hover:not(:disabled),
@@ -419,23 +447,49 @@ class YumeButton extends HTMLElement {
419
447
  }
420
448
 
421
449
  _render() {
450
+ const needsAnchor = this.hasAttribute("href");
451
+ const isAnchor = this.button?.tagName === "A";
452
+
453
+ if (this.button && needsAnchor !== isAnchor) {
454
+ this.button.remove();
455
+ this.button = null;
456
+ }
457
+
422
458
  if (!this.button) {
423
- this.button = document.createElement("button");
459
+ this.button = needsAnchor
460
+ ? document.createElement("a")
461
+ : document.createElement("button");
424
462
  this.button.classList.add("button");
425
- this.button.setAttribute("role", "button");
426
- this.button.setAttribute("tabindex", "0");
427
463
  this.button.setAttribute("part", "button");
464
+ if (!needsAnchor) {
465
+ this.button.setAttribute("role", "button");
466
+ this.button.setAttribute("tabindex", "0");
467
+ }
428
468
  this.shadowRoot.appendChild(this.button);
429
469
  }
430
470
 
431
471
  this._updateButtonAttributes();
432
472
 
433
- if (this.hasAttribute("disabled")) {
434
- this.button.setAttribute("disabled", "");
435
- this.button.setAttribute("aria-disabled", "true");
473
+ const disabled = this.hasAttribute("disabled");
474
+ if (needsAnchor) {
475
+ // <a> has no native disabled — manage via aria and href removal
476
+ if (disabled) {
477
+ this.button.removeAttribute("href");
478
+ this.button.setAttribute("aria-disabled", "true");
479
+ this.button.setAttribute("tabindex", "-1");
480
+ } else {
481
+ this.button.setAttribute("href", this.getAttribute("href"));
482
+ this.button.setAttribute("aria-disabled", "false");
483
+ this.button.removeAttribute("tabindex");
484
+ }
436
485
  } else {
437
- this.button.removeAttribute("disabled");
438
- this.button.setAttribute("aria-disabled", "false");
486
+ if (disabled) {
487
+ this.button.setAttribute("disabled", "");
488
+ this.button.setAttribute("aria-disabled", "true");
489
+ } else {
490
+ this.button.removeAttribute("disabled");
491
+ this.button.setAttribute("aria-disabled", "false");
492
+ }
439
493
  }
440
494
 
441
495
  this.button.innerHTML = `
@@ -450,9 +504,17 @@ class YumeButton extends HTMLElement {
450
504
  }
451
505
 
452
506
  _updateButtonAttributes() {
453
- const attributes = YumeButton.observedAttributes;
507
+ const isAnchor = this.button?.tagName === "A";
508
+ // These are only meaningful on <button>
509
+ const buttonOnlyAttrs = new Set(["type", "disabled", "name", "value", "autofocus", "form", "formaction", "formenctype", "formmethod", "formnovalidate", "formtarget"]);
510
+ // These are only meaningful on <a>; href is managed separately in _render
511
+ const anchorOnlyAttrs = new Set(["href", "target", "rel"]);
512
+
513
+ YumeButton.observedAttributes.forEach((attr) => {
514
+ if (isAnchor && buttonOnlyAttrs.has(attr)) return;
515
+ if (isAnchor && attr === "href") return; // handled in _render (disabled-aware)
516
+ if (!isAnchor && anchorOnlyAttrs.has(attr)) return;
454
517
 
455
- attributes.forEach((attr) => {
456
518
  if (this.hasAttribute(attr)) {
457
519
  this.button.setAttribute(attr, this.getAttribute(attr));
458
520
  } else {