@helixui/library 3.3.1-next.115 → 3.3.1-next.118

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 (129) hide show
  1. package/custom-elements.json +445 -276
  2. package/dist/components/hx-accordion/hx-accordion-item.d.ts +35 -0
  3. package/dist/components/hx-accordion/hx-accordion-item.d.ts.map +1 -1
  4. package/dist/components/hx-checkbox/hx-checkbox.d.ts +153 -1
  5. package/dist/components/hx-checkbox/hx-checkbox.d.ts.map +1 -1
  6. package/dist/components/hx-checkbox/hx-checkbox.styles.d.ts.map +1 -1
  7. package/dist/components/hx-checkbox/index.js +1 -1
  8. package/dist/components/hx-checkbox-group/hx-checkbox-group.d.ts +151 -2
  9. package/dist/components/hx-checkbox-group/hx-checkbox-group.d.ts.map +1 -1
  10. package/dist/components/hx-checkbox-group/index.js +1 -1
  11. package/dist/components/hx-color-picker/hx-color-picker.d.ts +163 -1
  12. package/dist/components/hx-color-picker/hx-color-picker.d.ts.map +1 -1
  13. package/dist/components/hx-color-picker/hx-color-picker.styles.d.ts.map +1 -1
  14. package/dist/components/hx-color-picker/index.js +1 -1
  15. package/dist/components/hx-combobox/hx-combobox.d.ts +311 -2
  16. package/dist/components/hx-combobox/hx-combobox.d.ts.map +1 -1
  17. package/dist/components/hx-combobox/index.js +1 -1
  18. package/dist/components/hx-date-picker/hx-date-picker.d.ts +182 -56
  19. package/dist/components/hx-date-picker/hx-date-picker.d.ts.map +1 -1
  20. package/dist/components/hx-date-picker/hx-date-picker.styles.d.ts.map +1 -1
  21. package/dist/components/hx-date-picker/index.js +1 -1
  22. package/dist/components/hx-dialog/hx-dialog.d.ts +240 -0
  23. package/dist/components/hx-dialog/hx-dialog.d.ts.map +1 -1
  24. package/dist/components/hx-dialog/index.js +1 -1
  25. package/dist/components/hx-dropdown/hx-dropdown.d.ts +80 -0
  26. package/dist/components/hx-dropdown/hx-dropdown.d.ts.map +1 -1
  27. package/dist/components/hx-dropdown/index.js +1 -1
  28. package/dist/components/hx-field/hx-field.d.ts +109 -0
  29. package/dist/components/hx-field/hx-field.d.ts.map +1 -1
  30. package/dist/components/hx-field/index.js +1 -1
  31. package/dist/components/hx-popover/hx-popover.d.ts +91 -0
  32. package/dist/components/hx-popover/hx-popover.d.ts.map +1 -1
  33. package/dist/components/hx-popover/index.js +1 -1
  34. package/dist/components/hx-radio-group/hx-radio-group.d.ts +152 -1
  35. package/dist/components/hx-radio-group/hx-radio-group.d.ts.map +1 -1
  36. package/dist/components/hx-radio-group/hx-radio.d.ts +14 -0
  37. package/dist/components/hx-radio-group/hx-radio.d.ts.map +1 -1
  38. package/dist/components/hx-radio-group/index.js +1 -1
  39. package/dist/components/hx-select/hx-select.d.ts +303 -2
  40. package/dist/components/hx-select/hx-select.d.ts.map +1 -1
  41. package/dist/components/hx-select/hx-select.styles.d.ts.map +1 -1
  42. package/dist/components/hx-select/index.js +1 -1
  43. package/dist/components/hx-side-nav/hx-nav-item.styles.d.ts.map +1 -1
  44. package/dist/components/hx-side-nav/index.js +1 -1
  45. package/dist/components/hx-switch/hx-switch.d.ts +78 -1
  46. package/dist/components/hx-switch/hx-switch.d.ts.map +1 -1
  47. package/dist/components/hx-switch/hx-switch.styles.d.ts.map +1 -1
  48. package/dist/components/hx-switch/index.js +1 -1
  49. package/dist/components/hx-toggle-button/hx-toggle-button.d.ts +110 -0
  50. package/dist/components/hx-toggle-button/hx-toggle-button.d.ts.map +1 -1
  51. package/dist/components/hx-toggle-button/hx-toggle-button.styles.d.ts.map +1 -1
  52. package/dist/components/hx-toggle-button/index.js +1 -1
  53. package/dist/components/hx-tooltip/hx-tooltip.d.ts +52 -0
  54. package/dist/components/hx-tooltip/hx-tooltip.d.ts.map +1 -1
  55. package/dist/components/hx-tooltip/index.js +1 -1
  56. package/dist/css/helix-all.css +98 -1
  57. package/dist/css/helix-forms.css +98 -1
  58. package/dist/css/hx-checkbox.css +18 -0
  59. package/dist/css/hx-color-picker.css +25 -0
  60. package/dist/css/hx-date-picker.css +2 -1
  61. package/dist/css/hx-select.css +19 -0
  62. package/dist/css/hx-switch.css +17 -0
  63. package/dist/css/hx-toggle-button.css +17 -0
  64. package/dist/css/index.css +1 -1
  65. package/dist/css/manifest.json +2 -1
  66. package/dist/index.js +15 -15
  67. package/dist/shared/aria-flatten-DY6v2vah.js +22 -0
  68. package/dist/shared/aria-flatten-DY6v2vah.js.map +1 -0
  69. package/dist/shared/aria-idref-Q0yiSR3p.js +104 -0
  70. package/dist/shared/aria-idref-Q0yiSR3p.js.map +1 -0
  71. package/dist/shared/hx-accordion-ZVzgDzTG.js.map +1 -1
  72. package/dist/shared/hx-checkbox-BdgoUeWi.js +696 -0
  73. package/dist/shared/hx-checkbox-BdgoUeWi.js.map +1 -0
  74. package/dist/shared/hx-checkbox-group-LWezHrvS.js +496 -0
  75. package/dist/shared/hx-checkbox-group-LWezHrvS.js.map +1 -0
  76. package/dist/shared/hx-color-picker-DVhZl88b.js +1221 -0
  77. package/dist/shared/hx-color-picker-DVhZl88b.js.map +1 -0
  78. package/dist/shared/hx-combobox-DvlezcDV.js +1359 -0
  79. package/dist/shared/hx-combobox-DvlezcDV.js.map +1 -0
  80. package/dist/shared/{hx-date-picker-2iRG1p74.js → hx-date-picker-N-0aG5XL.js} +542 -206
  81. package/dist/shared/hx-date-picker-N-0aG5XL.js.map +1 -0
  82. package/dist/shared/hx-dialog-DzB7VytW.js +717 -0
  83. package/dist/shared/hx-dialog-DzB7VytW.js.map +1 -0
  84. package/dist/shared/{hx-dropdown-LyaRc8Rf.js → hx-dropdown-DJWlF94E.js} +130 -77
  85. package/dist/shared/hx-dropdown-DJWlF94E.js.map +1 -0
  86. package/dist/shared/{hx-field-B3Qo8OLS.js → hx-field-zw0U1KVi.js} +99 -38
  87. package/dist/shared/hx-field-zw0U1KVi.js.map +1 -0
  88. package/dist/shared/{hx-nav-item-xqRPOCWX.js → hx-nav-item-CODtUlew.js} +13 -9
  89. package/dist/shared/{hx-nav-item-xqRPOCWX.js.map → hx-nav-item-CODtUlew.js.map} +1 -1
  90. package/dist/shared/{hx-popover-B-FP3-wW.js → hx-popover-CHxWY_cd.js} +123 -66
  91. package/dist/shared/hx-popover-CHxWY_cd.js.map +1 -0
  92. package/dist/shared/hx-radio-CeGzARNk.js +822 -0
  93. package/dist/shared/hx-radio-CeGzARNk.js.map +1 -0
  94. package/dist/shared/hx-select-DrcS-YRJ.js +1089 -0
  95. package/dist/shared/hx-select-DrcS-YRJ.js.map +1 -0
  96. package/dist/shared/hx-switch-BX_8uNUs.js +540 -0
  97. package/dist/shared/hx-switch-BX_8uNUs.js.map +1 -0
  98. package/dist/shared/{hx-toggle-button-iLiYrMbD.js → hx-toggle-button-Dcz9IlUm.js} +226 -65
  99. package/dist/shared/hx-toggle-button-Dcz9IlUm.js.map +1 -0
  100. package/dist/shared/{hx-tooltip-nYOv9OLu.js → hx-tooltip-DVqtKPCD.js} +68 -46
  101. package/dist/shared/hx-tooltip-DVqtKPCD.js.map +1 -0
  102. package/dist/utils/aria-flatten.d.ts +56 -0
  103. package/dist/utils/aria-flatten.d.ts.map +1 -0
  104. package/dist/utils/aria-idref.d.ts +127 -0
  105. package/dist/utils/aria-idref.d.ts.map +1 -0
  106. package/figma-inventory.json +64 -1
  107. package/package.json +2 -2
  108. package/dist/shared/hx-checkbox-D7xma9YH.js +0 -524
  109. package/dist/shared/hx-checkbox-D7xma9YH.js.map +0 -1
  110. package/dist/shared/hx-checkbox-group-C9n315Ju.js +0 -323
  111. package/dist/shared/hx-checkbox-group-C9n315Ju.js.map +0 -1
  112. package/dist/shared/hx-color-picker-uRc865FJ.js +0 -882
  113. package/dist/shared/hx-color-picker-uRc865FJ.js.map +0 -1
  114. package/dist/shared/hx-combobox-DDzqNKEW.js +0 -924
  115. package/dist/shared/hx-combobox-DDzqNKEW.js.map +0 -1
  116. package/dist/shared/hx-date-picker-2iRG1p74.js.map +0 -1
  117. package/dist/shared/hx-dialog-DRN_1-Y-.js +0 -514
  118. package/dist/shared/hx-dialog-DRN_1-Y-.js.map +0 -1
  119. package/dist/shared/hx-dropdown-LyaRc8Rf.js.map +0 -1
  120. package/dist/shared/hx-field-B3Qo8OLS.js.map +0 -1
  121. package/dist/shared/hx-popover-B-FP3-wW.js.map +0 -1
  122. package/dist/shared/hx-radio-CJvNU2yP.js +0 -621
  123. package/dist/shared/hx-radio-CJvNU2yP.js.map +0 -1
  124. package/dist/shared/hx-select-C8fEHQhC.js +0 -807
  125. package/dist/shared/hx-select-C8fEHQhC.js.map +0 -1
  126. package/dist/shared/hx-switch-BrZFaRue.js +0 -420
  127. package/dist/shared/hx-switch-BrZFaRue.js.map +0 -1
  128. package/dist/shared/hx-toggle-button-iLiYrMbD.js.map +0 -1
  129. package/dist/shared/hx-tooltip-nYOv9OLu.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { H as t } from "../../shared/hx-toggle-button-iLiYrMbD.js";
1
+ import { H as t } from "../../shared/hx-toggle-button-Dcz9IlUm.js";
2
2
  export {
3
3
  t as HelixToggleButton
4
4
  };
@@ -2,6 +2,37 @@ import { HelixElement } from '../../base/index.js';
2
2
  /**
3
3
  * A tooltip that displays contextual help text on hover or focus.
4
4
  *
5
+ * ## Architecture Note: Light-DOM Description Shim (group-4 round-1)
6
+ *
7
+ * `aria-describedby` IDREFs cannot resolve across the Shadow DOM boundary —
8
+ * the trigger lives in the consumer's light DOM and references a tooltip
9
+ * whose body is in this component's shadow root. The tooltip text must
10
+ * therefore be exposed in DOCUMENT scope.
11
+ *
12
+ * The shim is a single visually-hidden `<span>` appended to `document.body`
13
+ * with the `_tooltipId` as its `id`. The trigger's `aria-describedby` points
14
+ * at this span. The text content is mirrored from the slotted `content`
15
+ * slot on every relevant signal:
16
+ *
17
+ * 1. `firstUpdated` (initial wiring)
18
+ * 2. `slotchange` on the default slot AND the `content` slot (the slotted
19
+ * element list changes)
20
+ * 3. **Text-content mutations on the assigned `content` slot elements**
21
+ * (round-23 P2 pattern). Without this observer a framework that
22
+ * rewrites the slotted `<span slot="content">` `textContent` IN PLACE
23
+ * (Vue / React keyed text rerender) would leave the shim stale.
24
+ *
25
+ * Cleanup: `disconnectedCallback` removes the shim from `document.body`,
26
+ * disconnects the slot-text observer, and clears the timers. SSR is
27
+ * sidestepped by guarding `document` access — the shim is created lazily
28
+ * the first time `_setupTriggerAria()` runs in a browser environment.
29
+ *
30
+ * `role="tooltip"` is the correct APG role and is NEVER promoted to
31
+ * `role="dialog"` — APG explicitly forbids tooltips from holding focus and
32
+ * the tooltip body is not a focus target. No host-canonical `_internals`
33
+ * work is owed: the trigger is the announced surface, and it correctly
34
+ * references the tooltip via `aria-describedby`.
35
+ *
5
36
  * @summary Contextual help text and abbreviations with smart positioning.
6
37
  *
7
38
  * @tag hx-tooltip
@@ -97,11 +128,32 @@ export declare class HelixTooltip extends HelixElement {
97
128
  * @internal
98
129
  */
99
130
  private _lightDomDescription;
131
+ /**
132
+ * Watches in-place text mutations on the elements assigned to the
133
+ * `<slot name="content">`. Without this observer, a framework that
134
+ * rewrites the slotted `<span slot="content">` `textContent` in place
135
+ * would leave the document-scope shim stale — the `slotchange` event
136
+ * does NOT fire on descendant text mutations.
137
+ *
138
+ * The observer is reinstalled on every `_setupTriggerAria()` call against
139
+ * the deduped current set of assigned elements; it is fully torn down in
140
+ * `disconnectedCallback` to prevent leaks on SSR teardown.
141
+ * @internal
142
+ */
143
+ private _contentSlotTextObserver;
100
144
  connectedCallback(): void;
101
145
  disconnectedCallback(): void;
102
146
  firstUpdated(): void;
103
147
  /** @internal */
104
148
  private _setupTriggerAria;
149
+ /**
150
+ * (Re-)installs the slotted-content text observer over the deduped union
151
+ * of assigned `content` slot elements. Disconnects any previous observer
152
+ * before re-attaching so observer count is bounded by component lifetime,
153
+ * not by `slotchange` event count.
154
+ * @internal
155
+ */
156
+ private _installContentSlotTextObserver;
105
157
  /** @internal */
106
158
  private _scheduleShow;
107
159
  /** @internal */
@@ -1 +1 @@
1
- {"version":3,"file":"hx-tooltip.d.ts","sourceRoot":"","sources":["../../../src/components/hx-tooltip/hx-tooltip.ts"],"names":[],"mappings":"AACA,OAAO,4CAA4C,CAAC;AAGpD,OAAO,EAAE,YAAY,EAAmB,MAAM,qBAAqB,CAAC;AAMpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAEH,qBACa,YAAa,SAAQ,YAAY;IAC5C,OAAgB,MAAM,4BAA6C;IAEnE;;;;;OAKG;IAEH,SAAS,EACL,KAAK,GACL,WAAW,GACX,SAAS,GACT,OAAO,GACP,aAAa,GACb,WAAW,GACX,QAAQ,GACR,cAAc,GACd,YAAY,GACZ,MAAM,GACN,YAAY,GACZ,UAAU,CAAS;IAEvB;;;OAGG;IAEH,SAAS,SAAO;IAEhB;;;OAGG;IAEH,SAAS,SAAO;IAEhB,gBAAgB;IACP,OAAO,CAAC,QAAQ,CAAS;IAElC,gBAAgB;IAChB,OAAO,CAAC,UAAU,CAA8C;IAChE,gBAAgB;IAChB,OAAO,CAAC,UAAU,CAA8C;IAEhE,gBAAgB;IAChB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;IAE/C,gBAAgB;IACW,OAAO,CAAC,YAAY,CAA0B;IACzE,gBAAgB;IACe,OAAO,CAAC,YAAY,CAA0B;IAC7E,gBAAgB;IACW,OAAO,CAAC,eAAe,CAAsB;IACxE,gBAAgB;IACW,OAAO,CAAC,UAAU,CAAsB;IACnE,gBAAgB;IACS,OAAO,CAAC,QAAQ,CAAsB;IAE/D;;;;;;OAMG;IACH,OAAO,CAAC,oBAAoB,CAAgC;IAInD,iBAAiB,IAAI,IAAI;IAUzB,oBAAoB,IAAI,IAAI;IAQ5B,YAAY,IAAI,IAAI;IAM7B,gBAAgB;IAChB,OAAO,CAAC,iBAAiB;IAuCzB,gBAAgB;IAChB,OAAO,CAAC,aAAa;IAOrB,gBAAgB;IAChB,OAAO,CAAC,aAAa;IAOrB,gBAAgB;YACF,KAAK;IAMnB,gBAAgB;IAChB,OAAO,CAAC,KAAK;IAIb,gBAAgB;IAChB,OAAO,CAAC,YAAY;IAapB,gBAAgB;YACF,eAAe;IA0C7B,gBAAgB;IAChB,OAAO,CAAC,cAAc,CAMpB;IAEF;;;;;;OAMG;IACH,OAAO,CAAC,wBAAwB;IAavB,MAAM;CAyBhB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,YAAY,EAAE,YAAY,CAAC;KAC5B;CACF"}
1
+ {"version":3,"file":"hx-tooltip.d.ts","sourceRoot":"","sources":["../../../src/components/hx-tooltip/hx-tooltip.ts"],"names":[],"mappings":"AACA,OAAO,4CAA4C,CAAC;AAGpD,OAAO,EAAE,YAAY,EAAmB,MAAM,qBAAqB,CAAC;AAMpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmFG;AAEH,qBACa,YAAa,SAAQ,YAAY;IAC5C,OAAgB,MAAM,4BAA6C;IAEnE;;;;;OAKG;IAEH,SAAS,EACL,KAAK,GACL,WAAW,GACX,SAAS,GACT,OAAO,GACP,aAAa,GACb,WAAW,GACX,QAAQ,GACR,cAAc,GACd,YAAY,GACZ,MAAM,GACN,YAAY,GACZ,UAAU,CAAS;IAEvB;;;OAGG;IAEH,SAAS,SAAO;IAEhB;;;OAGG;IAEH,SAAS,SAAO;IAEhB,gBAAgB;IACP,OAAO,CAAC,QAAQ,CAAS;IAElC,gBAAgB;IAChB,OAAO,CAAC,UAAU,CAA8C;IAChE,gBAAgB;IAChB,OAAO,CAAC,UAAU,CAA8C;IAEhE,gBAAgB;IAChB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;IAE/C,gBAAgB;IACW,OAAO,CAAC,YAAY,CAA0B;IACzE,gBAAgB;IACe,OAAO,CAAC,YAAY,CAA0B;IAC7E,gBAAgB;IACW,OAAO,CAAC,eAAe,CAAsB;IACxE,gBAAgB;IACW,OAAO,CAAC,UAAU,CAAsB;IACnE,gBAAgB;IACS,OAAO,CAAC,QAAQ,CAAsB;IAE/D;;;;;;OAMG;IACH,OAAO,CAAC,oBAAoB,CAAgC;IAE5D;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,wBAAwB,CAAiC;IAIxD,iBAAiB,IAAI,IAAI;IAUzB,oBAAoB,IAAI,IAAI;IAa5B,YAAY,IAAI,IAAI;IAM7B,gBAAgB;IAChB,OAAO,CAAC,iBAAiB;IA0CzB;;;;;;OAMG;IACH,OAAO,CAAC,+BAA+B;IAsCvC,gBAAgB;IAChB,OAAO,CAAC,aAAa;IAOrB,gBAAgB;IAChB,OAAO,CAAC,aAAa;IAOrB,gBAAgB;YACF,KAAK;IAMnB,gBAAgB;IAChB,OAAO,CAAC,KAAK;IAIb,gBAAgB;IAChB,OAAO,CAAC,YAAY;IAapB,gBAAgB;YACF,eAAe;IA0C7B,gBAAgB;IAChB,OAAO,CAAC,cAAc,CAMpB;IAEF;;;;;;OAMG;IACH,OAAO,CAAC,wBAAwB;IAavB,MAAM;CAyBhB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,YAAY,EAAE,YAAY,CAAC;KAC5B;CACF"}
@@ -1,4 +1,4 @@
1
- import { H as i } from "../../shared/hx-tooltip-nYOv9OLu.js";
1
+ import { H as i } from "../../shared/hx-tooltip-DVqtKPCD.js";
2
2
  export {
3
3
  i as HelixTooltip
4
4
  };
@@ -2080,6 +2080,23 @@
2080
2080
 
2081
2081
  /* ─── Focus Ring ─── */
2082
2082
 
2083
+ /*
2084
+ * Host-focus path: on the modern (IDL element-references) render branch the
2085
+ * host is the tabbable surface (tabindex=0) and the inner input is demoted
2086
+ * to tabindex=-1. Drive the focus ring from ':host(:focus-visible)' so
2087
+ * keyboard users still get a visible affordance. Codex round-11 P1.
2088
+ */
2089
+ :host(:focus-visible) .checkbox__box {
2090
+ outline: var(--hx-checkbox-focus-ring-width, var(--hx-focus-ring-width, 2px)) solid
2091
+ var(--hx-checkbox-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
2092
+ outline-offset: var(--hx-checkbox-focus-ring-offset, var(--hx-focus-ring-offset, 2px));
2093
+ }
2094
+
2095
+ /*
2096
+ * Fallback (no-IDL-ref) path: the host carries tabindex=-1 and the inner
2097
+ * input is the tab target. The native :focus-visible on the input drives
2098
+ * the same visual ring, scoped via the inner-state class.
2099
+ */
2083
2100
  .checkbox__input:focus-visible ~ .checkbox__box {
2084
2101
  outline: var(--hx-checkbox-focus-ring-width, var(--hx-focus-ring-width, 2px)) solid
2085
2102
  var(--hx-checkbox-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
@@ -2234,6 +2251,7 @@
2234
2251
  border: 2px solid ButtonText;
2235
2252
  }
2236
2253
 
2254
+ :host(:focus-visible) .checkbox__box,
2237
2255
  .checkbox__input:focus-visible ~ .checkbox__box {
2238
2256
  outline: 3px solid Highlight;
2239
2257
  outline-offset: 2px;
@@ -2900,6 +2918,31 @@
2900
2918
  pointer-events: none;
2901
2919
  opacity: var(--hx-opacity-disabled, 0.5);
2902
2920
  }
2921
+ /* Slotted label / help / error blocks for cross-shadow naming. */
2922
+ .hx-color-picker__label {
2923
+ display: block;
2924
+ margin-bottom: var(--hx-space-1, 0.25rem);
2925
+ font-weight: var(--hx-font-weight-semibold, 600);
2926
+ color: var(--hx-color-neutral-900, #1a1a1a);
2927
+ }
2928
+ .hx-color-picker__label:empty {
2929
+ display: none;
2930
+ }
2931
+ .hx-color-picker__help {
2932
+ display: block;
2933
+ margin-top: var(--hx-space-1, 0.25rem);
2934
+ font-size: var(--hx-font-size-xs, 0.75rem);
2935
+ color: var(--hx-color-neutral-600, #525252);
2936
+ }
2937
+ .hx-color-picker__error {
2938
+ display: block;
2939
+ margin-top: var(--hx-space-1, 0.25rem);
2940
+ font-size: var(--hx-font-size-xs, 0.75rem);
2941
+ color: var(--hx-color-danger-700, #c43e3e);
2942
+ }
2943
+ [hidden] {
2944
+ display: none !important;
2945
+ }
2903
2946
  .trigger {
2904
2947
  display: inline-flex;
2905
2948
  align-items: center;
@@ -4426,7 +4469,8 @@
4426
4469
  Live region (screen reader announcements)
4427
4470
  ============================================================ */
4428
4471
 
4429
- .calendar__live-region {
4472
+ .calendar__live-region,
4473
+ .field__sr-only {
4430
4474
  position: absolute;
4431
4475
  width: 1px;
4432
4476
  height: 1px;
@@ -8298,6 +8342,11 @@ export const helixGridItemStyles = css`
8298
8342
  /* ─── 3-tier token cascade: component → semantic → hardcoded fallback ─── */
8299
8343
  :host {
8300
8344
  display: block;
8345
+ /* Round-3 finding 1: host is the canonical combobox surface, so it owns
8346
+ keyboard focus. Suppress the UA default outline; the custom focus ring
8347
+ is painted on the inner trigger via :host(:focus-visible)
8348
+ .field__trigger so visual feedback follows the host's focus state. */
8349
+ outline: none;
8301
8350
 
8302
8351
  /* Background & foreground */
8303
8352
  --_bg: var(--hx-select-bg, var(--hx-color-surface-default, #ffffff));
@@ -8374,6 +8423,12 @@ export const helixGridItemStyles = css`
8374
8423
  }
8375
8424
 
8376
8425
  .field__trigger {
8426
+ /* Round-3 finding 1 / CodeRabbit F1: trigger is a <button type="button">
8427
+ (labelable) so native <label for> click activation works for mouse
8428
+ users. Reset native button chrome before applying field styles. */
8429
+ appearance: none;
8430
+ -webkit-appearance: none;
8431
+ margin: 0;
8377
8432
  display: flex;
8378
8433
  align-items: center;
8379
8434
  justify-content: space-between;
@@ -8384,6 +8439,7 @@ export const helixGridItemStyles = css`
8384
8439
  border-radius: var(--_border-radius);
8385
8440
  background-color: var(--_bg);
8386
8441
  color: var(--_color);
8442
+ font: inherit;
8387
8443
  font-family: inherit;
8388
8444
  font-size: var(--hx-font-size-md, 1rem);
8389
8445
  line-height: var(--hx-line-height-normal, 1.5);
@@ -8396,6 +8452,11 @@ export const helixGridItemStyles = css`
8396
8452
  outline: none;
8397
8453
  }
8398
8454
 
8455
+ /* Round-3 finding 1: host is the canonical focusable surface. Both the
8456
+ :host(:focus-visible) descendant selector AND the legacy
8457
+ .field__trigger:focus-visible (kept for forced-colors regression test
8458
+ parity) paint the focus ring on the visual trigger. */
8459
+ :host(:focus-visible) .field__trigger,
8399
8460
  .field__trigger:focus-visible {
8400
8461
  border-color: var(--_focus-ring-color);
8401
8462
  box-shadow: 0 0 0 var(--hx-focus-ring-width, 2px)
@@ -8464,6 +8525,7 @@ export const helixGridItemStyles = css`
8464
8525
  border-color: var(--_error-color);
8465
8526
  }
8466
8527
 
8528
+ :host(:focus-visible) .field--error .field__trigger,
8467
8529
  .field--error .field__trigger:focus-visible {
8468
8530
  border-color: var(--_error-color);
8469
8531
  box-shadow: 0 0 0 var(--hx-focus-ring-width, 2px)
@@ -8597,6 +8659,7 @@ export const helixGridItemStyles = css`
8597
8659
  border: 2px solid ButtonText;
8598
8660
  }
8599
8661
 
8662
+ :host(:focus-visible) .field__trigger,
8600
8663
  .field__trigger:focus-visible {
8601
8664
  outline: 3px solid Highlight;
8602
8665
  outline-offset: 2px;
@@ -10544,6 +10607,22 @@ export const helixStructuredListRowStyles = css`
10544
10607
  appearance: none;
10545
10608
  }
10546
10609
 
10610
+ /*
10611
+ * Host-focus path: on the modern (IDL element-references) render branch the
10612
+ * host is the tabbable surface (tabindex=0) and the inner track button is
10613
+ * demoted to tabindex=-1. Drive the focus ring from ':host(:focus-visible)'
10614
+ * so keyboard users still see a visible affordance. Codex round-11 P1.
10615
+ */
10616
+ :host(:focus-visible) .switch__track {
10617
+ outline: var(--hx-focus-ring-width, 2px) solid
10618
+ var(--hx-switch-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
10619
+ outline-offset: var(--hx-focus-ring-offset, 2px);
10620
+ }
10621
+
10622
+ /*
10623
+ * Fallback (no-IDL-ref) path: the host carries tabindex=-1 and the inner
10624
+ * track button is the tab target. Native :focus-visible drives the ring.
10625
+ */
10547
10626
  .switch__track:focus-visible {
10548
10627
  outline: var(--hx-focus-ring-width, 2px) solid
10549
10628
  var(--hx-switch-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
@@ -10681,6 +10760,7 @@ export const helixStructuredListRowStyles = css`
10681
10760
  border: 2px solid ButtonText;
10682
10761
  }
10683
10762
 
10763
+ :host(:focus-visible) .switch__track,
10684
10764
  .switch__track:focus-visible {
10685
10765
  outline: 3px solid Highlight;
10686
10766
  outline-offset: 2px;
@@ -12483,6 +12563,22 @@ export const helixToastStackStyles = css`
12483
12563
  -webkit-user-select: none;
12484
12564
  }
12485
12565
 
12566
+ /*
12567
+ * Host-focus path: on the modern (IDL element-references) render branch the
12568
+ * host is the tabbable surface (tabindex=0) and the inner <button> is
12569
+ * demoted to tabindex=-1. Drive the focus ring from ':host(:focus-visible)'
12570
+ * so keyboard users still see a visible affordance. Codex round-11 P1.
12571
+ */
12572
+ :host(:focus-visible) .button {
12573
+ outline: var(--hx-focus-ring-width, 2px) solid
12574
+ var(--hx-toggle-button-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
12575
+ outline-offset: var(--hx-focus-ring-offset, 2px);
12576
+ }
12577
+
12578
+ /*
12579
+ * Fallback (no-IDL-ref) path: the host carries tabindex=-1 and the inner
12580
+ * <button> is the tab target. Native :focus-visible drives the ring.
12581
+ */
12486
12582
  .button:focus-visible {
12487
12583
  outline: var(--hx-focus-ring-width, 2px) solid
12488
12584
  var(--hx-toggle-button-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
@@ -12681,6 +12777,7 @@ export const helixToastStackStyles = css`
12681
12777
  border: 2px solid ButtonText;
12682
12778
  }
12683
12779
 
12780
+ :host(:focus-visible) .button,
12684
12781
  .button:focus-visible {
12685
12782
  outline: 3px solid Highlight;
12686
12783
  outline-offset: 2px;
@@ -72,6 +72,23 @@
72
72
 
73
73
  /* ─── Focus Ring ─── */
74
74
 
75
+ /*
76
+ * Host-focus path: on the modern (IDL element-references) render branch the
77
+ * host is the tabbable surface (tabindex=0) and the inner input is demoted
78
+ * to tabindex=-1. Drive the focus ring from ':host(:focus-visible)' so
79
+ * keyboard users still get a visible affordance. Codex round-11 P1.
80
+ */
81
+ :host(:focus-visible) .checkbox__box {
82
+ outline: var(--hx-checkbox-focus-ring-width, var(--hx-focus-ring-width, 2px)) solid
83
+ var(--hx-checkbox-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
84
+ outline-offset: var(--hx-checkbox-focus-ring-offset, var(--hx-focus-ring-offset, 2px));
85
+ }
86
+
87
+ /*
88
+ * Fallback (no-IDL-ref) path: the host carries tabindex=-1 and the inner
89
+ * input is the tab target. The native :focus-visible on the input drives
90
+ * the same visual ring, scoped via the inner-state class.
91
+ */
75
92
  .checkbox__input:focus-visible ~ .checkbox__box {
76
93
  outline: var(--hx-checkbox-focus-ring-width, var(--hx-focus-ring-width, 2px)) solid
77
94
  var(--hx-checkbox-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
@@ -226,6 +243,7 @@
226
243
  border: 2px solid ButtonText;
227
244
  }
228
245
 
246
+ :host(:focus-visible) .checkbox__box,
229
247
  .checkbox__input:focus-visible ~ .checkbox__box {
230
248
  outline: 3px solid Highlight;
231
249
  outline-offset: 2px;
@@ -402,6 +420,31 @@
402
420
  pointer-events: none;
403
421
  opacity: var(--hx-opacity-disabled, 0.5);
404
422
  }
423
+ /* Slotted label / help / error blocks for cross-shadow naming. */
424
+ .hx-color-picker__label {
425
+ display: block;
426
+ margin-bottom: var(--hx-space-1, 0.25rem);
427
+ font-weight: var(--hx-font-weight-semibold, 600);
428
+ color: var(--hx-color-neutral-900, #1a1a1a);
429
+ }
430
+ .hx-color-picker__label:empty {
431
+ display: none;
432
+ }
433
+ .hx-color-picker__help {
434
+ display: block;
435
+ margin-top: var(--hx-space-1, 0.25rem);
436
+ font-size: var(--hx-font-size-xs, 0.75rem);
437
+ color: var(--hx-color-neutral-600, #525252);
438
+ }
439
+ .hx-color-picker__error {
440
+ display: block;
441
+ margin-top: var(--hx-space-1, 0.25rem);
442
+ font-size: var(--hx-font-size-xs, 0.75rem);
443
+ color: var(--hx-color-danger-700, #c43e3e);
444
+ }
445
+ [hidden] {
446
+ display: none !important;
447
+ }
405
448
  .trigger {
406
449
  display: inline-flex;
407
450
  align-items: center;
@@ -1398,7 +1441,8 @@
1398
1441
  Live region (screen reader announcements)
1399
1442
  ============================================================ */
1400
1443
 
1401
- .calendar__live-region {
1444
+ .calendar__live-region,
1445
+ .field__sr-only {
1402
1446
  position: absolute;
1403
1447
  width: 1px;
1404
1448
  height: 1px;
@@ -2615,6 +2659,11 @@
2615
2659
  /* ─── 3-tier token cascade: component → semantic → hardcoded fallback ─── */
2616
2660
  :host {
2617
2661
  display: block;
2662
+ /* Round-3 finding 1: host is the canonical combobox surface, so it owns
2663
+ keyboard focus. Suppress the UA default outline; the custom focus ring
2664
+ is painted on the inner trigger via :host(:focus-visible)
2665
+ .field__trigger so visual feedback follows the host's focus state. */
2666
+ outline: none;
2618
2667
 
2619
2668
  /* Background & foreground */
2620
2669
  --_bg: var(--hx-select-bg, var(--hx-color-surface-default, #ffffff));
@@ -2691,6 +2740,12 @@
2691
2740
  }
2692
2741
 
2693
2742
  .field__trigger {
2743
+ /* Round-3 finding 1 / CodeRabbit F1: trigger is a <button type="button">
2744
+ (labelable) so native <label for> click activation works for mouse
2745
+ users. Reset native button chrome before applying field styles. */
2746
+ appearance: none;
2747
+ -webkit-appearance: none;
2748
+ margin: 0;
2694
2749
  display: flex;
2695
2750
  align-items: center;
2696
2751
  justify-content: space-between;
@@ -2701,6 +2756,7 @@
2701
2756
  border-radius: var(--_border-radius);
2702
2757
  background-color: var(--_bg);
2703
2758
  color: var(--_color);
2759
+ font: inherit;
2704
2760
  font-family: inherit;
2705
2761
  font-size: var(--hx-font-size-md, 1rem);
2706
2762
  line-height: var(--hx-line-height-normal, 1.5);
@@ -2713,6 +2769,11 @@
2713
2769
  outline: none;
2714
2770
  }
2715
2771
 
2772
+ /* Round-3 finding 1: host is the canonical focusable surface. Both the
2773
+ :host(:focus-visible) descendant selector AND the legacy
2774
+ .field__trigger:focus-visible (kept for forced-colors regression test
2775
+ parity) paint the focus ring on the visual trigger. */
2776
+ :host(:focus-visible) .field__trigger,
2716
2777
  .field__trigger:focus-visible {
2717
2778
  border-color: var(--_focus-ring-color);
2718
2779
  box-shadow: 0 0 0 var(--hx-focus-ring-width, 2px)
@@ -2781,6 +2842,7 @@
2781
2842
  border-color: var(--_error-color);
2782
2843
  }
2783
2844
 
2845
+ :host(:focus-visible) .field--error .field__trigger,
2784
2846
  .field--error .field__trigger:focus-visible {
2785
2847
  border-color: var(--_error-color);
2786
2848
  box-shadow: 0 0 0 var(--hx-focus-ring-width, 2px)
@@ -2914,6 +2976,7 @@
2914
2976
  border: 2px solid ButtonText;
2915
2977
  }
2916
2978
 
2979
+ :host(:focus-visible) .field__trigger,
2917
2980
  .field__trigger:focus-visible {
2918
2981
  outline: 3px solid Highlight;
2919
2982
  outline-offset: 2px;
@@ -3328,6 +3391,22 @@
3328
3391
  appearance: none;
3329
3392
  }
3330
3393
 
3394
+ /*
3395
+ * Host-focus path: on the modern (IDL element-references) render branch the
3396
+ * host is the tabbable surface (tabindex=0) and the inner track button is
3397
+ * demoted to tabindex=-1. Drive the focus ring from ':host(:focus-visible)'
3398
+ * so keyboard users still see a visible affordance. Codex round-11 P1.
3399
+ */
3400
+ :host(:focus-visible) .switch__track {
3401
+ outline: var(--hx-focus-ring-width, 2px) solid
3402
+ var(--hx-switch-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
3403
+ outline-offset: var(--hx-focus-ring-offset, 2px);
3404
+ }
3405
+
3406
+ /*
3407
+ * Fallback (no-IDL-ref) path: the host carries tabindex=-1 and the inner
3408
+ * track button is the tab target. Native :focus-visible drives the ring.
3409
+ */
3331
3410
  .switch__track:focus-visible {
3332
3411
  outline: var(--hx-focus-ring-width, 2px) solid
3333
3412
  var(--hx-switch-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
@@ -3465,6 +3544,7 @@
3465
3544
  border: 2px solid ButtonText;
3466
3545
  }
3467
3546
 
3547
+ :host(:focus-visible) .switch__track,
3468
3548
  .switch__track:focus-visible {
3469
3549
  outline: 3px solid Highlight;
3470
3550
  outline-offset: 2px;
@@ -4400,6 +4480,22 @@
4400
4480
  -webkit-user-select: none;
4401
4481
  }
4402
4482
 
4483
+ /*
4484
+ * Host-focus path: on the modern (IDL element-references) render branch the
4485
+ * host is the tabbable surface (tabindex=0) and the inner <button> is
4486
+ * demoted to tabindex=-1. Drive the focus ring from ':host(:focus-visible)'
4487
+ * so keyboard users still see a visible affordance. Codex round-11 P1.
4488
+ */
4489
+ :host(:focus-visible) .button {
4490
+ outline: var(--hx-focus-ring-width, 2px) solid
4491
+ var(--hx-toggle-button-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
4492
+ outline-offset: var(--hx-focus-ring-offset, 2px);
4493
+ }
4494
+
4495
+ /*
4496
+ * Fallback (no-IDL-ref) path: the host carries tabindex=-1 and the inner
4497
+ * <button> is the tab target. Native :focus-visible drives the ring.
4498
+ */
4403
4499
  .button:focus-visible {
4404
4500
  outline: var(--hx-focus-ring-width, 2px) solid
4405
4501
  var(--hx-toggle-button-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
@@ -4598,6 +4694,7 @@
4598
4694
  border: 2px solid ButtonText;
4599
4695
  }
4600
4696
 
4697
+ :host(:focus-visible) .button,
4601
4698
  .button:focus-visible {
4602
4699
  outline: 3px solid Highlight;
4603
4700
  outline-offset: 2px;
@@ -70,6 +70,23 @@
70
70
 
71
71
  /* ─── Focus Ring ─── */
72
72
 
73
+ /*
74
+ * Host-focus path: on the modern (IDL element-references) render branch the
75
+ * host is the tabbable surface (tabindex=0) and the inner input is demoted
76
+ * to tabindex=-1. Drive the focus ring from ':host(:focus-visible)' so
77
+ * keyboard users still get a visible affordance. Codex round-11 P1.
78
+ */
79
+ :host(:focus-visible) .checkbox__box {
80
+ outline: var(--hx-checkbox-focus-ring-width, var(--hx-focus-ring-width, 2px)) solid
81
+ var(--hx-checkbox-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
82
+ outline-offset: var(--hx-checkbox-focus-ring-offset, var(--hx-focus-ring-offset, 2px));
83
+ }
84
+
85
+ /*
86
+ * Fallback (no-IDL-ref) path: the host carries tabindex=-1 and the inner
87
+ * input is the tab target. The native :focus-visible on the input drives
88
+ * the same visual ring, scoped via the inner-state class.
89
+ */
73
90
  .checkbox__input:focus-visible ~ .checkbox__box {
74
91
  outline: var(--hx-checkbox-focus-ring-width, var(--hx-focus-ring-width, 2px)) solid
75
92
  var(--hx-checkbox-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
@@ -224,6 +241,7 @@
224
241
  border: 2px solid ButtonText;
225
242
  }
226
243
 
244
+ :host(:focus-visible) .checkbox__box,
227
245
  .checkbox__input:focus-visible ~ .checkbox__box {
228
246
  outline: 3px solid Highlight;
229
247
  outline-offset: 2px;
@@ -9,6 +9,31 @@
9
9
  pointer-events: none;
10
10
  opacity: var(--hx-opacity-disabled, 0.5);
11
11
  }
12
+ /* Slotted label / help / error blocks for cross-shadow naming. */
13
+ .hx-color-picker__label {
14
+ display: block;
15
+ margin-bottom: var(--hx-space-1, 0.25rem);
16
+ font-weight: var(--hx-font-weight-semibold, 600);
17
+ color: var(--hx-color-neutral-900, #1a1a1a);
18
+ }
19
+ .hx-color-picker__label:empty {
20
+ display: none;
21
+ }
22
+ .hx-color-picker__help {
23
+ display: block;
24
+ margin-top: var(--hx-space-1, 0.25rem);
25
+ font-size: var(--hx-font-size-xs, 0.75rem);
26
+ color: var(--hx-color-neutral-600, #525252);
27
+ }
28
+ .hx-color-picker__error {
29
+ display: block;
30
+ margin-top: var(--hx-space-1, 0.25rem);
31
+ font-size: var(--hx-font-size-xs, 0.75rem);
32
+ color: var(--hx-color-danger-700, #c43e3e);
33
+ }
34
+ [hidden] {
35
+ display: none !important;
36
+ }
12
37
  .trigger {
13
38
  display: inline-flex;
14
39
  align-items: center;
@@ -335,7 +335,8 @@
335
335
  Live region (screen reader announcements)
336
336
  ============================================================ */
337
337
 
338
- .calendar__live-region {
338
+ .calendar__live-region,
339
+ .field__sr-only {
339
340
  position: absolute;
340
341
  width: 1px;
341
342
  height: 1px;
@@ -2,6 +2,11 @@
2
2
  /* ─── 3-tier token cascade: component → semantic → hardcoded fallback ─── */
3
3
  :host {
4
4
  display: block;
5
+ /* Round-3 finding 1: host is the canonical combobox surface, so it owns
6
+ keyboard focus. Suppress the UA default outline; the custom focus ring
7
+ is painted on the inner trigger via :host(:focus-visible)
8
+ .field__trigger so visual feedback follows the host's focus state. */
9
+ outline: none;
5
10
 
6
11
  /* Background & foreground */
7
12
  --_bg: var(--hx-select-bg, var(--hx-color-surface-default, #ffffff));
@@ -78,6 +83,12 @@
78
83
  }
79
84
 
80
85
  .field__trigger {
86
+ /* Round-3 finding 1 / CodeRabbit F1: trigger is a <button type="button">
87
+ (labelable) so native <label for> click activation works for mouse
88
+ users. Reset native button chrome before applying field styles. */
89
+ appearance: none;
90
+ -webkit-appearance: none;
91
+ margin: 0;
81
92
  display: flex;
82
93
  align-items: center;
83
94
  justify-content: space-between;
@@ -88,6 +99,7 @@
88
99
  border-radius: var(--_border-radius);
89
100
  background-color: var(--_bg);
90
101
  color: var(--_color);
102
+ font: inherit;
91
103
  font-family: inherit;
92
104
  font-size: var(--hx-font-size-md, 1rem);
93
105
  line-height: var(--hx-line-height-normal, 1.5);
@@ -100,6 +112,11 @@
100
112
  outline: none;
101
113
  }
102
114
 
115
+ /* Round-3 finding 1: host is the canonical focusable surface. Both the
116
+ :host(:focus-visible) descendant selector AND the legacy
117
+ .field__trigger:focus-visible (kept for forced-colors regression test
118
+ parity) paint the focus ring on the visual trigger. */
119
+ :host(:focus-visible) .field__trigger,
103
120
  .field__trigger:focus-visible {
104
121
  border-color: var(--_focus-ring-color);
105
122
  box-shadow: 0 0 0 var(--hx-focus-ring-width, 2px)
@@ -168,6 +185,7 @@
168
185
  border-color: var(--_error-color);
169
186
  }
170
187
 
188
+ :host(:focus-visible) .field--error .field__trigger,
171
189
  .field--error .field__trigger:focus-visible {
172
190
  border-color: var(--_error-color);
173
191
  box-shadow: 0 0 0 var(--hx-focus-ring-width, 2px)
@@ -301,6 +319,7 @@
301
319
  border: 2px solid ButtonText;
302
320
  }
303
321
 
322
+ :host(:focus-visible) .field__trigger,
304
323
  .field__trigger:focus-visible {
305
324
  outline: 3px solid Highlight;
306
325
  outline-offset: 2px;
@@ -49,6 +49,22 @@
49
49
  appearance: none;
50
50
  }
51
51
 
52
+ /*
53
+ * Host-focus path: on the modern (IDL element-references) render branch the
54
+ * host is the tabbable surface (tabindex=0) and the inner track button is
55
+ * demoted to tabindex=-1. Drive the focus ring from ':host(:focus-visible)'
56
+ * so keyboard users still see a visible affordance. Codex round-11 P1.
57
+ */
58
+ :host(:focus-visible) .switch__track {
59
+ outline: var(--hx-focus-ring-width, 2px) solid
60
+ var(--hx-switch-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
61
+ outline-offset: var(--hx-focus-ring-offset, 2px);
62
+ }
63
+
64
+ /*
65
+ * Fallback (no-IDL-ref) path: the host carries tabindex=-1 and the inner
66
+ * track button is the tab target. Native :focus-visible drives the ring.
67
+ */
52
68
  .switch__track:focus-visible {
53
69
  outline: var(--hx-focus-ring-width, 2px) solid
54
70
  var(--hx-switch-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
@@ -186,6 +202,7 @@
186
202
  border: 2px solid ButtonText;
187
203
  }
188
204
 
205
+ :host(:focus-visible) .switch__track,
189
206
  .switch__track:focus-visible {
190
207
  outline: 3px solid Highlight;
191
208
  outline-offset: 2px;
@@ -34,6 +34,22 @@
34
34
  -webkit-user-select: none;
35
35
  }
36
36
 
37
+ /*
38
+ * Host-focus path: on the modern (IDL element-references) render branch the
39
+ * host is the tabbable surface (tabindex=0) and the inner <button> is
40
+ * demoted to tabindex=-1. Drive the focus ring from ':host(:focus-visible)'
41
+ * so keyboard users still see a visible affordance. Codex round-11 P1.
42
+ */
43
+ :host(:focus-visible) .button {
44
+ outline: var(--hx-focus-ring-width, 2px) solid
45
+ var(--hx-toggle-button-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
46
+ outline-offset: var(--hx-focus-ring-offset, 2px);
47
+ }
48
+
49
+ /*
50
+ * Fallback (no-IDL-ref) path: the host carries tabindex=-1 and the inner
51
+ * <button> is the tab target. Native :focus-visible drives the ring.
52
+ */
37
53
  .button:focus-visible {
38
54
  outline: var(--hx-focus-ring-width, 2px) solid
39
55
  var(--hx-toggle-button-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
@@ -232,6 +248,7 @@
232
248
  border: 2px solid ButtonText;
233
249
  }
234
250
 
251
+ :host(:focus-visible) .button,
235
252
  .button:focus-visible {
236
253
  outline: 3px solid Highlight;
237
254
  outline-offset: 2px;
@@ -1,4 +1,4 @@
1
- /* index.css — generated 2026-05-03T14:41:47.411Z */
1
+ /* index.css — generated 2026-05-05T19:04:42.574Z */
2
2
  /* Imports all per-component CSS files for Drupal asset pipeline */
3
3
 
4
4
  @import './hx-accordion.css';