@nectary/components 5.29.2 → 5.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bundle.js CHANGED
@@ -2348,9 +2348,12 @@ class Button extends NectaryElement {
2348
2348
  super.connectedCallback();
2349
2349
  this.#controller = new AbortController();
2350
2350
  const { signal } = this.#controller;
2351
- this.setAttribute("role", "button");
2352
- this.#internals.role = "button";
2353
- this.tabIndex = 0;
2351
+ if (!this.hasAttribute("tabindex")) {
2352
+ this.setAttribute("tabindex", "0");
2353
+ }
2354
+ if (!this.hasAttribute("role")) {
2355
+ this.setAttribute("role", "button");
2356
+ }
2354
2357
  this.addEventListener("click", this.#onButtonClick, { signal });
2355
2358
  this.addEventListener("focus", this.#onButtonFocus, { signal });
2356
2359
  this.addEventListener("blur", this.#onButtonBlur, { signal });
@@ -2374,7 +2377,9 @@ class Button extends NectaryElement {
2374
2377
  "toggled",
2375
2378
  "size",
2376
2379
  "data-size",
2377
- "data-managed-aria-disabled"
2380
+ "data-managed-aria-disabled",
2381
+ "role",
2382
+ "tabindex"
2378
2383
  ];
2379
2384
  }
2380
2385
  attributeChangedCallback(name, oldVal, newVal) {
@@ -2412,6 +2417,33 @@ class Button extends NectaryElement {
2412
2417
  this.#onSizeUpdate();
2413
2418
  break;
2414
2419
  }
2420
+ case "role": {
2421
+ if (isAttrEqual(oldVal, newVal)) {
2422
+ break;
2423
+ }
2424
+ const effectiveRole = newVal !== null && newVal !== "" ? newVal : "button";
2425
+ this.#internals.role = effectiveRole;
2426
+ if (newVal === null || newVal === "") {
2427
+ this.setAttribute("role", "button");
2428
+ }
2429
+ break;
2430
+ }
2431
+ case "tabindex": {
2432
+ if (newVal === null) {
2433
+ if (this.isDomConnected) {
2434
+ this.setAttribute("tabindex", "0");
2435
+ }
2436
+ break;
2437
+ }
2438
+ if (isAttrEqual(oldVal, newVal)) {
2439
+ break;
2440
+ }
2441
+ const parsed = Number.parseInt(newVal, 10);
2442
+ if (Number.isNaN(parsed)) {
2443
+ this.setAttribute("tabindex", "0");
2444
+ }
2445
+ break;
2446
+ }
2415
2447
  }
2416
2448
  }
2417
2449
  set type(value) {
package/button/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Context, subscribeContext } from "../utils/context.js";
2
- import { updateAttribute, isAttrEqual, updateBooleanAttribute, isAttrTrue, updateLiteralAttribute, getLiteralAttribute, getAttribute, getBooleanAttribute } from "../utils/dom.js";
2
+ import { isAttrEqual, updateAttribute, updateBooleanAttribute, isAttrTrue, updateLiteralAttribute, getLiteralAttribute, getAttribute, getBooleanAttribute } from "../utils/dom.js";
3
3
  import { defineCustomElement, NectaryElement } from "../utils/element.js";
4
4
  import { getReactEventHandler } from "../utils/get-react-event-handler.js";
5
5
  import { requestSubmitForm } from "../utils/form.js";
@@ -28,9 +28,12 @@ class Button extends NectaryElement {
28
28
  super.connectedCallback();
29
29
  this.#controller = new AbortController();
30
30
  const { signal } = this.#controller;
31
- this.setAttribute("role", "button");
32
- this.#internals.role = "button";
33
- this.tabIndex = 0;
31
+ if (!this.hasAttribute("tabindex")) {
32
+ this.setAttribute("tabindex", "0");
33
+ }
34
+ if (!this.hasAttribute("role")) {
35
+ this.setAttribute("role", "button");
36
+ }
34
37
  this.addEventListener("click", this.#onButtonClick, { signal });
35
38
  this.addEventListener("focus", this.#onButtonFocus, { signal });
36
39
  this.addEventListener("blur", this.#onButtonBlur, { signal });
@@ -54,7 +57,9 @@ class Button extends NectaryElement {
54
57
  "toggled",
55
58
  "size",
56
59
  "data-size",
57
- "data-managed-aria-disabled"
60
+ "data-managed-aria-disabled",
61
+ "role",
62
+ "tabindex"
58
63
  ];
59
64
  }
60
65
  attributeChangedCallback(name, oldVal, newVal) {
@@ -92,6 +97,33 @@ class Button extends NectaryElement {
92
97
  this.#onSizeUpdate();
93
98
  break;
94
99
  }
100
+ case "role": {
101
+ if (isAttrEqual(oldVal, newVal)) {
102
+ break;
103
+ }
104
+ const effectiveRole = newVal !== null && newVal !== "" ? newVal : "button";
105
+ this.#internals.role = effectiveRole;
106
+ if (newVal === null || newVal === "") {
107
+ this.setAttribute("role", "button");
108
+ }
109
+ break;
110
+ }
111
+ case "tabindex": {
112
+ if (newVal === null) {
113
+ if (this.isDomConnected) {
114
+ this.setAttribute("tabindex", "0");
115
+ }
116
+ break;
117
+ }
118
+ if (isAttrEqual(oldVal, newVal)) {
119
+ break;
120
+ }
121
+ const parsed = Number.parseInt(newVal, 10);
122
+ if (Number.isNaN(parsed)) {
123
+ this.setAttribute("tabindex", "0");
124
+ }
125
+ break;
126
+ }
95
127
  }
96
128
  }
97
129
  set type(value) {
package/button/types.d.ts CHANGED
@@ -5,6 +5,10 @@ export type TSinchButtonType = 'primary' | 'secondary'
5
5
  /** @deprecated */
6
6
  | 'tertiary' | 'subtle-primary' | 'subtle-secondary' | 'cta-primary' | 'cta-secondary' | 'destructive';
7
7
  export type TSinchButtonProps = {
8
+ /** ARIA role, `button` by default. Curated union for common use cases; hosts can still set other roles in HTML. */
9
+ role?: 'button' | 'tab' | 'menuitem' | 'switch' | 'link' | 'option';
10
+ /** Keyboard navigation order, `0` by default */
11
+ tabIndex?: number;
8
12
  /** Button Type */
9
13
  type?: TSinchButtonType;
10
14
  /** Size, `m` by default */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nectary/components",
3
- "version": "5.29.2",
3
+ "version": "5.30.0",
4
4
  "files": [
5
5
  "**/*/*.css",
6
6
  "**/*/*.json",