@astryxdesign/core 0.4.1 → 0.4.2-canary.464a445

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 (182) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/dist/Avatar/Avatar.d.ts +4 -1
  3. package/dist/Avatar/Avatar.d.ts.map +1 -1
  4. package/dist/Avatar/Avatar.js +19 -23
  5. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
  6. package/dist/AvatarGroup/AvatarGroupOverflow.js +7 -2
  7. package/dist/Button/Button.d.ts.map +1 -1
  8. package/dist/Button/Button.js +9 -7
  9. package/dist/Chat/ChatMessage.d.ts +7 -0
  10. package/dist/Chat/ChatMessage.d.ts.map +1 -1
  11. package/dist/Chat/ChatMessageBubble.d.ts +13 -1
  12. package/dist/Chat/ChatMessageBubble.d.ts.map +1 -1
  13. package/dist/Chat/ChatMessageBubble.js +19 -1
  14. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  15. package/dist/CheckboxInput/CheckboxInput.js +5 -0
  16. package/dist/CommandPalette/CommandPaletteFooter.d.ts.map +1 -1
  17. package/dist/CommandPalette/CommandPaletteFooter.js +5 -3
  18. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  19. package/dist/DateTimeInput/DateTimeInput.js +2 -2
  20. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
  21. package/dist/DropdownMenu/DropdownMenuSubMenu.js +19 -15
  22. package/dist/HoverCard/HoverCard.d.ts +1 -1
  23. package/dist/HoverCard/HoverCard.d.ts.map +1 -1
  24. package/dist/HoverCard/HoverCard.js +5 -13
  25. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  26. package/dist/HoverCard/useHoverCard.js +6 -5
  27. package/dist/InputGroup/groupStyles.d.ts.map +1 -1
  28. package/dist/InputGroup/groupStyles.js +7 -2
  29. package/dist/Layer/layerHost.d.ts +24 -0
  30. package/dist/Layer/layerHost.d.ts.map +1 -0
  31. package/dist/Layer/layerHost.js +79 -0
  32. package/dist/Layer/useLayer.d.ts +14 -6
  33. package/dist/Layer/useLayer.d.ts.map +1 -1
  34. package/dist/Layer/useLayer.js +158 -30
  35. package/dist/NavItem/navItemStyles.stylex.d.ts +17 -5
  36. package/dist/NavItem/navItemStyles.stylex.d.ts.map +1 -1
  37. package/dist/NavItem/navItemStyles.stylex.js +11 -5
  38. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  39. package/dist/RadioList/RadioListItem.js +5 -0
  40. package/dist/SideNav/SideNav.d.ts +7 -9
  41. package/dist/SideNav/SideNav.d.ts.map +1 -1
  42. package/dist/SideNav/SideNav.js +32 -5
  43. package/dist/SideNav/SideNavCollapseButton.d.ts +25 -9
  44. package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
  45. package/dist/SideNav/SideNavCollapseButton.js +39 -15
  46. package/dist/SideNav/SideNavCollapseContext.d.ts +21 -0
  47. package/dist/SideNav/SideNavCollapseContext.d.ts.map +1 -1
  48. package/dist/SideNav/SideNavCollapseContext.js +16 -2
  49. package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
  50. package/dist/SideNav/SideNavHeading.js +89 -32
  51. package/dist/SideNav/SideNavItem.d.ts +7 -2
  52. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  53. package/dist/SideNav/SideNavItem.js +119 -75
  54. package/dist/SideNav/SideNavSection.d.ts.map +1 -1
  55. package/dist/SideNav/SideNavSection.js +7 -16
  56. package/dist/SideNav/index.d.ts +1 -1
  57. package/dist/SideNav/index.d.ts.map +1 -1
  58. package/dist/Slider/Slider.d.ts.map +1 -1
  59. package/dist/Slider/Slider.js +56 -15
  60. package/dist/Switch/Switch.d.ts.map +1 -1
  61. package/dist/Switch/Switch.js +5 -0
  62. package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
  63. package/dist/Thumbnail/Thumbnail.js +5 -0
  64. package/dist/TopNav/TopNavHeading.d.ts.map +1 -1
  65. package/dist/TopNav/TopNavHeading.js +14 -6
  66. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  67. package/dist/TopNav/TopNavMegaMenu.js +25 -93
  68. package/dist/TopNav/TopNavMegaMenuItem.js +1 -1
  69. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  70. package/dist/TopNav/TopNavMenu.js +10 -5
  71. package/dist/astryx.css +13 -7
  72. package/dist/astryx.umd.js +50 -50
  73. package/dist/astryx.umd.js.map +4 -4
  74. package/dist/hooks/index.d.ts +1 -1
  75. package/dist/hooks/index.d.ts.map +1 -1
  76. package/dist/hooks/index.js +1 -1
  77. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  78. package/dist/hooks/useFocusTrap.js +16 -2
  79. package/dist/hooks/useMenuHover.d.ts +50 -5
  80. package/dist/hooks/useMenuHover.d.ts.map +1 -1
  81. package/dist/hooks/useMenuHover.js +171 -51
  82. package/dist/theme/defineTheme.d.ts +8 -2
  83. package/dist/theme/defineTheme.d.ts.map +1 -1
  84. package/dist/theme/defineTheme.js +8 -1
  85. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  86. package/dist/theme/derivedVarRegistry.js +7 -0
  87. package/dist/theme/expandColorScale.d.ts.map +1 -1
  88. package/dist/theme/expandColorScale.js +1 -0
  89. package/dist/theme/expandMotionScale.d.ts +1 -0
  90. package/dist/theme/expandMotionScale.d.ts.map +1 -1
  91. package/dist/theme/expandMotionScale.js +1 -0
  92. package/dist/theme/expandRadiusScale.d.ts +1 -0
  93. package/dist/theme/expandRadiusScale.d.ts.map +1 -1
  94. package/dist/theme/expandRadiusScale.js +1 -0
  95. package/dist/theme/expandTypeScale.d.ts +1 -0
  96. package/dist/theme/expandTypeScale.d.ts.map +1 -1
  97. package/dist/theme/expandTypeScale.js +1 -0
  98. package/dist/theme/tokens.stylex.d.ts +3 -1
  99. package/dist/theme/tokens.stylex.d.ts.map +1 -1
  100. package/dist/theme/tokens.stylex.js +3 -1
  101. package/locales/en.json +84 -0
  102. package/locales/pseudo.json +63 -0
  103. package/package.json +3 -3
  104. package/src/Avatar/Avatar.doc.mjs +5 -2
  105. package/src/Avatar/Avatar.test.tsx +51 -0
  106. package/src/Avatar/Avatar.tsx +30 -20
  107. package/src/AvatarGroup/AvatarGroup.doc.mjs +1 -1
  108. package/src/AvatarGroup/AvatarGroup.test.tsx +14 -0
  109. package/src/AvatarGroup/AvatarGroupOverflow.tsx +3 -2
  110. package/src/Button/Button.tsx +5 -3
  111. package/src/ButtonGroup/ButtonGroup.test.tsx +7 -4
  112. package/src/Card/Card.doc.mjs +2 -0
  113. package/src/Chat/Chat.doc.mjs +4 -1
  114. package/src/Chat/ChatMessage.doc.mjs +3 -3
  115. package/src/Chat/ChatMessage.tsx +7 -0
  116. package/src/Chat/ChatMessageBubble.doc.mjs +7 -0
  117. package/src/Chat/ChatMessageBubble.test.tsx +95 -6
  118. package/src/Chat/ChatMessageBubble.tsx +25 -0
  119. package/src/CheckboxInput/CheckboxInput.tsx +20 -0
  120. package/src/CodeBlock/CodeBlock.doc.mjs +3 -0
  121. package/src/CommandPalette/CommandPaletteFooter.tsx +6 -3
  122. package/src/DateTimeInput/DateTimeInput.tsx +4 -2
  123. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +72 -1
  124. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +24 -20
  125. package/src/HoverCard/HoverCard.doc.mjs +3 -3
  126. package/src/HoverCard/HoverCard.test.tsx +283 -55
  127. package/src/HoverCard/HoverCard.tsx +5 -13
  128. package/src/HoverCard/useHoverCard.tsx +8 -11
  129. package/src/InputGroup/groupStyles.ts +7 -8
  130. package/src/Item/Item.doc.mjs +4 -0
  131. package/src/Layer/layerHost.test.ts +99 -0
  132. package/src/Layer/layerHost.ts +141 -0
  133. package/src/Layer/useLayer.doc.mjs +14 -4
  134. package/src/Layer/useLayer.test.tsx +332 -7
  135. package/src/Layer/useLayer.tsx +235 -36
  136. package/src/MobileNav/MobileNav.doc.mjs +7 -0
  137. package/src/NavItem/navItemStyles.stylex.ts +31 -5
  138. package/src/RadioList/RadioListItem.tsx +20 -0
  139. package/src/SideNav/SideNav.doc.mjs +13 -4
  140. package/src/SideNav/SideNav.test.tsx +858 -2
  141. package/src/SideNav/SideNav.tsx +37 -16
  142. package/src/SideNav/SideNavCollapseButton.doc.mjs +28 -6
  143. package/src/SideNav/SideNavCollapseButton.tsx +67 -15
  144. package/src/SideNav/SideNavCollapseContext.ts +29 -9
  145. package/src/SideNav/SideNavHeading.tsx +53 -25
  146. package/src/SideNav/SideNavItem.doc.mjs +13 -0
  147. package/src/SideNav/SideNavItem.tsx +97 -84
  148. package/src/SideNav/SideNavSection.tsx +6 -20
  149. package/src/SideNav/index.ts +2 -0
  150. package/src/Slider/Slider.test.tsx +69 -33
  151. package/src/Slider/Slider.tsx +65 -13
  152. package/src/Switch/Switch.tsx +20 -0
  153. package/src/TabList/TabList.doc.mjs +3 -0
  154. package/src/Text/Text.doc.mjs +1 -1
  155. package/src/Thumbnail/Thumbnail.doc.mjs +3 -0
  156. package/src/Thumbnail/Thumbnail.tsx +10 -0
  157. package/src/Timestamp/Timestamp.test.tsx +40 -22
  158. package/src/Toolbar/Toolbar.test.tsx +14 -14
  159. package/src/TopNav/TopNav.test.tsx +86 -1
  160. package/src/TopNav/TopNavHeading.tsx +21 -14
  161. package/src/TopNav/TopNavMegaMenu.test.tsx +43 -0
  162. package/src/TopNav/TopNavMegaMenu.tsx +29 -105
  163. package/src/TopNav/TopNavMegaMenuItem.tsx +1 -1
  164. package/src/TopNav/TopNavMenu.test.tsx +41 -0
  165. package/src/TopNav/TopNavMenu.tsx +14 -4
  166. package/src/TreeList/TreeList.doc.mjs +1 -0
  167. package/src/hooks/index.ts +5 -1
  168. package/src/hooks/useFocusTrap.test.tsx +16 -0
  169. package/src/hooks/useFocusTrap.ts +20 -2
  170. package/src/hooks/useMenuHover.test.tsx +364 -0
  171. package/src/hooks/useMenuHover.ts +243 -47
  172. package/src/theme/defineTheme.ts +9 -0
  173. package/src/theme/derivedVarRegistry.test.ts +78 -12
  174. package/src/theme/derivedVarRegistry.ts +4 -0
  175. package/src/theme/expandColorScale.ts +1 -0
  176. package/src/theme/expandMotionScale.ts +1 -0
  177. package/src/theme/expandRadiusScale.ts +1 -0
  178. package/src/theme/expandTypeScale.ts +1 -0
  179. package/src/theme/themingTargets.test.ts +152 -26
  180. package/src/theme/tokens.stylex.ts +3 -1
  181. package/src/theme/tokens.test.ts +12 -0
  182. package/src/theme/useTheme.test.tsx +18 -0
@@ -30,6 +30,7 @@ import { Link } from "../Link/index.js";
30
30
  import { Icon } from "../Icon/index.js";
31
31
  import { Tooltip } from "../Tooltip/index.js";
32
32
  import { navItemStyles } from "../NavItem/navItemStyles.stylex.js";
33
+ import { focusOutlineProps } from "../utils/focusOutline.stylex.js";
33
34
  import { useSideNavCollapse } from "./SideNavCollapseContext.js";
34
35
  import { useLinkComponent } from "../Link/useLinkComponent.js";
35
36
  import { mergeProps, mergeRefs } from "../utils/index.js";
@@ -62,6 +63,19 @@ const styles = {
62
63
  kg3NbH: "xnjsko4",
63
64
  $$css: true
64
65
  },
66
+ interactive: {
67
+ kkrTdU: "x1ypdohk",
68
+ kaIpWk: "xh6dtrn",
69
+ kMzoRj: "xc342km",
70
+ ksu8eU: "xng3xce",
71
+ kWkggS: "xjbqb8w",
72
+ kMv6JI: "xjb2p0i",
73
+ kGuDYH: "x1qlqyl8",
74
+ k63SB2: "x1sodnla",
75
+ k9WMMc: "x1yc453h",
76
+ kHE3J0: "xe9uy6x",
77
+ $$css: true
78
+ },
65
79
  menuTrigger: {
66
80
  kkrTdU: "x1ypdohk",
67
81
  kaIpWk: "xh6dtrn",
@@ -74,6 +88,32 @@ const styles = {
74
88
  k9WMMc: "x1yc453h",
75
89
  $$css: true
76
90
  },
91
+ icon: {
92
+ kmuXW: "x2lah0s",
93
+ k1xSpc: "x78zum5",
94
+ kGNEyG: "x6s0dn4",
95
+ kjj79g: "xl56j7k",
96
+ $$css: true
97
+ },
98
+ heading: {
99
+ kGuDYH: "x18juvz8",
100
+ k63SB2: "x2mo6ok",
101
+ kLWn49: "xf74fhv",
102
+ kMwMTN: "x1tgivj0",
103
+ kybGjl: "x1hl2dhg",
104
+ kVQacm: "xb3r6kr",
105
+ kg5iWk: "xlyipyv",
106
+ khDVqt: "xuxw1ft",
107
+ $$css: true
108
+ },
109
+ headingLink: {
110
+ kybGjl: "x1hl2dhg",
111
+ kMwMTN: "x1heor9g",
112
+ kVQacm: "xb3r6kr",
113
+ kg5iWk: "xlyipyv",
114
+ khDVqt: "xuxw1ft",
115
+ $$css: true
116
+ },
77
117
  chevron: {
78
118
  kmuXW: "x2lah0s",
79
119
  k1xSpc: "x78zum5",
@@ -85,6 +125,26 @@ const styles = {
85
125
  kGuDYH: "x1qlqyl8",
86
126
  $$css: true
87
127
  },
128
+ popoverHeading: {
129
+ k1xSpc: "x78zum5",
130
+ kGNEyG: "x6s0dn4",
131
+ kOIVth: "x1txdalj",
132
+ kzqmXN: "xh8yej3",
133
+ kWkggS: "xjbqb8w",
134
+ kMv6JI: "xjb2p0i",
135
+ kGuDYH: "x1qlqyl8",
136
+ kMwMTN: "x1heor9g",
137
+ k9WMMc: "x1yc453h",
138
+ kAzted: "xkoleio",
139
+ kZCmMZ: "x12gdq22 x1betex2",
140
+ kwRFfy: "x1djylfy",
141
+ k8WAf4: "xt970qd",
142
+ keoZOQ: "xcsaf9d",
143
+ k1K539: "x1p37lm5",
144
+ kUOVxO: "xhrcg97",
145
+ kkrTdU: "x1ypdohk",
146
+ $$css: true
147
+ },
88
148
  popoverChevron: {
89
149
  kmuXW: "x2lah0s",
90
150
  k1xSpc: "x78zum5",
@@ -187,14 +247,12 @@ export function SideNavHeading({
187
247
  role: 'none',
188
248
  hasCloseButton: false
189
249
  });
190
- const closeMenuCtx = useMemo(() => ({
191
- closeMenu: popover.hide
192
- }), [popover.hide]);
193
250
  const {
194
251
  triggerProps,
195
252
  contentProps,
196
253
  menuRef,
197
- setTriggerEl
254
+ setTriggerEl,
255
+ close: closeMenu
198
256
  } = useMenuHover({
199
257
  show: popover.show,
200
258
  hide: popover.hide,
@@ -202,7 +260,14 @@ export function SideNavHeading({
202
260
  isEnabled: !!menu,
203
261
  showDelay: 0
204
262
  });
205
- const setRef = mergeRefs(rootRef, setTriggerEl, ref, menu ? popover.triggerRef : undefined);
263
+ const closeMenuCtx = useMemo(() => ({
264
+ closeMenu
265
+ }), [closeMenu]);
266
+
267
+ // setTriggerEl belongs on the chevron button, not this root: it is the
268
+ // focus-restore target and a <div> cannot take focus. triggerRef stays here
269
+ // because the panel anchors to the whole heading.
270
+ const setRef = mergeRefs(rootRef, ref, menu ? popover.triggerRef : undefined);
206
271
 
207
272
  // In collapsed mode: hide if no icon, show icon-only if has icon
208
273
  if (isCollapsed && !icon) {
@@ -215,7 +280,9 @@ export function SideNavHeading({
215
280
  },
216
281
  children: icon
217
282
  });
218
- const collapsedSetRef = mergeRefs(collapsedItemRef, ref, menu ? popover.triggerRef : undefined);
283
+ const collapsedSetRef = mergeRefs(collapsedItemRef, ref,
284
+ // Collapsed, this button is the trigger, so it takes both roles.
285
+ menu ? popover.triggerRef : undefined, menu ? setTriggerEl : undefined);
219
286
  let collapsedElement;
220
287
  if (headingHref) {
221
288
  collapsedElement = /*#__PURE__*/_jsx(LinkComponent, {
@@ -223,7 +290,7 @@ export function SideNavHeading({
223
290
  href: headingHref,
224
291
  "aria-label": heading,
225
292
  "data-testid": testId,
226
- ...mergeProps(themeProps('side-nav-heading'), stylex.props(navItemStyles.item, styles.rootCollapsed, xstyle), className, style),
293
+ ...mergeProps(themeProps('side-nav-heading'), focusOutlineProps.focusVisible(navItemStyles.item, styles.rootCollapsed, xstyle), className, style),
227
294
  children: collapsedIcon
228
295
  });
229
296
  } else if (menu) {
@@ -235,7 +302,7 @@ export function SideNavHeading({
235
302
  "data-testid": testId,
236
303
  ...popover.triggerProps,
237
304
  ...triggerProps,
238
- ...mergeProps(themeProps('side-nav-heading'), stylex.props(navItemStyles.item, styles.rootCollapsed, styles.menuTrigger, xstyle), className, style),
305
+ ...mergeProps(themeProps('side-nav-heading'), focusOutlineProps.focusVisible(navItemStyles.item, styles.rootCollapsed, styles.menuTrigger, xstyle), className, style),
239
306
  children: collapsedIcon
240
307
  }), popover.render(/*#__PURE__*/_jsxs("div", {
241
308
  ref: menuRef,
@@ -245,10 +312,9 @@ export function SideNavHeading({
245
312
  ...contentProps,
246
313
  children: [/*#__PURE__*/_jsxs("button", {
247
314
  type: "button",
248
- ...{
249
- className: "x78zum5 x6s0dn4 x1txdalj xh8yej3 xjbqb8w xjb2p0i x1qlqyl8 x1heor9g x1yc453h xkoleio x12gdq22 x1betex2 x1djylfy xt970qd xcsaf9d x1p37lm5 xhrcg97 x1ypdohk"
250
- },
251
- onClick: triggerProps.onClick,
315
+ ...focusOutlineProps.focusVisible(styles.popoverHeading),
316
+ // A close affordance, not the trigger: dismiss only.
317
+ onClick: closeMenu,
252
318
  children: [icon && /*#__PURE__*/_jsx("span", {
253
319
  ...{
254
320
  className: "x2lah0s x78zum5 x6s0dn4 xl56j7k"
@@ -350,9 +416,7 @@ export function SideNavHeading({
350
416
  },
351
417
  children: [hasAnyHref && headingHref && menu ? /*#__PURE__*/_jsx(LinkComponent, {
352
418
  href: headingHref,
353
- ...{
354
- className: "x18juvz8 x2mo6ok xf74fhv x1hl2dhg x1heor9g xb3r6kr xlyipyv xuxw1ft"
355
- },
419
+ ...focusOutlineProps.focusVisible(styles.heading, styles.headingLink),
356
420
  children: heading
357
421
  }) : /*#__PURE__*/_jsx("span", {
358
422
  ...{
@@ -389,10 +453,9 @@ export function SideNavHeading({
389
453
  // sizing, with flipped chevron inline after the title. Always static (no links).
390
454
  const popoverHeadingContent = /*#__PURE__*/_jsxs("button", {
391
455
  type: "button",
392
- ...{
393
- className: "x78zum5 x6s0dn4 x1txdalj xh8yej3 xjbqb8w xjb2p0i x1qlqyl8 x1heor9g x1yc453h xkoleio x12gdq22 x1betex2 x1djylfy xt970qd xcsaf9d x1p37lm5 xhrcg97 x1ypdohk"
394
- },
395
- onClick: triggerProps.onClick,
456
+ ...focusOutlineProps.focusVisible(styles.popoverHeading),
457
+ // A close affordance, not the trigger: dismiss only.
458
+ onClick: closeMenu,
396
459
  children: [icon && /*#__PURE__*/_jsx("span", {
397
460
  ...{
398
461
  className: "x2lah0s x78zum5 x6s0dn4 xl56j7k"
@@ -412,7 +475,7 @@ export function SideNavHeading({
412
475
  ref: ref,
413
476
  href: headingHref,
414
477
  "data-testid": testId,
415
- ...mergeProps(themeProps('side-nav-heading'), stylex.props(styles.root, styles.menuTrigger, xstyle), className, style),
478
+ ...mergeProps(themeProps('side-nav-heading'), focusOutlineProps.focusVisible(styles.root, styles.menuTrigger, xstyle), className, style),
416
479
  ...props,
417
480
  children: [icon && /*#__PURE__*/_jsx("span", {
418
481
  ...{
@@ -437,6 +500,7 @@ export function SideNavHeading({
437
500
  },
438
501
  children: icon
439
502
  }), renderTextContent(/*#__PURE__*/_jsx("button", {
503
+ ref: setTriggerEl,
440
504
  type: "button",
441
505
  "aria-label": t('@astryx.sideNav.heading.openMenu'),
442
506
  onClick: e => {
@@ -444,9 +508,7 @@ export function SideNavHeading({
444
508
  triggerProps.onClick();
445
509
  },
446
510
  ...popover.triggerProps,
447
- ...{
448
- className: "x2lah0s x78zum5 x6s0dn4 xl56j7k xy8csz5 ximsjs8 xv9yike x1ypdohk xh6dtrn xc342km xng3xce xjbqb8w xjb2p0i x1qlqyl8 x1sodnla x1yc453h xe9uy6x"
449
- },
511
+ ...focusOutlineProps.focusVisible(styles.chevron, styles.interactive),
450
512
  children: /*#__PURE__*/_jsx(Icon, {
451
513
  icon: "chevronDown",
452
514
  size: "sm",
@@ -486,9 +548,7 @@ export function SideNavHeading({
486
548
  children: [icon && (headingHref ? /*#__PURE__*/_jsx(LinkComponent, {
487
549
  href: headingHref,
488
550
  "aria-label": heading,
489
- ...{
490
- className: "x2lah0s x78zum5 x6s0dn4 xl56j7k"
491
- },
551
+ ...focusOutlineProps.focusVisible(styles.icon),
492
552
  children: icon
493
553
  }) : /*#__PURE__*/_jsx("span", {
494
554
  ...{
@@ -496,6 +556,7 @@ export function SideNavHeading({
496
556
  },
497
557
  children: icon
498
558
  })), renderTextContent(showChevron ? /*#__PURE__*/_jsx("button", {
559
+ ref: setTriggerEl,
499
560
  type: "button",
500
561
  "aria-label": t('@astryx.sideNav.heading.openMenu'),
501
562
  onClick: e => {
@@ -503,9 +564,7 @@ export function SideNavHeading({
503
564
  triggerProps.onClick();
504
565
  },
505
566
  ...popover.triggerProps,
506
- ...{
507
- className: "x2lah0s x78zum5 x6s0dn4 xl56j7k xy8csz5 ximsjs8 xv9yike x1ypdohk xh6dtrn xc342km xng3xce xjbqb8w xjb2p0i x1qlqyl8 x1sodnla x1yc453h xe9uy6x"
508
- },
567
+ ...focusOutlineProps.focusVisible(styles.chevron, styles.interactive),
509
568
  children: /*#__PURE__*/_jsx(Icon, {
510
569
  icon: "chevronDown",
511
570
  size: "sm",
@@ -542,9 +601,7 @@ export function SideNavHeading({
542
601
  children: [icon && (headingHref ? /*#__PURE__*/_jsx(LinkComponent, {
543
602
  href: headingHref,
544
603
  "aria-label": heading,
545
- ...{
546
- className: "x2lah0s x78zum5 x6s0dn4 xl56j7k"
547
- },
604
+ ...focusOutlineProps.focusVisible(styles.icon),
548
605
  children: icon
549
606
  }) : /*#__PURE__*/_jsx("span", {
550
607
  ...{
@@ -1,11 +1,16 @@
1
1
  /**
2
2
  * @file SideNavItem.tsx
3
- * @input Uses React, ReactNode, StyleX, Icon, IconType
3
+ * @input Uses React, ReactNode, StyleX, Icon, IconType, useMenuHover
4
4
  * @output Exports SideNavItem component and SideNavItemProps
5
5
  * @position Core implementation; used inside SideNav children
6
6
  *
7
7
  * Navigation item with icon, selected state, and nesting.
8
8
  *
9
+ * Collapsed items with children open their submenu flyout through
10
+ * `useMenuHover`, the shared hover-intent hook (same one `SideNavHeading` and
11
+ * `TopNavMenu` use). Hover is a progressive enhancement over the popover's
12
+ * click behavior and is inert on coarse pointers.
13
+ *
9
14
  * SYNC: When modified, update these files to stay in sync:
10
15
  * - /packages/core/src/SideNav/SideNav.doc.mjs
11
16
  * - /packages/core/src/SideNav/SideNav.test.tsx
@@ -107,7 +112,7 @@ export interface SideNavItemProps extends BaseProps<HTMLElement> {
107
112
  * </SideNavItem>
108
113
  * ```
109
114
  */
110
- export declare function SideNavItem({ as, label, icon, selectedIcon, isSelected, isDisabled, href, onClick, endContent, children, collapsible: itemCollapsible, size, 'data-testid': testId, ref, xstyle, }: SideNavItemProps): import("react").JSX.Element | null;
115
+ export declare function SideNavItem({ as, label, icon, selectedIcon, isSelected, isDisabled, href, onClick, endContent, children, collapsible: itemCollapsible, size, 'data-testid': testId, ref, xstyle, ...rest }: SideNavItemProps): import("react").JSX.Element | null;
111
116
  export declare namespace SideNavItem {
112
117
  var displayName: string;
113
118
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SideNavItem.d.ts","sourceRoot":"","sources":["../../src/SideNav/SideNavItem.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAaf,OAAO,EAAuB,KAAK,QAAQ,EAAC,MAAM,SAAS,CAAC;AAE5D,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,eAAe,CAAC;AAGrD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAE5C,OAAO,EAAgB,KAAK,WAAW,EAAC,MAAM,iCAAiC,CAAC;AA4MhF,MAAM,WAAW,gBAAiB,SAAQ,SAAS,CAAC,WAAW,CAAC;IAC9D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC7B;;;;OAIG;IACH,EAAE,CAAC,EAAE,iBAAiB,CAAC;IACvB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC5B;;OAEG;IACH,YAAY,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IACpC;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACxC;;OAEG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB;;;;;;;;;;OAUG;IACH,WAAW,CAAC,EACR,OAAO,GACP;QACE,kBAAkB,CAAC,EAAE,OAAO,CAAC;QAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,iBAAiB,CAAC,EAAE,CAAC,WAAW,EAAE,OAAO,KAAK,IAAI,CAAC;KACpD,CAAC;IACN;;;OAGG;IACH,IAAI,CAAC,EAAE,WAAW,CAAC;CACpB;AAMD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,WAAW,CAAC,EAC1B,EAAE,EACF,KAAK,EACL,IAAI,EACJ,YAAY,EACZ,UAAkB,EAClB,UAAkB,EAClB,IAAI,EACJ,OAAO,EACP,UAAU,EACV,QAAQ,EACR,WAAW,EAAE,eAAe,EAC5B,IAAW,EACX,aAAa,EAAE,MAAM,EACrB,GAAG,EACH,MAAM,GACP,EAAE,gBAAgB,sCAuVlB;yBAvWe,WAAW"}
1
+ {"version":3,"file":"SideNavItem.d.ts","sourceRoot":"","sources":["../../src/SideNav/SideNavItem.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAYf,OAAO,EAAuB,KAAK,QAAQ,EAAC,MAAM,SAAS,CAAC;AAE5D,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,eAAe,CAAC;AAIrD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAE5C,OAAO,EAAgB,KAAK,WAAW,EAAC,MAAM,iCAAiC,CAAC;AA8NhF,MAAM,WAAW,gBAAiB,SAAQ,SAAS,CAAC,WAAW,CAAC;IAC9D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC7B;;;;OAIG;IACH,EAAE,CAAC,EAAE,iBAAiB,CAAC;IACvB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC5B;;OAEG;IACH,YAAY,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IACpC;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IACxC;;OAEG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB;;;;;;;;;;OAUG;IACH,WAAW,CAAC,EACR,OAAO,GACP;QACE,kBAAkB,CAAC,EAAE,OAAO,CAAC;QAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,iBAAiB,CAAC,EAAE,CAAC,WAAW,EAAE,OAAO,KAAK,IAAI,CAAC;KACpD,CAAC;IACN;;;OAGG;IACH,IAAI,CAAC,EAAE,WAAW,CAAC;CACpB;AAMD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,WAAW,CAAC,EAC1B,EAAE,EACF,KAAK,EACL,IAAI,EACJ,YAAY,EACZ,UAAkB,EAClB,UAAkB,EAClB,IAAI,EACJ,OAAO,EACP,UAAU,EACV,QAAQ,EACR,WAAW,EAAE,eAAe,EAC5B,IAAW,EACX,aAAa,EAAE,MAAM,EACrB,GAAG,EACH,MAAM,EACN,GAAG,IAAI,EACR,EAAE,gBAAgB,sCA4UlB;yBA7Ve,WAAW"}
@@ -4,12 +4,17 @@
4
4
 
5
5
  /**
6
6
  * @file SideNavItem.tsx
7
- * @input Uses React, ReactNode, StyleX, Icon, IconType
7
+ * @input Uses React, ReactNode, StyleX, Icon, IconType, useMenuHover
8
8
  * @output Exports SideNavItem component and SideNavItemProps
9
9
  * @position Core implementation; used inside SideNav children
10
10
  *
11
11
  * Navigation item with icon, selected state, and nesting.
12
12
  *
13
+ * Collapsed items with children open their submenu flyout through
14
+ * `useMenuHover`, the shared hover-intent hook (same one `SideNavHeading` and
15
+ * `TopNavMenu` use). Hover is a progressive enhancement over the popover's
16
+ * click behavior and is inert on coarse pointers.
17
+ *
13
18
  * SYNC: When modified, update these files to stay in sync:
14
19
  * - /packages/core/src/SideNav/SideNav.doc.mjs
15
20
  * - /packages/core/src/SideNav/SideNav.test.tsx
@@ -20,13 +25,15 @@
20
25
  import { useCallback, useId, useMemo, useRef, useState } from 'react';
21
26
  import * as stylex from '@stylexjs/stylex';
22
27
  import "../theme/tokens.stylex.js";
23
- import { colorVars, spacingVars, sizeVars, fontWeightVars, typeScaleVars, durationVars, easeVars, borderVars, radiusVars } from "../theme/tokens.stylex.js";
28
+ import { colorVars, spacingVars, sizeVars, fontWeightVars, typeScaleVars, durationVars, easeVars, radiusVars } from "../theme/tokens.stylex.js";
24
29
  import { Icon, renderIconSlot } from "../Icon/index.js";
25
30
  import { useLinkComponent } from "../Link/useLinkComponent.js";
26
31
  import { usePopover } from "../Popover/usePopover.js";
32
+ import { useMenuHover } from "../hooks/useMenuHover.js";
27
33
  import { mergeProps, mergeRefs } from "../utils/index.js";
28
34
  import { Tooltip } from "../Tooltip/index.js";
29
35
  import { navItemStyles } from "../NavItem/navItemStyles.stylex.js";
36
+ import { focusOutlineProps } from "../utils/focusOutline.stylex.js";
30
37
  import { useSideNavCollapse, SideNavCollapseContext } from "./SideNavCollapseContext.js";
31
38
  import { useSideNavRenderMode } from "./SideNavRenderContext.js";
32
39
  import { useAppShellMobile } from "../AppShell/AppShellMobileContext.js";
@@ -66,7 +73,7 @@ const styles = {
66
73
  kZKoxP: "xvpftlf",
67
74
  kGuDYH: "x1qlqyl8",
68
75
  k1ekBW: "x11xpdln",
69
- kIyJzY: "xuedmi6",
76
+ kIyJzY: "xuedmi6 x12w9bfk",
70
77
  kAMwcw: "xlr8y92",
71
78
  kmuXW: "x2lah0s",
72
79
  $$css: true
@@ -74,6 +81,50 @@ const styles = {
74
81
  expandChevronExpanded: {
75
82
  k3aq6I: "x19jd1h0",
76
83
  $$css: true
84
+ },
85
+ expandToggle: {
86
+ k1xSpc: "x3nfvp2",
87
+ kGNEyG: "x6s0dn4",
88
+ kjj79g: "xl56j7k",
89
+ kmuXW: "x2lah0s",
90
+ kmVPX3: "x1717udv",
91
+ kogj98: "x1ghz6dp",
92
+ kMzoRj: "xc342km",
93
+ ksu8eU: "xng3xce",
94
+ kWkggS: "xjbqb8w",
95
+ kMwMTN: "x1heor9g",
96
+ kkrTdU: "x1ypdohk",
97
+ kaIpWk: "xh6dtrn",
98
+ kHE3J0: "xe9uy6x",
99
+ kSReZ0: "xyxi2l3",
100
+ $$css: true
101
+ },
102
+ splitAction: {
103
+ k1xSpc: "x78zum5",
104
+ kGNEyG: "x6s0dn4",
105
+ kSGwAc: "xkh2ocl",
106
+ kOIVth: "x1txdalj",
107
+ kUk6DE: "x98rzlu",
108
+ k7Eaqz: "xeuugli",
109
+ kMwMTN: "x1heor9g",
110
+ kybGjl: "x1hl2dhg",
111
+ kmVPX3: "x1717udv",
112
+ kogj98: "x1ghz6dp",
113
+ kMzoRj: "xc342km",
114
+ ksu8eU: "xng3xce",
115
+ kWkggS: "xjbqb8w",
116
+ kMv6JI: "xjb2p0i",
117
+ kGuDYH: "x1qlqyl8",
118
+ k63SB2: "x1pd3egz",
119
+ kLWn49: "x15bjb6t",
120
+ k9WMMc: "x1yc453h",
121
+ kkrTdU: "x1ypdohk",
122
+ $$css: true
123
+ },
124
+ popoverGap: {
125
+ keTefX: "x11g1kdw",
126
+ k71WvV: "xnur1sd",
127
+ $$css: true
77
128
  }
78
129
  };
79
130
 
@@ -164,7 +215,8 @@ export function SideNavItem({
164
215
  size = 'md',
165
216
  'data-testid': testId,
166
217
  ref,
167
- xstyle
218
+ xstyle,
219
+ ...rest
168
220
  }) {
169
221
  const t = useTranslator();
170
222
  const {
@@ -184,7 +236,9 @@ export function SideNavItem({
184
236
  hasLightDismiss: true,
185
237
  hasAutoFocus: true,
186
238
  hasCloseButton: false,
187
- dialogLabel: `${label} submenu`
239
+ dialogLabel: t('@astryx.sideNavItem.submenuLabel', {
240
+ label
241
+ })
188
242
  });
189
243
 
190
244
  // Collapse state for items with children
@@ -230,39 +284,24 @@ export function SideNavItem({
230
284
  toggleItemCollapse();
231
285
  };
232
286
 
233
- // Hover handlers for collapsed popover (mirrors TopNavMenu pattern)
234
- const showTimeoutRef = useRef(null);
235
- const hideTimeoutRef = useRef(null);
236
- const clearPopoverTimeouts = useCallback(() => {
237
- if (showTimeoutRef.current) {
238
- clearTimeout(showTimeoutRef.current);
239
- showTimeoutRef.current = null;
240
- }
241
- if (hideTimeoutRef.current) {
242
- clearTimeout(hideTimeoutRef.current);
243
- hideTimeoutRef.current = null;
244
- }
245
- }, []);
246
- const schedulePopoverShow = useCallback(() => {
247
- clearPopoverTimeouts();
248
- showTimeoutRef.current = setTimeout(() => {
249
- popover.show({
250
- skipAutoFocus: true
251
- });
252
- }, 150);
253
- }, [clearPopoverTimeouts, popover]);
254
- const schedulePopoverHide = useCallback(() => {
255
- clearPopoverTimeouts();
256
- hideTimeoutRef.current = setTimeout(() => {
257
- popover.hide();
258
- }, 200);
259
- }, [clearPopoverTimeouts, popover]);
260
- const handlePopoverMouseEnter = useCallback(() => {
261
- schedulePopoverShow();
262
- }, [schedulePopoverShow]);
263
- const handlePopoverMouseLeave = useCallback(() => {
264
- schedulePopoverHide();
265
- }, [schedulePopoverHide]);
287
+ // Pointer half only. The hook's `onKeyDown`/`menuRef` drive a `useListFocus`
288
+ // over `[role="menuitem"]`, and this flyout is a focus-trapped dialog of
289
+ // links wiring them would swallow arrow keys rather than navigate with
290
+ // them. Keyboard stays with `usePopover`'s trap, as in DropdownMenuSubMenu.
291
+ const {
292
+ triggerProps: hoverTriggerProps,
293
+ contentProps: hoverContentProps
294
+ } = useMenuHover({
295
+ show: popover.show,
296
+ hide: popover.hide,
297
+ isOpen: popover.isOpen,
298
+ isEnabled: isCollapsed && hasChildren,
299
+ // Standard popover toggling: the flyout opens beside the rail, not over
300
+ // the icon, so the click after a hover-open is a deliberate dismissal
301
+ // rather than the #3121 confirmation the nav menus need.
302
+ clickGuardMs: 0,
303
+ ownsFocus: false
304
+ });
266
305
 
267
306
  // In collapsed mode: hide items without icons
268
307
  if (isCollapsed && !icon) {
@@ -275,14 +314,19 @@ export function SideNavItem({
275
314
  if (isCollapsed) {
276
315
  const collapsedIcon = displayIcon && renderIconSlot(displayIcon, {
277
316
  size: 'sm',
278
- color: isSelected ? 'primary' : isDisabled ? 'disabled' : 'secondary'
317
+ // `inherit` so a selected row's icon follows the row to HighlightText
318
+ // under forced colors. Identical to `primary` otherwise: both token
319
+ // families are emitted from one expression.
320
+ color: isSelected ? 'inherit' : isDisabled ? 'disabled' : 'secondary'
279
321
  });
280
322
 
281
- // Shared collapsed item styles — used by trigger, link, and button
323
+ // Shared collapsed item styles — used by trigger, link, and button.
324
+ // All three render a focusable element, so each draws the shared ring.
282
325
  const collapsedItemStyles = mergeProps(themeProps('side-nav-item', {
283
326
  size,
284
- selected: isSelected ? 'selected' : null
285
- }), stylex.props(navItemStyles.item, navItemStyles[size], styles.itemCollapsed, size === 'sm' && styles.itemCollapsedSm, size === 'lg' && styles.itemCollapsedLg, isSelected && navItemStyles.selected, isDisabled && navItemStyles.disabled));
327
+ selected: isSelected ? 'selected' : null,
328
+ disabled: isDisabled ? 'disabled' : null
329
+ }), focusOutlineProps.focusVisible(navItemStyles.item, navItemStyles[size], styles.itemCollapsed, size === 'sm' && styles.itemCollapsedSm, size === 'lg' && styles.itemCollapsedLg, isSelected && navItemStyles.selected, isDisabled && navItemStyles.disabled));
286
330
 
287
331
  // Items with children: popover trigger + popover
288
332
  if (hasChildren) {
@@ -291,9 +335,8 @@ export function SideNavItem({
291
335
  children: [/*#__PURE__*/_jsx("button", {
292
336
  ref: mergeRefs(ref, popover.triggerRef),
293
337
  type: "button",
294
- onClick: popover.toggle,
295
- onMouseEnter: handlePopoverMouseEnter,
296
- onMouseLeave: handlePopoverMouseLeave,
338
+ ...rest,
339
+ ...hoverTriggerProps,
297
340
  "aria-label": label,
298
341
  "data-testid": testId,
299
342
  ...popover.triggerProps,
@@ -301,10 +344,10 @@ export function SideNavItem({
301
344
  children: collapsedIcon
302
345
  }), popover.render(/*#__PURE__*/_jsxs("div", {
303
346
  ...{
304
- className: "x1litavf x1y0btm7 x14i3s5s xu0wf1k x7a5moj x11g1kdw xfb3i0g"
347
+ className: "x1hviunn xu0wf1k x7a5moj xfb3i0g"
305
348
  },
306
- onMouseEnter: handlePopoverMouseEnter,
307
- onMouseLeave: handlePopoverMouseLeave,
349
+ onMouseEnter: hoverContentProps.onMouseEnter,
350
+ onMouseLeave: hoverContentProps.onMouseLeave,
308
351
  onClick: () => popover.hide(),
309
352
  children: [/*#__PURE__*/_jsx("div", {
310
353
  ...{
@@ -317,7 +360,8 @@ export function SideNavItem({
317
360
  })]
318
361
  }), {
319
362
  placement: 'end',
320
- alignment: 'start'
363
+ alignment: 'start',
364
+ xstyle: styles.popoverGap
321
365
  })]
322
366
  });
323
367
  }
@@ -335,6 +379,7 @@ export function SideNavItem({
335
379
  as: as,
336
380
  isDisabled: isDisabled,
337
381
  onClick: handleClick,
382
+ ...rest,
338
383
  ...collapsedAriaProps,
339
384
  ...collapsedItemStyles,
340
385
  children: collapsedIcon
@@ -352,7 +397,8 @@ export function SideNavItem({
352
397
  const itemContent = /*#__PURE__*/_jsxs(_Fragment, {
353
398
  children: [displayIcon && renderIconSlot(displayIcon, {
354
399
  size: 'sm',
355
- color: isSelected ? 'primary' : isDisabled ? 'disabled' : 'secondary'
400
+ // `inherit` see the collapsed path above.
401
+ color: isSelected ? 'inherit' : isDisabled ? 'disabled' : 'secondary'
356
402
  }), !isCollapsed && /*#__PURE__*/_jsx("span", {
357
403
  ...{
358
404
  className: "x98rzlu xeuugli xb3r6kr xlyipyv xuxw1ft"
@@ -370,39 +416,38 @@ export function SideNavItem({
370
416
  xstyle: [styles.expandChevron, !isItemCollapsed && styles.expandChevronExpanded]
371
417
  })]
372
418
  });
373
- const navItemStyleProps = mergeProps(themeProps('side-nav-item', {
419
+ const itemThemeProps = themeProps('side-nav-item', {
374
420
  size,
375
- selected: isSelected ? 'selected' : null
376
- }), stylex.props(navItemStyles.item, navItemStyles[size], isSelected && navItemStyles.selected, isDisabled && navItemStyles.disabled));
377
-
378
- // ── Split-action path: <div> row with <a> + <button> as siblings ──
379
- //
380
- // When both collapsible and href are set, we can't nest a <button>
381
- // inside an <a>. Instead we use a <div> as the flex row container,
382
- // an <a display:contents> for the link (with ::before covering the row),
383
- // and a <button> sibling lifted above the overlay via z-index.
421
+ selected: isSelected ? 'selected' : null,
422
+ disabled: isDisabled ? 'disabled' : null
423
+ });
424
+ const itemStyleArgs = [navItemStyles.item, navItemStyles[size], isSelected && navItemStyles.selected, isDisabled && navItemStyles.disabled];
384
425
 
385
- // ── Split-action path: primary element + toggle button as siblings ──
386
- //
387
- // When collapsible and a primary action (href or onClick) are both set,
388
- // we render a <div> row with the primary element and chevron toggle as
389
- // siblings. This avoids nesting interactive elements (<button> inside <a>).
426
+ // Two shapes of the same row appearance:
427
+ // - `rowProps` for the split-action path, where the row is a plain <div>
428
+ // container and its children take focus (so the ring belongs on them);
429
+ // - `focusableRowProps` for every other path, where the row element is
430
+ // itself the focusable control.
431
+ const rowProps = mergeProps(itemThemeProps, stylex.props(...itemStyleArgs));
432
+ const focusableRowProps = mergeProps(itemThemeProps, focusOutlineProps.focusVisible(...itemStyleArgs));
390
433
 
434
+ // Split-action path: collapsible plus a primary action renders the primary
435
+ // element and the chevron toggle as siblings in a <div> row, since a
436
+ // <button> cannot nest inside an <a>.
391
437
  let itemElement;
392
438
  if (hasIndependentToggle) {
393
439
  itemElement = /*#__PURE__*/_jsxs("div", {
394
440
  "data-testid": testId,
395
- ...navItemStyleProps,
441
+ ...rowProps,
396
442
  children: [/*#__PURE__*/_jsx(NavItemElement, {
397
443
  ref: ref,
398
444
  href: href,
399
445
  as: as,
400
446
  isDisabled: isDisabled,
401
447
  onClick: handleClick,
448
+ ...rest,
402
449
  "aria-current": isSelected ? 'page' : undefined,
403
- ...{
404
- className: "x78zum5 x6s0dn4 x1txdalj x98rzlu xeuugli x1heor9g x1hl2dhg x1717udv x1ghz6dp xc342km xng3xce xjbqb8w xjb2p0i x1qlqyl8 x1pd3egz x15bjb6t x1yc453h x1ypdohk"
405
- },
450
+ ...focusOutlineProps.focusVisible(styles.splitAction),
406
451
  children: itemContent
407
452
  }), /*#__PURE__*/_jsx("button", {
408
453
  type: "button",
@@ -414,9 +459,7 @@ export function SideNavItem({
414
459
  }),
415
460
  "aria-expanded": !isItemCollapsed,
416
461
  "aria-controls": `${id}-children`,
417
- ...{
418
- className: "x3nfvp2 x6s0dn4 xl56j7k x2lah0s x1717udv x1ghz6dp xc342km xng3xce xjbqb8w x1heor9g x1ypdohk xh6dtrn xe9uy6x xyxi2l3"
419
- },
462
+ ...focusOutlineProps.focusVisible(styles.expandToggle),
420
463
  children: /*#__PURE__*/_jsx(Icon, {
421
464
  icon: "chevronDown",
422
465
  size: "lg",
@@ -439,8 +482,9 @@ export function SideNavItem({
439
482
  as: as,
440
483
  isDisabled: isDisabled,
441
484
  onClick: handleClick,
485
+ ...rest,
442
486
  ...ariaProps,
443
- ...navItemStyleProps,
487
+ ...focusableRowProps,
444
488
  children: itemContent
445
489
  });
446
490
  }
@@ -455,10 +499,10 @@ export function SideNavItem({
455
499
  inert: isItemCollapsed ? true : undefined,
456
500
  ...{
457
501
  0: {
458
- className: "xrvj5dj x1tu4anv x1qn9uv2 x80gvsz xlr8y92"
502
+ className: "xrvj5dj x1tu4anv x1qn9uv2 x80gvsz x12w9bfk xlr8y92"
459
503
  },
460
504
  1: {
461
- className: "xrvj5dj x1qn9uv2 x80gvsz xlr8y92 xihq33y"
505
+ className: "xrvj5dj x1qn9uv2 x80gvsz x12w9bfk xlr8y92 xihq33y"
462
506
  }
463
507
  }[!!isItemCollapsed << 0],
464
508
  children: /*#__PURE__*/_jsxs("div", {
@@ -1 +1 @@
1
- {"version":3,"file":"SideNavSection.d.ts","sourceRoot":"","sources":["../../src/SideNav/SideNavSection.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,EAAQ,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AASnD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AA+D5C,MAAM,WAAW,mBAAoB,SAAQ,SAAS,CAAC,cAAc,CAAC;IACpE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IACpB;;OAEG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,EAC7B,GAAG,EACH,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,cAAsB,EACtB,MAAM,EACN,SAAS,EACT,KAAK,EACL,aAAa,EAAE,MAAM,EACrB,GAAG,IAAI,EACR,EAAE,mBAAmB,qBAyDrB;yBArEe,cAAc"}
1
+ {"version":3,"file":"SideNavSection.d.ts","sourceRoot":"","sources":["../../src/SideNav/SideNavSection.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,EAAQ,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AASnD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAgE5C,MAAM,WAAW,mBAAoB,SAAQ,SAAS,CAAC,cAAc,CAAC;IACpE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IACpB;;OAEG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,EAC7B,GAAG,EACH,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,cAAsB,EACtB,MAAM,EACN,SAAS,EACT,KAAK,EACL,aAAa,EAAE,MAAM,EACrB,GAAG,IAAI,EACR,EAAE,mBAAmB,qBA0CrB;yBAtDe,cAAc"}