@dnanpm/ui-components 0.7.0 → 0.9.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.
Files changed (159) hide show
  1. package/dist/components/Accordion/Accordion.css +6 -3
  2. package/dist/components/AccordionItem/AccordionItem.css +6 -3
  3. package/dist/components/Breadcrumb/Breadcrumb.css +15 -12
  4. package/dist/components/Breadcrumb/Breadcrumb.module.css.cjs +6 -6
  5. package/dist/components/Breadcrumb/Breadcrumb.module.css.js +6 -6
  6. package/dist/components/Button/Button.css +33 -32
  7. package/dist/components/Button/Button.module.css.cjs +11 -11
  8. package/dist/components/Button/Button.module.css.js +11 -11
  9. package/dist/components/ButtonCard/ButtonCard.cjs +105 -0
  10. package/dist/components/ButtonCard/ButtonCard.cjs.map +1 -0
  11. package/dist/components/ButtonCard/ButtonCard.css +166 -0
  12. package/dist/components/ButtonCard/ButtonCard.d.ts +3 -0
  13. package/dist/components/ButtonCard/ButtonCard.d.ts.map +1 -0
  14. package/dist/components/ButtonCard/ButtonCard.js +105 -0
  15. package/dist/components/ButtonCard/ButtonCard.js.map +1 -0
  16. package/dist/components/ButtonCard/ButtonCard.module.css.cjs +18 -0
  17. package/dist/components/ButtonCard/ButtonCard.module.css.cjs.map +1 -0
  18. package/dist/components/ButtonCard/ButtonCard.module.css.js +19 -0
  19. package/dist/components/ButtonCard/ButtonCard.module.css.js.map +1 -0
  20. package/dist/components/ButtonCard/ButtonCard.types.d.ts +103 -0
  21. package/dist/components/ButtonCard/ButtonCard.types.d.ts.map +1 -0
  22. package/dist/components/ButtonCard/index.d.ts +3 -0
  23. package/dist/components/ButtonCard/index.d.ts.map +1 -0
  24. package/dist/components/ContentCard/ContentCard.cjs +96 -0
  25. package/dist/components/ContentCard/ContentCard.cjs.map +1 -0
  26. package/dist/components/ContentCard/ContentCard.css +249 -0
  27. package/dist/components/ContentCard/ContentCard.d.ts +3 -0
  28. package/dist/components/ContentCard/ContentCard.d.ts.map +1 -0
  29. package/dist/components/ContentCard/ContentCard.js +96 -0
  30. package/dist/components/ContentCard/ContentCard.js.map +1 -0
  31. package/dist/components/ContentCard/ContentCard.module.css.cjs +24 -0
  32. package/dist/components/ContentCard/ContentCard.module.css.cjs.map +1 -0
  33. package/dist/components/ContentCard/ContentCard.module.css.js +25 -0
  34. package/dist/components/ContentCard/ContentCard.module.css.js.map +1 -0
  35. package/dist/components/ContentCard/ContentCard.types.d.ts +99 -0
  36. package/dist/components/ContentCard/ContentCard.types.d.ts.map +1 -0
  37. package/dist/components/ContentCard/index.d.ts +3 -0
  38. package/dist/components/ContentCard/index.d.ts.map +1 -0
  39. package/dist/components/Drawer/Drawer.cjs +101 -0
  40. package/dist/components/Drawer/Drawer.cjs.map +1 -0
  41. package/dist/components/Drawer/Drawer.css +218 -0
  42. package/dist/components/Drawer/Drawer.d.ts +3 -0
  43. package/dist/components/Drawer/Drawer.d.ts.map +1 -0
  44. package/dist/components/Drawer/Drawer.js +101 -0
  45. package/dist/components/Drawer/Drawer.js.map +1 -0
  46. package/dist/components/Drawer/Drawer.module.css.cjs +37 -0
  47. package/dist/components/Drawer/Drawer.module.css.cjs.map +1 -0
  48. package/dist/components/Drawer/Drawer.module.css.js +37 -0
  49. package/dist/components/Drawer/Drawer.module.css.js.map +1 -0
  50. package/dist/components/Drawer/Drawer.types.d.ts +63 -0
  51. package/dist/components/Drawer/Drawer.types.d.ts.map +1 -0
  52. package/dist/components/Drawer/index.d.ts +3 -0
  53. package/dist/components/Drawer/index.d.ts.map +1 -0
  54. package/dist/components/Footer/Footer.css +87 -77
  55. package/dist/components/Footer/Footer.module.css.cjs +39 -39
  56. package/dist/components/Footer/Footer.module.css.js +39 -39
  57. package/dist/components/FunctionButton/FunctionButton.cjs +34 -0
  58. package/dist/components/FunctionButton/FunctionButton.cjs.map +1 -0
  59. package/dist/components/FunctionButton/FunctionButton.css +124 -0
  60. package/dist/components/FunctionButton/FunctionButton.d.ts +3 -0
  61. package/dist/components/FunctionButton/FunctionButton.d.ts.map +1 -0
  62. package/dist/components/FunctionButton/FunctionButton.js +34 -0
  63. package/dist/components/FunctionButton/FunctionButton.js.map +1 -0
  64. package/dist/components/FunctionButton/FunctionButton.module.css.cjs +11 -0
  65. package/dist/components/FunctionButton/FunctionButton.module.css.cjs.map +1 -0
  66. package/dist/components/FunctionButton/FunctionButton.module.css.js +12 -0
  67. package/dist/components/FunctionButton/FunctionButton.module.css.js.map +1 -0
  68. package/dist/components/FunctionButton/FunctionButton.types.d.ts +21 -0
  69. package/dist/components/FunctionButton/FunctionButton.types.d.ts.map +1 -0
  70. package/dist/components/FunctionButton/index.d.ts +3 -0
  71. package/dist/components/FunctionButton/index.d.ts.map +1 -0
  72. package/dist/components/Hero/Hero.cjs +24 -26
  73. package/dist/components/Hero/Hero.cjs.map +1 -1
  74. package/dist/components/Hero/Hero.css +81 -74
  75. package/dist/components/Hero/Hero.js +24 -26
  76. package/dist/components/Hero/Hero.js.map +1 -1
  77. package/dist/components/Hero/Hero.module.css.cjs +20 -17
  78. package/dist/components/Hero/Hero.module.css.cjs.map +1 -1
  79. package/dist/components/Hero/Hero.module.css.js +20 -17
  80. package/dist/components/Hero/Hero.module.css.js.map +1 -1
  81. package/dist/components/IconButton/IconButton.css +32 -34
  82. package/dist/components/IconButton/IconButton.module.css.cjs +9 -9
  83. package/dist/components/IconButton/IconButton.module.css.js +9 -9
  84. package/dist/components/Label/Label.css +2 -3
  85. package/dist/components/MainNavigation/MainNavigation.cjs +415 -120
  86. package/dist/components/MainNavigation/MainNavigation.cjs.map +1 -1
  87. package/dist/components/MainNavigation/MainNavigation.css +265 -159
  88. package/dist/components/MainNavigation/MainNavigation.d.ts +1 -1
  89. package/dist/components/MainNavigation/MainNavigation.d.ts.map +1 -1
  90. package/dist/components/MainNavigation/MainNavigation.js +417 -122
  91. package/dist/components/MainNavigation/MainNavigation.js.map +1 -1
  92. package/dist/components/MainNavigation/MainNavigation.module.css.cjs +78 -68
  93. package/dist/components/MainNavigation/MainNavigation.module.css.cjs.map +1 -1
  94. package/dist/components/MainNavigation/MainNavigation.module.css.js +78 -68
  95. package/dist/components/MainNavigation/MainNavigation.module.css.js.map +1 -1
  96. package/dist/components/MainNavigation/MainNavigation.types.d.ts +64 -17
  97. package/dist/components/MainNavigation/MainNavigation.types.d.ts.map +1 -1
  98. package/dist/components/MainNavigation/MainNavigation.utils.cjs +20 -0
  99. package/dist/components/MainNavigation/MainNavigation.utils.cjs.map +1 -1
  100. package/dist/components/MainNavigation/MainNavigation.utils.d.ts +10 -1
  101. package/dist/components/MainNavigation/MainNavigation.utils.d.ts.map +1 -1
  102. package/dist/components/MainNavigation/MainNavigation.utils.js +20 -0
  103. package/dist/components/MainNavigation/MainNavigation.utils.js.map +1 -1
  104. package/dist/components/MainNavigation/index.d.ts +1 -1
  105. package/dist/components/MainNavigation/index.d.ts.map +1 -1
  106. package/dist/components/Modal/Modal.cjs +101 -0
  107. package/dist/components/Modal/Modal.cjs.map +1 -0
  108. package/dist/components/Modal/Modal.css +204 -0
  109. package/dist/components/Modal/Modal.d.ts +3 -0
  110. package/dist/components/Modal/Modal.d.ts.map +1 -0
  111. package/dist/components/Modal/Modal.js +101 -0
  112. package/dist/components/Modal/Modal.js.map +1 -0
  113. package/dist/components/Modal/Modal.module.css.cjs +39 -0
  114. package/dist/components/Modal/Modal.module.css.cjs.map +1 -0
  115. package/dist/components/Modal/Modal.module.css.js +39 -0
  116. package/dist/components/Modal/Modal.module.css.js.map +1 -0
  117. package/dist/components/Modal/Modal.types.d.ts +62 -0
  118. package/dist/components/Modal/Modal.types.d.ts.map +1 -0
  119. package/dist/components/Modal/index.d.ts +3 -0
  120. package/dist/components/Modal/index.d.ts.map +1 -0
  121. package/dist/components/Modal/useDialogDismissal.cjs +41 -0
  122. package/dist/components/Modal/useDialogDismissal.cjs.map +1 -0
  123. package/dist/components/Modal/useDialogDismissal.d.ts +17 -0
  124. package/dist/components/Modal/useDialogDismissal.d.ts.map +1 -0
  125. package/dist/components/Modal/useDialogDismissal.js +41 -0
  126. package/dist/components/Modal/useDialogDismissal.js.map +1 -0
  127. package/dist/components/Modal/useNativeDialog.cjs +126 -0
  128. package/dist/components/Modal/useNativeDialog.cjs.map +1 -0
  129. package/dist/components/Modal/useNativeDialog.d.ts +14 -0
  130. package/dist/components/Modal/useNativeDialog.d.ts.map +1 -0
  131. package/dist/components/Modal/useNativeDialog.js +126 -0
  132. package/dist/components/Modal/useNativeDialog.js.map +1 -0
  133. package/dist/components/Notification/Notification.css +6 -3
  134. package/dist/components/Pictograph/Pictograph.css +6 -3
  135. package/dist/components/Pictograph/PictographItem.css +6 -3
  136. package/dist/components/Quote/Quote.css +2 -3
  137. package/dist/components/Spinner/Spinner.css +6 -3
  138. package/dist/index.cjs +10 -0
  139. package/dist/index.cjs.map +1 -1
  140. package/dist/index.d.ts +11 -1
  141. package/dist/index.d.ts.map +1 -1
  142. package/dist/index.js +10 -0
  143. package/dist/index.js.map +1 -1
  144. package/dist/styles/utils/elevation.css +2 -3
  145. package/dist/styles/utils/elevation.module.css.cjs +3 -0
  146. package/dist/styles/utils/elevation.module.css.cjs.map +1 -1
  147. package/dist/styles/utils/elevation.module.css.js +4 -1
  148. package/dist/styles/utils/elevation.module.css.js.map +1 -1
  149. package/dist/styles/utils/focus.css +26 -24
  150. package/dist/styles/utils/focus.module.css.cjs +3 -6
  151. package/dist/styles/utils/focus.module.css.cjs.map +1 -1
  152. package/dist/styles/utils/focus.module.css.js +4 -7
  153. package/dist/styles/utils/focus.module.css.js.map +1 -1
  154. package/dist/styles/utils/overlay.css +2 -3
  155. package/dist/styles/utils/text-decoration.css +4 -4
  156. package/dist/styles/utils/text-decoration.module.css.cjs +2 -2
  157. package/dist/styles/utils/text-decoration.module.css.js +2 -2
  158. package/dist/styles.css +17 -7
  159. package/package.json +3 -3
@@ -1,14 +1,15 @@
1
1
  import { jsxs, jsx, Fragment as Fragment$1 } from "react/jsx-runtime";
2
- import { useState, useRef, useCallback, useEffect, Fragment } from "react";
2
+ import { useState, useRef, useId, useCallback, useEffect, Fragment } from "react";
3
3
  import { Globe, Search, Cart, Close, Menu, ChevronRight, Open, ArrowRight } from "@dnanpm/icons";
4
4
  import focusStyles from "../../styles/utils/focus.module.css.js";
5
5
  import overlayStyles from "../../styles/utils/overlay.module.css.js";
6
6
  import elevationStyles from "../../styles/utils/elevation.module.css.js";
7
7
  import textDecorationStyles from "../../styles/utils/text-decoration.module.css.js";
8
8
  import styles from "./MainNavigation.module.css.js";
9
- import { assignRef, isMobileViewportByEnvironment, isMobileIosDeviceByEnvironment, isDesktopViewportByEnvironment, getLinkTarget, getLinkRel, toNavigableHref, isExternalLink, isItemInCurrentPath, isExternalTarget, isLinkInCurrentPage } from "./MainNavigation.utils.js";
9
+ import { assignRef, isMobileViewportByEnvironment, isMobileIosDeviceByEnvironment, isDesktopViewportByEnvironment, getLinkTarget, getLinkRel, toNavigableHref, isExternalLink, getLanguageToggleAnnouncements, languageLinkAriaLabels, isItemInCurrentPath, isExternalTarget, isLinkInCurrentPage } from "./MainNavigation.utils.js";
10
10
  import { cn } from "../../utils/cn/cn.js";
11
11
  import { Button } from "../Button/Button.js";
12
+ import { Drawer } from "../Drawer/Drawer.js";
12
13
  import { IconButton } from "../IconButton/IconButton.js";
13
14
  const defaultOrganizations = [];
14
15
  const defaultItems = [];
@@ -19,25 +20,30 @@ const mobileBodyScrollLockClass = "dds-un-scrollable";
19
20
  const defaultOverflowCategoryLabel = "Muut kategoriat";
20
21
  const desktopMinWidthMediaQuery = "(min-width: 1024px)";
21
22
  const defaultRenderLink = (props) => /* @__PURE__ */ jsx("a", { ...props });
23
+ const defaultRenderLanguageLink = (props) => /* @__PURE__ */ jsx("a", { ...props });
22
24
  const MainNavigation = ({
23
25
  organizations = defaultOrganizations,
24
26
  items = defaultItems,
25
- loginHref = "#",
26
27
  loginLabel = "Kirjaudu",
27
28
  logoHref = "/",
28
- languageSelectorLabel = "FI",
29
+ languages,
30
+ renderLanguageLink = defaultRenderLanguageLink,
29
31
  searchLabel = "Haku",
30
32
  cartLabel = "Ostoskori",
31
- showLanguageSelector = false,
32
- showSearch = false,
33
- showCart = false,
34
33
  cartCounter,
35
34
  cartCounterLabel = "tuotetta ostoskorissa",
36
- onLanguageSelectorClick,
37
- onSearchClick,
38
- onCartClick,
39
- mobileMenuOpenAriaLabel = "Avaa valikko",
40
- mobileMenuCloseAriaLabel = "Sulje valikko",
35
+ defaultCartOpen = false,
36
+ cartOpen,
37
+ onCartOpenChange,
38
+ defaultOpenDropdown,
39
+ onSearchOpenChange,
40
+ onLanguageOpenChange,
41
+ onLoginOpenChange,
42
+ searchDropdownContent,
43
+ loginDropdownContent,
44
+ cartContent,
45
+ mobileMenuOpenAriaLabel = "Avaa päävalikko",
46
+ mobileMenuCloseAriaLabel = "Sulje päävalikko",
41
47
  organizationStripAriaLabel = "Sivustot",
42
48
  logoAriaLabel = "Siirry etusivulle",
43
49
  mobilePrimaryNavigationAriaLabel = "Päävalikko",
@@ -59,8 +65,17 @@ const MainNavigation = ({
59
65
  const [openTopLevelItemIndex, setOpenTopLevelItemIndex] = useState(
60
66
  defaultOpenItemIndex
61
67
  );
62
- const [isDesktopHeaderOpen, setIsDesktopHeaderOpen] = useState(true);
68
+ const [isHeaderOpen, setIsHeaderOpen] = useState(true);
63
69
  const [mobileActiveCategoryIndex, setMobileActiveCategoryIndex] = useState(null);
70
+ const [internalCartOpen, setInternalCartOpen] = useState(defaultCartOpen);
71
+ const isCartControlled = cartOpen !== void 0;
72
+ const isCartOpen = cartOpen ?? internalCartOpen;
73
+ const hasInitialNavigationSurface = (cartOpen ?? defaultCartOpen) || defaultMobileMenuOpen || defaultOpenItemIndex != null && items[defaultOpenItemIndex]?.panel != null;
74
+ const [openUtilityDropdown, setOpenUtilityDropdown] = useState(hasInitialNavigationSurface ? null : defaultOpenDropdown ?? null);
75
+ const openUtilityDropdownRef = useRef(openUtilityDropdown);
76
+ const searchDropdownId = useId();
77
+ const languageDropdownId = useId();
78
+ const loginDropdownId = useId();
64
79
  const [isMobileSecondPanelClosing, setIsMobileSecondPanelClosing] = useState(false);
65
80
  const [isMobileThirdPanelClosing, setIsMobileThirdPanelClosing] = useState(false);
66
81
  const mobileSecondPanelCloseTimeoutRef = useRef(null);
@@ -76,6 +91,9 @@ const MainNavigation = ({
76
91
  );
77
92
  const headerElementRef = useRef(null);
78
93
  const desktopPanelTriggerButtonRefs = useRef([]);
94
+ const searchTriggerRef = useRef(null);
95
+ const languageTriggerRef = useRef(null);
96
+ const loginTriggerRef = useRef(null);
79
97
  const mobilePrimaryNavRef = useRef(null);
80
98
  const mobileMenuToggleButtonRef = useRef(null);
81
99
  const mobileModalPanelRef = useRef(null);
@@ -85,9 +103,14 @@ const MainNavigation = ({
85
103
  const mobileLevelTwoCategoryButtonRefs = useRef([]);
86
104
  const focusMobilePanelBackOnOpenRef = useRef(false);
87
105
  const focusMobileThirdPanelBackOnOpenRef = useRef(false);
106
+ const lastInteractionWasKeyboardRef = useRef(false);
88
107
  const focusReturnToMobileCategoryTimeoutRef = useRef(
89
108
  null
90
109
  );
110
+ const mobileMenuOpenRef = useRef(mobileMenuOpen);
111
+ const openTopLevelItemIndexRef = useRef(openTopLevelItemIndex);
112
+ const lastAppliedViewportModeRef = useRef(null);
113
+ const internalCartOpenRef = useRef(internalCartOpen);
91
114
  const setHeaderRef = useCallback(
92
115
  (node) => {
93
116
  headerElementRef.current = node;
@@ -130,19 +153,18 @@ const MainNavigation = ({
130
153
  let previousScrollY = window.pageYOffset;
131
154
  let headerHeight = parseFloat(window.getComputedStyle(headerElement).height.replace("px", "")) || headerElement.offsetHeight;
132
155
  const openHeader = () => {
133
- setIsDesktopHeaderOpen(true);
156
+ setIsHeaderOpen(true);
134
157
  };
135
158
  const closeHeader = () => {
136
- setIsDesktopHeaderOpen(false);
159
+ setIsHeaderOpen(false);
160
+ };
161
+ const headerHasVisibleFocus = () => {
162
+ const active = document.activeElement;
163
+ return lastInteractionWasKeyboardRef.current && active instanceof HTMLElement && headerElement.contains(active);
137
164
  };
138
165
  const handleScroll = () => {
139
166
  const currentScrollY = window.pageYOffset;
140
- if (!desktopQuery.matches) {
141
- openHeader();
142
- previousScrollY = currentScrollY;
143
- return;
144
- }
145
- if (mobileMenuOpen || openTopLevelItemIndex != null) {
167
+ if (mobileMenuOpen || openTopLevelItemIndex != null || openUtilityDropdown != null || headerHasVisibleFocus()) {
146
168
  openHeader();
147
169
  previousScrollY = currentScrollY;
148
170
  return;
@@ -156,6 +178,11 @@ const MainNavigation = ({
156
178
  }
157
179
  previousScrollY = currentScrollY;
158
180
  };
181
+ const handleFocusIn = () => {
182
+ if (headerHasVisibleFocus()) {
183
+ openHeader();
184
+ }
185
+ };
159
186
  const handleViewportChange = () => {
160
187
  openHeader();
161
188
  previousScrollY = window.pageYOffset;
@@ -163,14 +190,33 @@ const MainNavigation = ({
163
190
  };
164
191
  window.addEventListener("scroll", handleScroll, { passive: true });
165
192
  window.addEventListener("resize", handleViewportChange);
193
+ document.addEventListener("focusin", handleFocusIn);
166
194
  desktopQuery.addEventListener("change", handleViewportChange);
167
195
  handleScroll();
168
196
  return () => {
169
197
  window.removeEventListener("scroll", handleScroll);
170
198
  window.removeEventListener("resize", handleViewportChange);
199
+ document.removeEventListener("focusin", handleFocusIn);
171
200
  desktopQuery.removeEventListener("change", handleViewportChange);
172
201
  };
173
- }, [mobileMenuOpen, openTopLevelItemIndex]);
202
+ }, [mobileMenuOpen, openTopLevelItemIndex, openUtilityDropdown]);
203
+ useEffect(() => {
204
+ if (typeof document === "undefined") {
205
+ return;
206
+ }
207
+ const handleKeyDown = () => {
208
+ lastInteractionWasKeyboardRef.current = true;
209
+ };
210
+ const handlePointerDown = () => {
211
+ lastInteractionWasKeyboardRef.current = false;
212
+ };
213
+ document.addEventListener("keydown", handleKeyDown, true);
214
+ document.addEventListener("pointerdown", handlePointerDown, true);
215
+ return () => {
216
+ document.removeEventListener("keydown", handleKeyDown, true);
217
+ document.removeEventListener("pointerdown", handlePointerDown, true);
218
+ };
219
+ }, []);
174
220
  useEffect(() => {
175
221
  const browserWindow = globalThis.window;
176
222
  const browserDocument = globalThis.document;
@@ -208,6 +254,11 @@ const MainNavigation = ({
208
254
  }
209
255
  const desktopQuery = window.matchMedia(desktopMinWidthMediaQuery);
210
256
  const applyViewportModeChange = ({ matches: isDesktopViewport2 }) => {
257
+ const viewportMode = isDesktopViewport2 ? "desktop" : "mobile";
258
+ if (lastAppliedViewportModeRef.current === viewportMode) {
259
+ return;
260
+ }
261
+ lastAppliedViewportModeRef.current = viewportMode;
211
262
  if (isDesktopViewport2) {
212
263
  clearTimeout(mobileSecondPanelCloseTimeoutRef.current ?? void 0);
213
264
  mobileSecondPanelCloseTimeoutRef.current = null;
@@ -215,23 +266,23 @@ const MainNavigation = ({
215
266
  mobileThirdPanelCloseTimeoutRef.current = null;
216
267
  clearTimeout(resetMobileThirdPanelScrollTimeoutRef.current ?? void 0);
217
268
  resetMobileThirdPanelScrollTimeoutRef.current = null;
218
- setMobileMenuOpen((previous) => {
219
- if (previous) {
220
- onMobileMenuToggle?.(false);
221
- }
222
- return false;
223
- });
269
+ const wasMobileMenuOpen = mobileMenuOpenRef.current;
270
+ mobileMenuOpenRef.current = false;
271
+ if (wasMobileMenuOpen) {
272
+ onMobileMenuToggle?.(false);
273
+ }
274
+ setMobileMenuOpen(false);
224
275
  setMobileActiveCategoryIndex(null);
225
276
  setIsMobileSecondPanelClosing(false);
226
277
  setIsMobileThirdPanelClosing(false);
227
278
  return;
228
279
  }
229
- setOpenTopLevelItemIndex((previous) => {
230
- if (previous !== null) {
231
- onDesktopItemToggle?.(null);
232
- }
233
- return null;
234
- });
280
+ const hadOpenDesktopItem = openTopLevelItemIndexRef.current !== null;
281
+ openTopLevelItemIndexRef.current = null;
282
+ if (hadOpenDesktopItem) {
283
+ onDesktopItemToggle?.(null);
284
+ }
285
+ setOpenTopLevelItemIndex(null);
235
286
  };
236
287
  applyViewportModeChange(desktopQuery);
237
288
  desktopQuery.addEventListener("change", applyViewportModeChange);
@@ -240,6 +291,7 @@ const MainNavigation = ({
240
291
  };
241
292
  }, [onDesktopItemToggle, onMobileMenuToggle]);
242
293
  const resetMobilePanelState = useCallback(() => {
294
+ openTopLevelItemIndexRef.current = null;
243
295
  setOpenTopLevelItemIndex(null);
244
296
  setMobileActiveCategoryIndex(null);
245
297
  setIsMobileSecondPanelClosing(false);
@@ -256,20 +308,20 @@ const MainNavigation = ({
256
308
  return;
257
309
  }
258
310
  const shouldAnimateMobileClose = mobileMenuOpen;
311
+ const wasMobileMenuOpen = mobileMenuOpenRef.current;
312
+ const openDesktopItemIndex = openTopLevelItemIndexRef.current;
313
+ mobileMenuOpenRef.current = false;
314
+ openTopLevelItemIndexRef.current = null;
315
+ if (wasMobileMenuOpen) {
316
+ onMobileMenuToggle?.(false);
317
+ }
318
+ if (openDesktopItemIndex !== null) {
319
+ onDesktopItemToggle?.(null);
320
+ }
259
321
  clearTimeout(mobileMenuCloseResetTimeoutRef.current ?? void 0);
260
322
  setIsMobileMenuClosing(shouldAnimateMobileClose);
261
- setMobileMenuOpen((previous) => {
262
- if (previous) {
263
- onMobileMenuToggle?.(false);
264
- }
265
- return false;
266
- });
267
- setOpenTopLevelItemIndex((previous) => {
268
- if (previous !== null) {
269
- onDesktopItemToggle?.(null);
270
- }
271
- return null;
272
- });
323
+ setMobileMenuOpen(false);
324
+ setOpenTopLevelItemIndex(null);
273
325
  if (shouldAnimateMobileClose) {
274
326
  mobileMenuCloseResetTimeoutRef.current = setTimeout(() => {
275
327
  resetMobilePanelState();
@@ -292,19 +344,21 @@ const MainNavigation = ({
292
344
  closeMobileMenu();
293
345
  return;
294
346
  }
347
+ closeUtilityDropdown();
348
+ mobileMenuOpenRef.current = true;
295
349
  setMobileMenuOpen(true);
296
350
  setIsMobileMenuClosing(false);
297
351
  onMobileMenuToggle?.(true);
298
352
  };
299
353
  const toggleTopLevelItem = (index) => {
300
- setOpenTopLevelItemIndex((previous) => {
301
- const next = previous === index ? null : index;
302
- setMobileActiveCategoryIndex(null);
303
- setIsMobileSecondPanelClosing(false);
304
- setIsMobileThirdPanelClosing(false);
305
- onDesktopItemToggle?.(next);
306
- return next;
307
- });
354
+ closeUtilityDropdown();
355
+ const next = openTopLevelItemIndex === index ? null : index;
356
+ openTopLevelItemIndexRef.current = next;
357
+ setOpenTopLevelItemIndex(next);
358
+ setMobileActiveCategoryIndex(null);
359
+ setIsMobileSecondPanelClosing(false);
360
+ setIsMobileThirdPanelClosing(false);
361
+ onDesktopItemToggle?.(next);
308
362
  };
309
363
  const isDesktopViewport = useCallback(() => {
310
364
  return isDesktopViewportByEnvironment(globalThis.window);
@@ -356,6 +410,23 @@ const MainNavigation = ({
356
410
  },
357
411
  [getDesktopPanelInteractiveElements, isFocusable]
358
412
  );
413
+ const getUtilityDropdownFocusLoopElements = useCallback(
414
+ (kind) => {
415
+ const focusLoopElements = /* @__PURE__ */ new Set();
416
+ const triggerButton = kind === "search" ? searchTriggerRef.current : kind === "language" ? languageTriggerRef.current : loginTriggerRef.current;
417
+ if (triggerButton != null && isFocusable(triggerButton)) {
418
+ focusLoopElements.add(triggerButton);
419
+ }
420
+ getFocusableElements(
421
+ headerElementRef.current,
422
+ `.${styles["main-navigation__dropdown"]} a[href], .${styles["main-navigation__dropdown"]} button:not([disabled]), .${styles["main-navigation__dropdown"]} input:not([disabled]), .${styles["main-navigation__dropdown"]} select:not([disabled]), .${styles["main-navigation__dropdown"]} textarea:not([disabled]), .${styles["main-navigation__dropdown"]} [tabindex]:not([tabindex="-1"])`
423
+ ).forEach((element) => {
424
+ focusLoopElements.add(element);
425
+ });
426
+ return Array.from(focusLoopElements);
427
+ },
428
+ [getFocusableElements, isFocusable]
429
+ );
359
430
  const getMobileFocusableElements = useCallback(() => {
360
431
  const focusableElements = [];
361
432
  const addFocusableElements = (elements) => {
@@ -399,6 +470,26 @@ const MainNavigation = ({
399
470
  resetMobileThirdPanelScrollTimeoutRef.current = null;
400
471
  }, 0);
401
472
  }, []);
473
+ const notifyUtilityOpenChange = useCallback(
474
+ (kind, open) => {
475
+ if (kind === "search") {
476
+ onSearchOpenChange?.(open);
477
+ } else if (kind === "language") {
478
+ onLanguageOpenChange?.(open);
479
+ } else {
480
+ onLoginOpenChange?.(open);
481
+ }
482
+ },
483
+ [onLanguageOpenChange, onLoginOpenChange, onSearchOpenChange]
484
+ );
485
+ const closeUtilityDropdown = useCallback(() => {
486
+ const openDropdown = openUtilityDropdownRef.current;
487
+ if (openDropdown != null) {
488
+ openUtilityDropdownRef.current = null;
489
+ notifyUtilityOpenChange(openDropdown, false);
490
+ }
491
+ setOpenUtilityDropdown(null);
492
+ }, [notifyUtilityOpenChange]);
402
493
  const closeMenus = useCallback(() => {
403
494
  clearTimeout(mobileSecondPanelCloseTimeoutRef.current ?? void 0);
404
495
  mobileSecondPanelCloseTimeoutRef.current = null;
@@ -414,8 +505,14 @@ const MainNavigation = ({
414
505
  focusReturnToMobileTopLevelItemTimeoutRef.current = null;
415
506
  clearTimeout(focusReturnToMobileCategoryTimeoutRef.current ?? void 0);
416
507
  focusReturnToMobileCategoryTimeoutRef.current = null;
508
+ const openDropdown = openUtilityDropdownRef.current;
509
+ if (openDropdown != null) {
510
+ openUtilityDropdownRef.current = null;
511
+ notifyUtilityOpenChange(openDropdown, false);
512
+ }
513
+ setOpenUtilityDropdown(null);
417
514
  closeMobileMenu();
418
- }, [closeMobileMenu]);
515
+ }, [closeMobileMenu, notifyUtilityOpenChange]);
419
516
  const closeMobilePanel = useCallback(
420
517
  ({
421
518
  isClosing,
@@ -464,9 +561,87 @@ const MainNavigation = ({
464
561
  const openItem = openTopLevelItemIndex != null ? items[openTopLevelItemIndex] : void 0;
465
562
  const openPanel = openItem?.panel;
466
563
  const isMobilePanelClosingOut = isMobileMenuClosing && !mobileMenuOpen;
467
- const showPageOverlay = mobileMenuOpen || openPanel != null || isMobilePanelClosingOut;
468
564
  const isOverlayClosingOut = isMobilePanelClosingOut && openPanel == null;
565
+ const showSearch = searchDropdownContent != null && typeof searchDropdownContent !== "boolean";
566
+ const showLogin = loginDropdownContent != null && typeof loginDropdownContent !== "boolean";
567
+ const showCart = cartContent != null && typeof cartContent !== "boolean";
469
568
  const cartAccessibleLabel = cartCounter != null ? `${cartLabel} ${cartCounter} ${cartCounterLabel}` : cartLabel;
569
+ const currentLanguage = languages?.find((language) => language.current) ?? languages?.[0];
570
+ const alternativeLanguages = currentLanguage != null ? (languages ?? []).filter((language) => language.code !== currentLanguage.code) : [];
571
+ const showLanguage = currentLanguage != null && alternativeLanguages.length > 0;
572
+ const languageAnnouncements = currentLanguage != null ? getLanguageToggleAnnouncements(
573
+ (languages ?? []).map((language) => language.code),
574
+ currentLanguage.code
575
+ ) : [];
576
+ const activeUtilityDropdown = openUtilityDropdown === "search" && showSearch ? "search" : openUtilityDropdown === "language" && showLanguage ? "language" : openUtilityDropdown === "login" && showLogin ? "login" : null;
577
+ const isSearchOpen = activeUtilityDropdown === "search";
578
+ const isLanguageOpen = activeUtilityDropdown === "language";
579
+ const isLoginOpen = activeUtilityDropdown === "login";
580
+ const showPageOverlay = mobileMenuOpen || openPanel != null || isMobilePanelClosingOut || activeUtilityDropdown != null;
581
+ const toggleUtilityDropdown = (kind) => {
582
+ const previous = openUtilityDropdown;
583
+ const next = previous === kind ? null : kind;
584
+ if (previous != null && previous !== next) {
585
+ notifyUtilityOpenChange(previous, false);
586
+ }
587
+ if (next != null) {
588
+ notifyUtilityOpenChange(next, true);
589
+ closeMobileMenu();
590
+ if (isCartOpen) {
591
+ if (!isCartControlled) {
592
+ internalCartOpenRef.current = false;
593
+ setInternalCartOpen(false);
594
+ }
595
+ onCartOpenChange?.(false);
596
+ }
597
+ }
598
+ openUtilityDropdownRef.current = next;
599
+ setOpenUtilityDropdown(next);
600
+ };
601
+ const handleLanguageClick = () => {
602
+ toggleUtilityDropdown("language");
603
+ };
604
+ const handleSearchClick = () => {
605
+ toggleUtilityDropdown("search");
606
+ };
607
+ const handleLoginClick = () => {
608
+ toggleUtilityDropdown("login");
609
+ };
610
+ const handleCartClick = () => {
611
+ const next = !isCartOpen;
612
+ if (next) {
613
+ closeMenus();
614
+ }
615
+ if (!isCartControlled) {
616
+ internalCartOpenRef.current = next;
617
+ setInternalCartOpen(next);
618
+ }
619
+ onCartOpenChange?.(next);
620
+ };
621
+ const handleCartOpenChange = (open) => {
622
+ if (!isCartControlled) {
623
+ internalCartOpenRef.current = open;
624
+ setInternalCartOpen(open);
625
+ }
626
+ onCartOpenChange?.(open);
627
+ };
628
+ useEffect(() => {
629
+ if (isCartOpen) {
630
+ closeMenus();
631
+ }
632
+ }, [closeMenus, isCartOpen]);
633
+ useEffect(() => {
634
+ if (openUtilityDropdown != null && activeUtilityDropdown == null) {
635
+ closeUtilityDropdown();
636
+ }
637
+ }, [activeUtilityDropdown, closeUtilityDropdown, openUtilityDropdown]);
638
+ useEffect(() => {
639
+ if (!showCart && !isCartControlled && internalCartOpen && internalCartOpenRef.current) {
640
+ internalCartOpenRef.current = false;
641
+ setInternalCartOpen(false);
642
+ onCartOpenChange?.(false);
643
+ }
644
+ }, [internalCartOpen, isCartControlled, onCartOpenChange, showCart]);
470
645
  useEffect(() => {
471
646
  if (!showPageOverlay) {
472
647
  return;
@@ -566,8 +741,7 @@ const MainNavigation = ({
566
741
  type: "button",
567
742
  className: cn(
568
743
  styles["main-navigation__mobile-back-item"],
569
- focusStyles.focusableInset,
570
- focusStyles.focusableRadiusSm
744
+ focusStyles.focusableInset
571
745
  ),
572
746
  onClick: () => closeMobilePanel({
573
747
  isClosing: isMobileSecondPanelClosing,
@@ -575,6 +749,7 @@ const MainNavigation = ({
575
749
  closeTimeoutRef: mobileSecondPanelCloseTimeoutRef,
576
750
  onClosed: () => {
577
751
  const closedTopLevelItemIndex = openTopLevelItemIndex;
752
+ openTopLevelItemIndexRef.current = null;
578
753
  setOpenTopLevelItemIndex(null);
579
754
  setMobileActiveCategoryIndex(null);
580
755
  onDesktopItemToggle?.(null);
@@ -661,8 +836,7 @@ const MainNavigation = ({
661
836
  type: "button",
662
837
  className: cn(
663
838
  styles["main-navigation__mobile-level-2-category-button"],
664
- focusStyles.focusableInset,
665
- focusStyles.focusableRadiusSm
839
+ focusStyles.focusableInset
666
840
  ),
667
841
  onClick: () => openMobileCategoryPanel(index),
668
842
  onKeyDown: (event) => {
@@ -701,8 +875,7 @@ const MainNavigation = ({
701
875
  type: "button",
702
876
  className: cn(
703
877
  styles["main-navigation__mobile-back-item"],
704
- focusStyles.focusableInset,
705
- focusStyles.focusableRadiusSm
878
+ focusStyles.focusableInset
706
879
  ),
707
880
  onClick: () => closeMobilePanel({
708
881
  isClosing: isMobileThirdPanelClosing,
@@ -745,8 +918,7 @@ const MainNavigation = ({
745
918
  link,
746
919
  className: cn(
747
920
  styles["main-navigation__mobile-level-3-link"],
748
- focusStyles.focusableInset,
749
- focusStyles.focusableRadiusSm
921
+ focusStyles.focusableInset
750
922
  ),
751
923
  children: link.label
752
924
  })
@@ -787,7 +959,6 @@ const MainNavigation = ({
787
959
  className: cn(
788
960
  styles["main-navigation__panel-link"],
789
961
  focusStyles.focusableInset,
790
- focusStyles.focusableRadiusSm,
791
962
  textDecorationStyles.underlineLinkOnHover,
792
963
  isInCurrentPage && styles["main-navigation__panel-link--current"]
793
964
  ),
@@ -825,8 +996,7 @@ const MainNavigation = ({
825
996
  className: cn(
826
997
  styles["main-navigation__feature-link"],
827
998
  textDecorationStyles.underlineLinkOnHover,
828
- focusStyles.focusableInset,
829
- focusStyles.focusableRadiusSm
999
+ focusStyles.focusableInset
830
1000
  ),
831
1001
  children: /* @__PURE__ */ jsxs(Fragment$1, { children: [
832
1002
  isExternalFeatureLink ? /* @__PURE__ */ jsx(
@@ -878,7 +1048,6 @@ const MainNavigation = ({
878
1048
  className: cn(
879
1049
  styles["main-navigation__item-toggle"],
880
1050
  focusStyles.focusableInset,
881
- focusStyles.focusableRadiusSm,
882
1051
  isCurrentPathItem && styles["main-navigation__item-toggle--current"],
883
1052
  isOpen && styles["main-navigation__item-toggle--open"]
884
1053
  ),
@@ -904,7 +1073,6 @@ const MainNavigation = ({
904
1073
  className: cn(
905
1074
  styles["main-navigation__item-link"],
906
1075
  focusStyles.focusableInset,
907
- focusStyles.focusableRadiusSm,
908
1076
  isCurrentPathItem && styles["main-navigation__item-link--current"]
909
1077
  ),
910
1078
  ariaCurrent: isCurrentPathItem ? "page" : void 0,
@@ -917,7 +1085,7 @@ const MainNavigation = ({
917
1085
  ref: setHeaderRef,
918
1086
  className: cn(
919
1087
  styles["main-navigation"],
920
- isDesktopHeaderOpen && styles["main-navigation--open"],
1088
+ isHeaderOpen && styles["main-navigation--open"],
921
1089
  mobileMenuOpen && styles["main-navigation--menu-open"],
922
1090
  isMobileMenuClosing && styles["main-navigation--menu-closing"],
923
1091
  showPageOverlay && styles["main-navigation--overlay"],
@@ -927,6 +1095,21 @@ const MainNavigation = ({
927
1095
  ),
928
1096
  ...props,
929
1097
  onKeyDown: (event) => {
1098
+ if (event.key === "Tab" && activeUtilityDropdown != null) {
1099
+ const focusLoopElements = getUtilityDropdownFocusLoopElements(activeUtilityDropdown);
1100
+ if (focusLoopElements.length > 1) {
1101
+ event.preventDefault();
1102
+ const currentIndex = focusLoopElements.indexOf(
1103
+ document.activeElement
1104
+ );
1105
+ const direction = event.shiftKey ? -1 : 1;
1106
+ const nextIndex = currentIndex === -1 ? event.shiftKey ? focusLoopElements.length - 1 : 0 : (currentIndex + direction + focusLoopElements.length) % focusLoopElements.length;
1107
+ focusLoopElements[nextIndex]?.focus();
1108
+ } else {
1109
+ closeUtilityDropdown();
1110
+ }
1111
+ return;
1112
+ }
930
1113
  if (event.key === "Tab" && mobileMenuOpen && !isDesktopViewport()) {
931
1114
  const focusableElements = getMobileFocusableElements();
932
1115
  if (focusableElements.length > 0) {
@@ -954,7 +1137,12 @@ const MainNavigation = ({
954
1137
  }
955
1138
  }
956
1139
  if (event.key === "Escape") {
1140
+ const utilityDropdownToRestore = activeUtilityDropdown;
957
1141
  closeMenus();
1142
+ if (utilityDropdownToRestore != null) {
1143
+ const triggerButton = utilityDropdownToRestore === "search" ? searchTriggerRef.current : utilityDropdownToRestore === "language" ? languageTriggerRef.current : loginTriggerRef.current;
1144
+ triggerButton?.focus();
1145
+ }
958
1146
  }
959
1147
  props.onKeyDown?.(event);
960
1148
  },
@@ -979,11 +1167,7 @@ const MainNavigation = ({
979
1167
  /* @__PURE__ */ jsxs("div", { className: styles["main-navigation__navbar"], children: [
980
1168
  renderUtilityLink({
981
1169
  href: toNavigableHref(logoHref),
982
- className: cn(
983
- styles["main-navigation__logo"],
984
- focusStyles.focusable,
985
- focusStyles.focusableRadiusSm
986
- ),
1170
+ className: cn(styles["main-navigation__logo"], focusStyles.focusable),
987
1171
  "aria-label": logoAriaLabel,
988
1172
  children: /* @__PURE__ */ jsx("img", { src: defaultLogoSrc, alt: "", "aria-hidden": "true" })
989
1173
  }),
@@ -1010,51 +1194,116 @@ const MainNavigation = ({
1010
1194
  }
1011
1195
  ),
1012
1196
  /* @__PURE__ */ jsxs("div", { className: styles["main-navigation__icon-nav"], children: [
1013
- showLanguageSelector && /* @__PURE__ */ jsxs(
1014
- "button",
1015
- {
1016
- type: "button",
1017
- className: cn(
1018
- styles["main-navigation__icon-nav-item"],
1019
- focusStyles.focusableInset,
1020
- focusStyles.focusableRadiusSm
1021
- ),
1022
- "aria-label": languageSelectorLabel,
1023
- onClick: onLanguageSelectorClick,
1024
- children: [
1025
- /* @__PURE__ */ jsx(Globe, {}),
1026
- /* @__PURE__ */ jsx("span", { className: styles["main-navigation__icon-nav-label"], children: languageSelectorLabel })
1027
- ]
1028
- }
1029
- ),
1030
- showSearch && /* @__PURE__ */ jsxs(
1031
- "button",
1032
- {
1033
- type: "button",
1034
- className: cn(
1035
- styles["main-navigation__icon-nav-item"],
1036
- focusStyles.focusableInset,
1037
- focusStyles.focusableRadiusSm
1197
+ showLanguage && currentLanguage != null && /* @__PURE__ */ jsxs("div", { className: styles["main-navigation__utility"], children: [
1198
+ /* @__PURE__ */ jsxs(
1199
+ "button",
1200
+ {
1201
+ ref: languageTriggerRef,
1202
+ type: "button",
1203
+ className: cn(
1204
+ styles["main-navigation__icon-nav-item"],
1205
+ isLanguageOpen && styles["main-navigation__icon-nav-item--active"],
1206
+ focusStyles.focusableInset
1207
+ ),
1208
+ "aria-expanded": isLanguageOpen,
1209
+ "aria-controls": isLanguageOpen ? languageDropdownId : void 0,
1210
+ onClick: handleLanguageClick,
1211
+ children: [
1212
+ /* @__PURE__ */ jsx(Globe, { "aria-hidden": "true" }),
1213
+ /* @__PURE__ */ jsx(
1214
+ "span",
1215
+ {
1216
+ "aria-hidden": "true",
1217
+ className: styles["main-navigation__icon-nav-label"],
1218
+ children: currentLanguage.code.toUpperCase()
1219
+ }
1220
+ ),
1221
+ /* @__PURE__ */ jsx("span", { className: styles["main-navigation__sr-only"], children: languageAnnouncements.map((announcement, index) => /* @__PURE__ */ jsxs(Fragment, { children: [
1222
+ index > 0 ? " " : null,
1223
+ /* @__PURE__ */ jsx("span", { lang: announcement.lang, children: announcement.text })
1224
+ ] }, announcement.lang)) })
1225
+ ]
1226
+ }
1227
+ ),
1228
+ isLanguageOpen && /* @__PURE__ */ jsxs(Fragment$1, { children: [
1229
+ /* @__PURE__ */ jsx(
1230
+ "span",
1231
+ {
1232
+ "aria-hidden": "true",
1233
+ className: styles["main-navigation__dropdown-caret"]
1234
+ }
1038
1235
  ),
1039
- "aria-label": searchLabel,
1040
- onClick: onSearchClick,
1041
- children: [
1042
- /* @__PURE__ */ jsx(Search, {}),
1043
- /* @__PURE__ */ jsx("span", { className: styles["main-navigation__icon-nav-label"], children: searchLabel })
1044
- ]
1045
- }
1046
- ),
1236
+ /* @__PURE__ */ jsx(
1237
+ "div",
1238
+ {
1239
+ id: languageDropdownId,
1240
+ className: cn(
1241
+ styles["main-navigation__dropdown"],
1242
+ styles["main-navigation__dropdown--language"],
1243
+ elevationStyles.elevationMedium
1244
+ ),
1245
+ children: /* @__PURE__ */ jsx("ul", { className: styles["main-navigation__language-list"], children: alternativeLanguages.map((language) => /* @__PURE__ */ jsx(
1246
+ "li",
1247
+ {
1248
+ className: styles["main-navigation__language-list-item"],
1249
+ children: renderLanguageLink({
1250
+ href: toNavigableHref(language.href),
1251
+ lang: language.code,
1252
+ "aria-label": language.ariaLabel ?? languageLinkAriaLabels[language.code],
1253
+ className: cn(
1254
+ styles["main-navigation__language-link"],
1255
+ focusStyles.focusable
1256
+ ),
1257
+ children: language.code.toUpperCase()
1258
+ })
1259
+ },
1260
+ language.code
1261
+ )) })
1262
+ }
1263
+ )
1264
+ ] })
1265
+ ] }),
1266
+ showSearch && /* @__PURE__ */ jsxs("div", { className: styles["main-navigation__utility"], children: [
1267
+ /* @__PURE__ */ jsxs(
1268
+ "button",
1269
+ {
1270
+ ref: searchTriggerRef,
1271
+ type: "button",
1272
+ className: cn(
1273
+ styles["main-navigation__icon-nav-item"],
1274
+ isSearchOpen && styles["main-navigation__icon-nav-item--active"],
1275
+ focusStyles.focusableInset
1276
+ ),
1277
+ "aria-label": searchLabel,
1278
+ "aria-expanded": isSearchOpen,
1279
+ "aria-controls": isSearchOpen ? searchDropdownId : void 0,
1280
+ onClick: handleSearchClick,
1281
+ children: [
1282
+ /* @__PURE__ */ jsx(Search, {}),
1283
+ /* @__PURE__ */ jsx("span", { className: styles["main-navigation__icon-nav-label"], children: searchLabel })
1284
+ ]
1285
+ }
1286
+ ),
1287
+ isSearchOpen && /* @__PURE__ */ jsx(
1288
+ "span",
1289
+ {
1290
+ "aria-hidden": "true",
1291
+ className: styles["main-navigation__dropdown-caret"]
1292
+ }
1293
+ )
1294
+ ] }),
1047
1295
  showCart && /* @__PURE__ */ jsxs(
1048
1296
  "button",
1049
1297
  {
1050
1298
  type: "button",
1051
1299
  className: cn(
1052
1300
  styles["main-navigation__icon-nav-item"],
1053
- focusStyles.focusableInset,
1054
- focusStyles.focusableRadiusSm
1301
+ isCartOpen && styles["main-navigation__icon-nav-item--active"],
1302
+ focusStyles.focusableInset
1055
1303
  ),
1056
1304
  "aria-label": cartAccessibleLabel,
1057
- onClick: onCartClick,
1305
+ "aria-expanded": isCartOpen,
1306
+ onClick: handleCartClick,
1058
1307
  children: [
1059
1308
  /* @__PURE__ */ jsx(Cart, {}),
1060
1309
  /* @__PURE__ */ jsx("span", { className: styles["main-navigation__icon-nav-label"], children: cartLabel }),
@@ -1069,16 +1318,53 @@ const MainNavigation = ({
1069
1318
  ]
1070
1319
  }
1071
1320
  ),
1072
- /* @__PURE__ */ jsx(
1073
- Button,
1074
- {
1075
- href: toNavigableHref(loginHref),
1076
- size: "small",
1077
- renderLink: renderUtilityLink,
1078
- children: loginLabel
1079
- }
1080
- )
1321
+ showLogin && /* @__PURE__ */ jsxs("div", { className: styles["main-navigation__utility"], children: [
1322
+ /* @__PURE__ */ jsx(
1323
+ Button,
1324
+ {
1325
+ ref: loginTriggerRef,
1326
+ size: "small",
1327
+ "aria-expanded": isLoginOpen,
1328
+ "aria-controls": isLoginOpen ? loginDropdownId : void 0,
1329
+ onClick: handleLoginClick,
1330
+ children: loginLabel
1331
+ }
1332
+ ),
1333
+ isLoginOpen && /* @__PURE__ */ jsxs(Fragment$1, { children: [
1334
+ /* @__PURE__ */ jsx(
1335
+ "span",
1336
+ {
1337
+ "aria-hidden": "true",
1338
+ className: styles["main-navigation__dropdown-caret"]
1339
+ }
1340
+ ),
1341
+ /* @__PURE__ */ jsx(
1342
+ "div",
1343
+ {
1344
+ id: loginDropdownId,
1345
+ className: cn(
1346
+ styles["main-navigation__dropdown"],
1347
+ styles["main-navigation__dropdown--login"],
1348
+ elevationStyles.elevationMedium
1349
+ ),
1350
+ children: loginDropdownContent
1351
+ }
1352
+ )
1353
+ ] })
1354
+ ] })
1081
1355
  ] }),
1356
+ showSearch && isSearchOpen && /* @__PURE__ */ jsx(
1357
+ "div",
1358
+ {
1359
+ id: searchDropdownId,
1360
+ className: cn(
1361
+ styles["main-navigation__dropdown"],
1362
+ styles["main-navigation__dropdown--search"],
1363
+ elevationStyles.elevationMedium
1364
+ ),
1365
+ children: searchDropdownContent
1366
+ }
1367
+ ),
1082
1368
  /* @__PURE__ */ jsx(
1083
1369
  "button",
1084
1370
  {
@@ -1087,8 +1373,7 @@ const MainNavigation = ({
1087
1373
  className: cn(
1088
1374
  styles["main-navigation__menu-toggle"],
1089
1375
  mobileMenuOpen && styles["main-navigation__menu-toggle--open"],
1090
- focusStyles.focusableInset,
1091
- focusStyles.focusableRadiusSm
1376
+ focusStyles.focusableInset
1092
1377
  ),
1093
1378
  "aria-label": mobileMenuOpen ? mobileMenuCloseAriaLabel : mobileMenuOpenAriaLabel,
1094
1379
  "aria-expanded": mobileMenuOpen,
@@ -1099,6 +1384,16 @@ const MainNavigation = ({
1099
1384
  ] }),
1100
1385
  !mobileMenuOpen && renderPanel(
1101
1386
  cn(styles["main-navigation__panel"], styles["main-navigation__panel--desktop"])
1387
+ ),
1388
+ showCart && /* @__PURE__ */ jsx(
1389
+ Drawer,
1390
+ {
1391
+ open: isCartOpen,
1392
+ onOpenChange: handleCartOpenChange,
1393
+ title: cartLabel,
1394
+ size: "small",
1395
+ children: cartContent
1396
+ }
1102
1397
  )
1103
1398
  ]
1104
1399
  }