rizzo-css 0.0.17 → 0.0.19

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 (261) hide show
  1. package/README.md +4 -4
  2. package/bin/rizzo-css.js +329 -118
  3. package/dist/rizzo.min.css +3 -3
  4. package/package.json +7 -3
  5. package/scaffold/astro-minimal/.env.example +3 -0
  6. package/scaffold/astro-minimal/README.md +36 -0
  7. package/scaffold/astro-minimal/package.json +13 -0
  8. package/scaffold/astro-minimal/src/layouts/Layout.astro +28 -0
  9. package/scaffold/astro-minimal/src/pages/index.astro +10 -0
  10. package/scaffold/svelte-minimal/.env.example +3 -0
  11. package/scaffold/svelte-minimal/README.md +37 -0
  12. package/scaffold/svelte-minimal/package.json +20 -0
  13. package/scaffold/svelte-minimal/src/app.d.ts +11 -0
  14. package/scaffold/svelte-minimal/src/app.html +15 -0
  15. package/scaffold/svelte-minimal/src/routes/+layout.svelte +1 -0
  16. package/scaffold/svelte-minimal/src/routes/+page.svelte +5 -0
  17. package/scaffold/svelte-minimal/svelte.config.js +10 -0
  18. package/scaffold/svelte-minimal/tsconfig.json +11 -0
  19. package/scaffold/vanilla/README.md +4 -4
  20. package/scaffold/vanilla/components/accordion.html +18 -0
  21. package/scaffold/vanilla/components/alert.html +18 -0
  22. package/scaffold/vanilla/components/avatar.html +18 -0
  23. package/scaffold/vanilla/components/badge.html +18 -0
  24. package/scaffold/vanilla/components/breadcrumb.html +18 -0
  25. package/scaffold/vanilla/components/button.html +18 -0
  26. package/scaffold/vanilla/components/cards.html +18 -0
  27. package/scaffold/vanilla/components/copy-to-clipboard.html +18 -0
  28. package/scaffold/vanilla/components/divider.html +18 -0
  29. package/scaffold/vanilla/components/dropdown.html +18 -0
  30. package/scaffold/vanilla/components/forms.html +18 -0
  31. package/scaffold/vanilla/components/icons.html +18 -0
  32. package/scaffold/vanilla/components/index.html +18 -0
  33. package/scaffold/vanilla/components/modal.html +18 -0
  34. package/scaffold/vanilla/components/navbar.html +18 -0
  35. package/scaffold/vanilla/components/pagination.html +18 -0
  36. package/scaffold/vanilla/components/progress-bar.html +18 -0
  37. package/scaffold/vanilla/components/search.html +18 -0
  38. package/scaffold/vanilla/components/settings.html +18 -0
  39. package/scaffold/vanilla/components/spinner.html +18 -0
  40. package/scaffold/vanilla/components/table.html +18 -0
  41. package/scaffold/vanilla/components/tabs.html +18 -0
  42. package/scaffold/vanilla/components/theme-switcher.html +18 -0
  43. package/scaffold/vanilla/components/toast.html +18 -0
  44. package/scaffold/vanilla/components/tooltip.html +18 -0
  45. package/scaffold/vanilla/index.html +18 -0
  46. package/scaffold/astro-app/README.md +0 -43
  47. package/scaffold/astro-app/package.json +0 -1
  48. package/scaffold/astro-app/src/components/Accordion.astro +0 -178
  49. package/scaffold/astro-app/src/components/Alert.astro +0 -131
  50. package/scaffold/astro-app/src/components/Avatar.astro +0 -59
  51. package/scaffold/astro-app/src/components/Badge.astro +0 -24
  52. package/scaffold/astro-app/src/components/Breadcrumb.astro +0 -61
  53. package/scaffold/astro-app/src/components/Button.astro +0 -3
  54. package/scaffold/astro-app/src/components/Card.astro +0 -18
  55. package/scaffold/astro-app/src/components/Checkbox.astro +0 -38
  56. package/scaffold/astro-app/src/components/CliCommandTabs.astro +0 -90
  57. package/scaffold/astro-app/src/components/CodeBlock.astro +0 -393
  58. package/scaffold/astro-app/src/components/CopyToClipboard.astro +0 -219
  59. package/scaffold/astro-app/src/components/Divider.astro +0 -37
  60. package/scaffold/astro-app/src/components/DocsSidebar.astro +0 -51
  61. package/scaffold/astro-app/src/components/Dropdown.astro +0 -807
  62. package/scaffold/astro-app/src/components/FormGroup.astro +0 -59
  63. package/scaffold/astro-app/src/components/FrameworkSwitcher.astro +0 -72
  64. package/scaffold/astro-app/src/components/Input.astro +0 -59
  65. package/scaffold/astro-app/src/components/Modal.astro +0 -212
  66. package/scaffold/astro-app/src/components/Navbar.astro +0 -623
  67. package/scaffold/astro-app/src/components/PackageInstallTabs.astro +0 -87
  68. package/scaffold/astro-app/src/components/Pagination.astro +0 -240
  69. package/scaffold/astro-app/src/components/ProgressBar.astro +0 -65
  70. package/scaffold/astro-app/src/components/Radio.astro +0 -38
  71. package/scaffold/astro-app/src/components/Search.astro +0 -1259
  72. package/scaffold/astro-app/src/components/Select.astro +0 -49
  73. package/scaffold/astro-app/src/components/Settings.astro +0 -382
  74. package/scaffold/astro-app/src/components/Spinner.astro +0 -30
  75. package/scaffold/astro-app/src/components/Table.astro +0 -181
  76. package/scaffold/astro-app/src/components/Tabs.astro +0 -223
  77. package/scaffold/astro-app/src/components/Textarea.astro +0 -58
  78. package/scaffold/astro-app/src/components/ThemeIcon.astro +0 -50
  79. package/scaffold/astro-app/src/components/ThemeSwitcher.astro +0 -504
  80. package/scaffold/astro-app/src/components/Toast.astro +0 -30
  81. package/scaffold/astro-app/src/components/Tooltip.astro +0 -32
  82. package/scaffold/astro-app/src/components/icons/Brush.astro +0 -10
  83. package/scaffold/astro-app/src/components/icons/Cake.astro +0 -11
  84. package/scaffold/astro-app/src/components/icons/Check.astro +0 -29
  85. package/scaffold/astro-app/src/components/icons/Cherry.astro +0 -11
  86. package/scaffold/astro-app/src/components/icons/ChevronDown.astro +0 -29
  87. package/scaffold/astro-app/src/components/icons/Circle.astro +0 -29
  88. package/scaffold/astro-app/src/components/icons/Close.astro +0 -30
  89. package/scaffold/astro-app/src/components/icons/Cmd.astro +0 -26
  90. package/scaffold/astro-app/src/components/icons/Copy.astro +0 -30
  91. package/scaffold/astro-app/src/components/icons/Eye.astro +0 -30
  92. package/scaffold/astro-app/src/components/icons/Filter.astro +0 -29
  93. package/scaffold/astro-app/src/components/icons/Flame.astro +0 -28
  94. package/scaffold/astro-app/src/components/icons/Flower.astro +0 -11
  95. package/scaffold/astro-app/src/components/icons/Gear.astro +0 -30
  96. package/scaffold/astro-app/src/components/icons/Heart.astro +0 -28
  97. package/scaffold/astro-app/src/components/icons/IceCream.astro +0 -31
  98. package/scaffold/astro-app/src/components/icons/Leaf.astro +0 -29
  99. package/scaffold/astro-app/src/components/icons/Lemon.astro +0 -11
  100. package/scaffold/astro-app/src/components/icons/Moon.astro +0 -29
  101. package/scaffold/astro-app/src/components/icons/Owl.astro +0 -34
  102. package/scaffold/astro-app/src/components/icons/Palette.astro +0 -33
  103. package/scaffold/astro-app/src/components/icons/Rainbow.astro +0 -31
  104. package/scaffold/astro-app/src/components/icons/Search.astro +0 -30
  105. package/scaffold/astro-app/src/components/icons/Shield.astro +0 -28
  106. package/scaffold/astro-app/src/components/icons/Snowflake.astro +0 -34
  107. package/scaffold/astro-app/src/components/icons/Sort.astro +0 -30
  108. package/scaffold/astro-app/src/components/icons/Sun.astro +0 -29
  109. package/scaffold/astro-app/src/components/icons/Sunset.astro +0 -10
  110. package/scaffold/astro-app/src/components/icons/Zap.astro +0 -9
  111. package/scaffold/astro-app/src/components/icons/devicons/Astro.astro +0 -53
  112. package/scaffold/astro-app/src/components/icons/devicons/Bash.astro +0 -34
  113. package/scaffold/astro-app/src/components/icons/devicons/Css3.astro +0 -29
  114. package/scaffold/astro-app/src/components/icons/devicons/Git.astro +0 -24
  115. package/scaffold/astro-app/src/components/icons/devicons/Html5.astro +0 -27
  116. package/scaffold/astro-app/src/components/icons/devicons/Javascript.astro +0 -25
  117. package/scaffold/astro-app/src/components/icons/devicons/Nodejs.astro +0 -47
  118. package/scaffold/astro-app/src/components/icons/devicons/Plaintext.astro +0 -33
  119. package/scaffold/astro-app/src/components/icons/devicons/React.astro +0 -27
  120. package/scaffold/astro-app/src/components/icons/devicons/Svelte.astro +0 -25
  121. package/scaffold/astro-app/src/components/icons/devicons/Vue.astro +0 -26
  122. package/scaffold/astro-app/src/config/frameworks.ts +0 -26
  123. package/scaffold/astro-app/src/config/themes.ts +0 -54
  124. package/scaffold/astro-app/src/layouts/DocsLayout.astro +0 -263
  125. package/scaffold/astro-app/src/layouts/Layout.astro +0 -41
  126. package/scaffold/astro-app/src/pages/components/accordion.astro +0 -172
  127. package/scaffold/astro-app/src/pages/components/alert.astro +0 -250
  128. package/scaffold/astro-app/src/pages/components/avatar.astro +0 -102
  129. package/scaffold/astro-app/src/pages/components/badge.astro +0 -119
  130. package/scaffold/astro-app/src/pages/components/breadcrumb.astro +0 -124
  131. package/scaffold/astro-app/src/pages/components/button.astro +0 -74
  132. package/scaffold/astro-app/src/pages/components/cards.astro +0 -247
  133. package/scaffold/astro-app/src/pages/components/copy-to-clipboard.astro +0 -49
  134. package/scaffold/astro-app/src/pages/components/divider.astro +0 -74
  135. package/scaffold/astro-app/src/pages/components/dropdown.astro +0 -394
  136. package/scaffold/astro-app/src/pages/components/forms.astro +0 -367
  137. package/scaffold/astro-app/src/pages/components/icons.astro +0 -246
  138. package/scaffold/astro-app/src/pages/components/modal.astro +0 -152
  139. package/scaffold/astro-app/src/pages/components/navbar.astro +0 -80
  140. package/scaffold/astro-app/src/pages/components/pagination.astro +0 -126
  141. package/scaffold/astro-app/src/pages/components/progress-bar.astro +0 -94
  142. package/scaffold/astro-app/src/pages/components/search.astro +0 -155
  143. package/scaffold/astro-app/src/pages/components/settings.astro +0 -78
  144. package/scaffold/astro-app/src/pages/components/spinner.astro +0 -81
  145. package/scaffold/astro-app/src/pages/components/table.astro +0 -144
  146. package/scaffold/astro-app/src/pages/components/tabs.astro +0 -220
  147. package/scaffold/astro-app/src/pages/components/theme-switcher.astro +0 -69
  148. package/scaffold/astro-app/src/pages/components/toast.astro +0 -157
  149. package/scaffold/astro-app/src/pages/components/tooltip.astro +0 -209
  150. package/scaffold/astro-app/src/pages/components.astro +0 -290
  151. package/scaffold/astro-app/src/pages/docs/accessibility.astro +0 -9
  152. package/scaffold/astro-app/src/pages/docs/colors.astro +0 -9
  153. package/scaffold/astro-app/src/pages/docs/design-system.astro +0 -9
  154. package/scaffold/astro-app/src/pages/docs/getting-started.astro +0 -9
  155. package/scaffold/astro-app/src/pages/docs/index.astro +0 -15
  156. package/scaffold/astro-app/src/pages/docs/themes/[theme].astro +0 -14
  157. package/scaffold/astro-app/src/pages/docs/theming.astro +0 -10
  158. package/scaffold/astro-app/src/pages/index.astro +0 -24
  159. package/scaffold/svelte-app/README.md +0 -39
  160. package/scaffold/svelte-app/package.json +0 -22
  161. package/scaffold/svelte-app/src/app.d.ts +0 -28
  162. package/scaffold/svelte-app/src/app.html +0 -21
  163. package/scaffold/svelte-app/src/lib/assets/favicon.svg +0 -1
  164. package/scaffold/svelte-app/src/lib/rizzo/Accordion.svelte +0 -128
  165. package/scaffold/svelte-app/src/lib/rizzo/Alert.svelte +0 -85
  166. package/scaffold/svelte-app/src/lib/rizzo/Avatar.svelte +0 -39
  167. package/scaffold/svelte-app/src/lib/rizzo/Badge.svelte +0 -31
  168. package/scaffold/svelte-app/src/lib/rizzo/Breadcrumb.svelte +0 -49
  169. package/scaffold/svelte-app/src/lib/rizzo/Button.svelte +0 -27
  170. package/scaffold/svelte-app/src/lib/rizzo/Card.svelte +0 -17
  171. package/scaffold/svelte-app/src/lib/rizzo/Checkbox.svelte +0 -37
  172. package/scaffold/svelte-app/src/lib/rizzo/CopyToClipboard.svelte +0 -79
  173. package/scaffold/svelte-app/src/lib/rizzo/Divider.svelte +0 -28
  174. package/scaffold/svelte-app/src/lib/rizzo/Dropdown.svelte +0 -254
  175. package/scaffold/svelte-app/src/lib/rizzo/FormGroup.svelte +0 -51
  176. package/scaffold/svelte-app/src/lib/rizzo/Input.svelte +0 -59
  177. package/scaffold/svelte-app/src/lib/rizzo/Modal.svelte +0 -157
  178. package/scaffold/svelte-app/src/lib/rizzo/Pagination.svelte +0 -93
  179. package/scaffold/svelte-app/src/lib/rizzo/ProgressBar.svelte +0 -58
  180. package/scaffold/svelte-app/src/lib/rizzo/Radio.svelte +0 -38
  181. package/scaffold/svelte-app/src/lib/rizzo/Select.svelte +0 -51
  182. package/scaffold/svelte-app/src/lib/rizzo/Spinner.svelte +0 -14
  183. package/scaffold/svelte-app/src/lib/rizzo/Table.svelte +0 -158
  184. package/scaffold/svelte-app/src/lib/rizzo/Tabs.svelte +0 -117
  185. package/scaffold/svelte-app/src/lib/rizzo/Textarea.svelte +0 -59
  186. package/scaffold/svelte-app/src/lib/rizzo/ThemeIcon.svelte +0 -54
  187. package/scaffold/svelte-app/src/lib/rizzo/ThemeSwitcher.svelte +0 -315
  188. package/scaffold/svelte-app/src/lib/rizzo/Toast.svelte +0 -33
  189. package/scaffold/svelte-app/src/lib/rizzo/Tooltip.svelte +0 -19
  190. package/scaffold/svelte-app/src/lib/rizzo/icons/Check.svelte +0 -29
  191. package/scaffold/svelte-app/src/lib/rizzo/icons/ChevronDown.svelte +0 -29
  192. package/scaffold/svelte-app/src/lib/rizzo/icons/Circle.svelte +0 -29
  193. package/scaffold/svelte-app/src/lib/rizzo/icons/Close.svelte +0 -30
  194. package/scaffold/svelte-app/src/lib/rizzo/icons/Cmd.svelte +0 -27
  195. package/scaffold/svelte-app/src/lib/rizzo/icons/Copy.svelte +0 -30
  196. package/scaffold/svelte-app/src/lib/rizzo/icons/Eye.svelte +0 -30
  197. package/scaffold/svelte-app/src/lib/rizzo/icons/Filter.svelte +0 -29
  198. package/scaffold/svelte-app/src/lib/rizzo/icons/Gear.svelte +0 -30
  199. package/scaffold/svelte-app/src/lib/rizzo/icons/IceCream.svelte +0 -31
  200. package/scaffold/svelte-app/src/lib/rizzo/icons/Moon.svelte +0 -29
  201. package/scaffold/svelte-app/src/lib/rizzo/icons/Owl.svelte +0 -34
  202. package/scaffold/svelte-app/src/lib/rizzo/icons/Palette.svelte +0 -33
  203. package/scaffold/svelte-app/src/lib/rizzo/icons/Rainbow.svelte +0 -31
  204. package/scaffold/svelte-app/src/lib/rizzo/icons/Search.svelte +0 -30
  205. package/scaffold/svelte-app/src/lib/rizzo/icons/Snowflake.svelte +0 -34
  206. package/scaffold/svelte-app/src/lib/rizzo/icons/Sort.svelte +0 -30
  207. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Astro.svelte +0 -45
  208. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Bash.svelte +0 -28
  209. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Css3.svelte +0 -23
  210. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Git.svelte +0 -18
  211. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Html5.svelte +0 -21
  212. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Javascript.svelte +0 -19
  213. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Nodejs.svelte +0 -44
  214. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Plaintext.svelte +0 -24
  215. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/React.svelte +0 -21
  216. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/SvelteIcon.svelte +0 -19
  217. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Vue.svelte +0 -20
  218. package/scaffold/svelte-app/src/lib/rizzo/index.ts +0 -35
  219. package/scaffold/svelte-app/src/lib/rizzo-docs/CodeBlock.svelte +0 -239
  220. package/scaffold/svelte-app/src/lib/rizzo-docs/SvelteDocPage.svelte +0 -99
  221. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/AccordionDoc.svelte +0 -53
  222. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/AlertDoc.svelte +0 -114
  223. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/AvatarDoc.svelte +0 -92
  224. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/BadgeDoc.svelte +0 -60
  225. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/BreadcrumbDoc.svelte +0 -55
  226. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ButtonDoc.svelte +0 -55
  227. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/CardsDoc.svelte +0 -173
  228. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ComingSoon.svelte +0 -12
  229. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ComponentsOverview.svelte +0 -92
  230. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/CopyToClipboardDoc.svelte +0 -26
  231. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/DividerDoc.svelte +0 -105
  232. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/DropdownDoc.svelte +0 -161
  233. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/FormsDoc.svelte +0 -375
  234. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/IconsDoc.svelte +0 -246
  235. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/Index.svelte +0 -8
  236. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ModalDoc.svelte +0 -50
  237. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/NavbarDoc.svelte +0 -79
  238. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/PaginationDoc.svelte +0 -44
  239. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ProgressBarDoc.svelte +0 -95
  240. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/SearchDoc.svelte +0 -147
  241. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/SettingsDoc.svelte +0 -158
  242. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/SpinnerDoc.svelte +0 -41
  243. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/TableDoc.svelte +0 -116
  244. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/TabsDoc.svelte +0 -152
  245. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ThemeSwitcherDoc.svelte +0 -189
  246. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/Theming.svelte +0 -6
  247. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ToastDoc.svelte +0 -136
  248. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/TooltipDoc.svelte +0 -57
  249. package/scaffold/svelte-app/src/routes/+layout.svelte +0 -10
  250. package/scaffold/svelte-app/src/routes/+page.svelte +0 -31
  251. package/scaffold/svelte-app/src/routes/components/+page.svelte +0 -4
  252. package/scaffold/svelte-app/src/routes/components/[slug]/+page.svelte +0 -7
  253. package/scaffold/svelte-app/static/robots.txt +0 -3
  254. package/scaffold/svelte-app/svelte.config.js +0 -13
  255. package/scaffold/svelte-app/tsconfig.json +0 -21
  256. package/scaffold/svelte-app/vite.config.ts +0 -6
  257. /package/scaffold/{astro-app → astro-minimal}/astro.config.mjs +0 -0
  258. /package/scaffold/{astro-app → astro-minimal}/public/.gitkeep +0 -0
  259. /package/scaffold/{astro-app → astro-minimal}/public/favicon.svg +0 -0
  260. /package/scaffold/{astro-app → astro-minimal}/tsconfig.json +0 -0
  261. /package/scaffold/{svelte-app → svelte-minimal}/static/.gitkeep +0 -0
@@ -1,807 +0,0 @@
1
- ---
2
- import ChevronDown from './icons/ChevronDown.astro';
3
-
4
- interface MenuItem {
5
- label: string;
6
- value?: string;
7
- href?: string;
8
- onClick?: string;
9
- disabled?: boolean;
10
- separator?: boolean;
11
- submenu?: MenuItem[];
12
- }
13
-
14
- interface Props {
15
- trigger: string;
16
- items: MenuItem[];
17
- id?: string;
18
- class?: string;
19
- position?: 'left' | 'right';
20
- align?: 'start' | 'end';
21
- }
22
-
23
- const {
24
- trigger,
25
- items,
26
- id,
27
- class: className = '',
28
- position = 'left',
29
- align = 'start',
30
- } = Astro.props;
31
-
32
- const dropdownId = id || `dropdown-${Math.random().toString(36).substr(2, 9)}`;
33
- const triggerId = `${dropdownId}-trigger`;
34
- const menuId = `${dropdownId}-menu`;
35
- ---
36
-
37
- <div class={`dropdown ${className}`.trim()} data-dropdown={dropdownId}>
38
- <button
39
- type="button"
40
- class="dropdown__trigger"
41
- id={triggerId}
42
- aria-expanded="false"
43
- aria-haspopup="true"
44
- aria-controls={menuId}
45
- aria-label={trigger}
46
- >
47
- <span class="dropdown__trigger-text">{trigger}</span>
48
- <ChevronDown class="dropdown__icon" width={16} height={16} />
49
- </button>
50
-
51
- <div
52
- class={`dropdown__menu dropdown__menu--${position} dropdown__menu--${align}`}
53
- id={menuId}
54
- role="menu"
55
- aria-labelledby={triggerId}
56
- aria-label={`${trigger} menu`}
57
- aria-orientation="vertical"
58
- aria-hidden="true"
59
- tabindex="-1"
60
- >
61
- {items.map((item, index) => {
62
- if (item.separator) {
63
- return <div class="dropdown__separator" role="separator" />;
64
- }
65
-
66
- const itemId = `${dropdownId}-item-${index}`;
67
- const hasSubmenu = item.submenu && item.submenu.length > 0;
68
- const submenuId = hasSubmenu ? `${dropdownId}-submenu-${index}` : undefined;
69
-
70
- if (item.href) {
71
- return (
72
- <div class={`dropdown__item-wrapper ${hasSubmenu ? 'dropdown__item-wrapper--has-submenu' : ''}`}>
73
- {hasSubmenu ? (
74
- <div
75
- class={`dropdown__item ${item.disabled ? 'dropdown__item--disabled' : ''} dropdown__item--has-submenu`}
76
- role="menuitem"
77
- id={itemId}
78
- tabindex="-1"
79
- aria-label={item.label}
80
- aria-disabled={item.disabled ? 'true' : 'false'}
81
- aria-expanded="false"
82
- aria-haspopup="true"
83
- aria-controls={submenuId}
84
- data-dropdown-has-submenu="true"
85
- >
86
- <span>{item.label}</span>
87
- <ChevronDown class="dropdown__item-arrow" width={12} height={12} />
88
- </div>
89
- ) : (
90
- <div
91
- class={`dropdown__item ${item.disabled ? 'dropdown__item--disabled' : ''}`}
92
- role="menuitem"
93
- id={itemId}
94
- tabindex="-1"
95
- aria-label={item.label}
96
- aria-disabled={item.disabled ? 'true' : 'false'}
97
- data-dropdown-href={item.href}
98
- >
99
- <span>{item.label}</span>
100
- </div>
101
- )}
102
- {hasSubmenu && item.submenu && (
103
- <div
104
- class="dropdown__submenu"
105
- id={submenuId}
106
- role="menu"
107
- aria-label={`${item.label} submenu`}
108
- aria-hidden="true"
109
- >
110
- {item.submenu.map((subItem, subIndex) => {
111
- if (subItem.separator) {
112
- return <div class="dropdown__separator" role="separator" />;
113
- }
114
-
115
- const subItemId = `${submenuId}-item-${subIndex}`;
116
- const hasNestedSubmenu = subItem.submenu && subItem.submenu.length > 0;
117
- const nestedSubmenuId = hasNestedSubmenu ? `${subItemId}-submenu` : undefined;
118
-
119
- if (subItem.href) {
120
- return (
121
- <div class={`dropdown__item-wrapper ${hasNestedSubmenu ? 'dropdown__item-wrapper--has-submenu' : ''}`}>
122
- {hasNestedSubmenu ? (
123
- <div
124
- class={`dropdown__item dropdown__submenu-item ${subItem.disabled ? 'dropdown__item--disabled' : ''} dropdown__item--has-submenu`}
125
- role="menuitem"
126
- id={subItemId}
127
- tabindex="-1"
128
- aria-label={subItem.label}
129
- aria-disabled={subItem.disabled ? 'true' : 'false'}
130
- aria-expanded="false"
131
- aria-haspopup="true"
132
- aria-controls={nestedSubmenuId}
133
- data-dropdown-has-submenu="true"
134
- >
135
- <span>{subItem.label}</span>
136
- <ChevronDown class="dropdown__item-arrow" width={12} height={12} />
137
- </div>
138
- ) : (
139
- <div
140
- class={`dropdown__item dropdown__submenu-item ${subItem.disabled ? 'dropdown__item--disabled' : ''}`}
141
- role="menuitem"
142
- id={subItemId}
143
- tabindex="-1"
144
- aria-label={subItem.label}
145
- aria-disabled={subItem.disabled ? 'true' : 'false'}
146
- data-dropdown-href={subItem.href}
147
- >
148
- <span>{subItem.label}</span>
149
- </div>
150
- )}
151
- {hasNestedSubmenu && subItem.submenu && (
152
- <div
153
- class="dropdown__submenu"
154
- id={nestedSubmenuId}
155
- role="menu"
156
- aria-label={`${subItem.label} submenu`}
157
- aria-hidden="true"
158
- >
159
- {subItem.submenu.map((nestedItem, nestedIndex) => {
160
- if (nestedItem.separator) {
161
- return <div class="dropdown__separator" role="separator" />;
162
- }
163
-
164
- const nestedItemId = `${nestedSubmenuId}-item-${nestedIndex}`;
165
-
166
- if (nestedItem.href) {
167
- return (
168
- <div
169
- class={`dropdown__item dropdown__submenu-item ${nestedItem.disabled ? 'dropdown__item--disabled' : ''}`}
170
- role="menuitem"
171
- id={nestedItemId}
172
- tabindex="-1"
173
- aria-disabled={nestedItem.disabled ? 'true' : 'false'}
174
- data-dropdown-href={nestedItem.href}
175
- >
176
- <span>{nestedItem.label}</span>
177
- </div>
178
- );
179
- }
180
-
181
- return (
182
- <div
183
- class={`dropdown__item dropdown__submenu-item ${nestedItem.disabled ? 'dropdown__item--disabled' : ''}`}
184
- role="menuitem"
185
- id={nestedItemId}
186
- tabindex="-1"
187
- aria-label={nestedItem.label}
188
- aria-disabled={nestedItem.disabled ? 'true' : 'false'}
189
- data-dropdown-value={nestedItem.value || nestedItem.label}
190
- data-dropdown-onclick={nestedItem.onClick || ''}
191
- >
192
- <span>{nestedItem.label}</span>
193
- </div>
194
- );
195
- })}
196
- </div>
197
- )}
198
- </div>
199
- );
200
- }
201
-
202
- return (
203
- <div class={`dropdown__item-wrapper ${hasNestedSubmenu ? 'dropdown__item-wrapper--has-submenu' : ''}`}>
204
- <div
205
- class={`dropdown__item dropdown__submenu-item ${subItem.disabled ? 'dropdown__item--disabled' : ''} ${hasNestedSubmenu ? 'dropdown__item--has-submenu' : ''}`}
206
- role="menuitem"
207
- id={subItemId}
208
- tabindex="-1"
209
- aria-label={subItem.label}
210
- aria-disabled={subItem.disabled ? 'true' : 'false'}
211
- aria-expanded={hasNestedSubmenu ? 'false' : undefined}
212
- aria-haspopup={hasNestedSubmenu ? 'true' : undefined}
213
- aria-controls={nestedSubmenuId}
214
- data-dropdown-value={subItem.value || subItem.label}
215
- data-dropdown-onclick={subItem.onClick || ''}
216
- data-dropdown-has-submenu={hasNestedSubmenu ? 'true' : undefined}
217
- >
218
- <span>{subItem.label}</span>
219
- {hasNestedSubmenu && <ChevronDown class="dropdown__item-arrow" width={12} height={12} />}
220
- </div>
221
- {hasNestedSubmenu && subItem.submenu && (
222
- <div
223
- class="dropdown__submenu"
224
- id={nestedSubmenuId}
225
- role="menu"
226
- aria-label={`${subItem.label} submenu`}
227
- aria-hidden="true"
228
- >
229
- {subItem.submenu.map((nestedItem, nestedIndex) => {
230
- if (nestedItem.separator) {
231
- return <div class="dropdown__separator" role="separator" />;
232
- }
233
-
234
- const nestedItemId = `${nestedSubmenuId}-item-${nestedIndex}`;
235
-
236
- if (nestedItem.href) {
237
- return (
238
- <div
239
- class={`dropdown__item dropdown__submenu-item ${nestedItem.disabled ? 'dropdown__item--disabled' : ''}`}
240
- role="menuitem"
241
- id={nestedItemId}
242
- tabindex="-1"
243
- aria-label={nestedItem.label}
244
- aria-disabled={nestedItem.disabled ? 'true' : 'false'}
245
- data-dropdown-href={nestedItem.href}
246
- >
247
- <span>{nestedItem.label}</span>
248
- </div>
249
- );
250
- }
251
-
252
- return (
253
- <div
254
- class={`dropdown__item dropdown__submenu-item ${nestedItem.disabled ? 'dropdown__item--disabled' : ''}`}
255
- role="menuitem"
256
- id={nestedItemId}
257
- tabindex="-1"
258
- aria-disabled={nestedItem.disabled ? 'true' : 'false'}
259
- data-dropdown-value={nestedItem.value || nestedItem.label}
260
- data-dropdown-onclick={nestedItem.onClick || ''}
261
- >
262
- <span>{nestedItem.label}</span>
263
- </div>
264
- );
265
- })}
266
- </div>
267
- )}
268
- </div>
269
- );
270
- })}
271
- </div>
272
- )}
273
- </div>
274
- );
275
- }
276
-
277
- return (
278
- <div class={`dropdown__item-wrapper ${hasSubmenu ? 'dropdown__item-wrapper--has-submenu' : ''}`}>
279
- <div
280
- class={`dropdown__item ${item.disabled ? 'dropdown__item--disabled' : ''} ${hasSubmenu ? 'dropdown__item--has-submenu' : ''}`}
281
- role="menuitem"
282
- id={itemId}
283
- tabindex="-1"
284
- aria-disabled={item.disabled ? 'true' : 'false'}
285
- aria-expanded={hasSubmenu ? 'false' : undefined}
286
- aria-haspopup={hasSubmenu ? 'true' : undefined}
287
- aria-controls={submenuId}
288
- data-dropdown-value={item.value || item.label}
289
- data-dropdown-onclick={item.onClick || ''}
290
- data-dropdown-has-submenu={hasSubmenu ? 'true' : undefined}
291
- >
292
- <span>{item.label}</span>
293
- {hasSubmenu && <ChevronDown class="dropdown__item-arrow" width={12} height={12} />}
294
- </div>
295
- {hasSubmenu && item.submenu && (
296
- <div
297
- class="dropdown__submenu"
298
- id={submenuId}
299
- role="menu"
300
- aria-label={`${item.label} submenu`}
301
- aria-hidden="true"
302
- >
303
- {item.submenu.map((subItem, subIndex) => {
304
- if (subItem.separator) {
305
- return <div class="dropdown__separator" role="separator" />;
306
- }
307
-
308
- const subItemId = `${submenuId}-item-${subIndex}`;
309
- const hasNestedSubmenu = subItem.submenu && subItem.submenu.length > 0;
310
- const nestedSubmenuId = hasNestedSubmenu ? `${subItemId}-submenu` : undefined;
311
-
312
- if (subItem.href) {
313
- return (
314
- <div class={`dropdown__item-wrapper ${hasNestedSubmenu ? 'dropdown__item-wrapper--has-submenu' : ''}`}>
315
- {hasNestedSubmenu ? (
316
- <div
317
- class={`dropdown__item dropdown__submenu-item ${subItem.disabled ? 'dropdown__item--disabled' : ''} dropdown__item--has-submenu`}
318
- role="menuitem"
319
- id={subItemId}
320
- tabindex="-1"
321
- aria-disabled={subItem.disabled ? 'true' : 'false'}
322
- aria-expanded="false"
323
- aria-haspopup="true"
324
- aria-controls={nestedSubmenuId}
325
- data-dropdown-has-submenu="true"
326
- >
327
- <span>{subItem.label}</span>
328
- <ChevronDown class="dropdown__item-arrow" width={12} height={12} />
329
- </div>
330
- ) : (
331
- <div
332
- class={`dropdown__item dropdown__submenu-item ${subItem.disabled ? 'dropdown__item--disabled' : ''}`}
333
- role="menuitem"
334
- id={subItemId}
335
- tabindex="-1"
336
- aria-disabled={subItem.disabled ? 'true' : 'false'}
337
- data-dropdown-href={subItem.href}
338
- >
339
- <span>{subItem.label}</span>
340
- </div>
341
- )}
342
- {hasNestedSubmenu && subItem.submenu && (
343
- <div
344
- class="dropdown__submenu"
345
- id={nestedSubmenuId}
346
- role="menu"
347
- aria-label={`${subItem.label} submenu`}
348
- aria-hidden="true"
349
- >
350
- {subItem.submenu.map((nestedItem, nestedIndex) => {
351
- if (nestedItem.separator) {
352
- return <div class="dropdown__separator" role="separator" />;
353
- }
354
-
355
- const nestedItemId = `${nestedSubmenuId}-item-${nestedIndex}`;
356
-
357
- if (nestedItem.href) {
358
- return (
359
- <div
360
- class={`dropdown__item dropdown__submenu-item ${nestedItem.disabled ? 'dropdown__item--disabled' : ''}`}
361
- role="menuitem"
362
- id={nestedItemId}
363
- tabindex="-1"
364
- aria-label={nestedItem.label}
365
- aria-disabled={nestedItem.disabled ? 'true' : 'false'}
366
- data-dropdown-href={nestedItem.href}
367
- >
368
- <span>{nestedItem.label}</span>
369
- </div>
370
- );
371
- }
372
-
373
- return (
374
- <div
375
- class={`dropdown__item dropdown__submenu-item ${nestedItem.disabled ? 'dropdown__item--disabled' : ''}`}
376
- role="menuitem"
377
- id={nestedItemId}
378
- tabindex="-1"
379
- aria-disabled={nestedItem.disabled ? 'true' : 'false'}
380
- data-dropdown-value={nestedItem.value || nestedItem.label}
381
- data-dropdown-onclick={nestedItem.onClick || ''}
382
- >
383
- <span>{nestedItem.label}</span>
384
- </div>
385
- );
386
- })}
387
- </div>
388
- )}
389
- </div>
390
- );
391
- }
392
-
393
- return (
394
- <div class={`dropdown__item-wrapper ${hasNestedSubmenu ? 'dropdown__item-wrapper--has-submenu' : ''}`}>
395
- <div
396
- class={`dropdown__item dropdown__submenu-item ${subItem.disabled ? 'dropdown__item--disabled' : ''} ${hasNestedSubmenu ? 'dropdown__item--has-submenu' : ''}`}
397
- role="menuitem"
398
- id={subItemId}
399
- tabindex="-1"
400
- aria-label={subItem.label}
401
- aria-disabled={subItem.disabled ? 'true' : 'false'}
402
- aria-expanded={hasNestedSubmenu ? 'false' : undefined}
403
- aria-haspopup={hasNestedSubmenu ? 'true' : undefined}
404
- aria-controls={nestedSubmenuId}
405
- data-dropdown-value={subItem.value || subItem.label}
406
- data-dropdown-onclick={subItem.onClick || ''}
407
- data-dropdown-has-submenu={hasNestedSubmenu ? 'true' : undefined}
408
- >
409
- <span>{subItem.label}</span>
410
- {hasNestedSubmenu && <ChevronDown class="dropdown__item-arrow" width={12} height={12} />}
411
- </div>
412
- {hasNestedSubmenu && subItem.submenu && (
413
- <div
414
- class="dropdown__submenu"
415
- id={nestedSubmenuId}
416
- role="menu"
417
- aria-label={`${subItem.label} submenu`}
418
- aria-hidden="true"
419
- >
420
- {subItem.submenu.map((nestedItem, nestedIndex) => {
421
- if (nestedItem.separator) {
422
- return <div class="dropdown__separator" role="separator" />;
423
- }
424
-
425
- const nestedItemId = `${nestedSubmenuId}-item-${nestedIndex}`;
426
-
427
- if (nestedItem.href) {
428
- return (
429
- <div
430
- class={`dropdown__item dropdown__submenu-item ${nestedItem.disabled ? 'dropdown__item--disabled' : ''}`}
431
- role="menuitem"
432
- id={nestedItemId}
433
- tabindex="-1"
434
- aria-disabled={nestedItem.disabled ? 'true' : 'false'}
435
- data-dropdown-href={nestedItem.href}
436
- >
437
- <span>{nestedItem.label}</span>
438
- </div>
439
- );
440
- }
441
-
442
- return (
443
- <div
444
- class={`dropdown__item dropdown__submenu-item ${nestedItem.disabled ? 'dropdown__item--disabled' : ''}`}
445
- role="menuitem"
446
- id={nestedItemId}
447
- tabindex="-1"
448
- aria-disabled={nestedItem.disabled ? 'true' : 'false'}
449
- data-dropdown-value={nestedItem.value || nestedItem.label}
450
- data-dropdown-onclick={nestedItem.onClick || ''}
451
- >
452
- <span>{nestedItem.label}</span>
453
- </div>
454
- );
455
- })}
456
- </div>
457
- )}
458
- </div>
459
- );
460
- })}
461
- </div>
462
- )}
463
- </div>
464
- );
465
- })}
466
- </div>
467
- </div>
468
-
469
- <script is:inline>
470
- (function initDropdown() {
471
- const init = () => {
472
- const dropdowns = document.querySelectorAll('[data-dropdown]');
473
-
474
- dropdowns.forEach((dropdown) => {
475
- const dropdownId = dropdown.getAttribute('data-dropdown');
476
- if (!dropdownId) return;
477
-
478
- if (dropdown.hasAttribute('data-dropdown-initialized')) return;
479
- dropdown.setAttribute('data-dropdown-initialized', 'true');
480
-
481
- const trigger = dropdown.querySelector('.dropdown__trigger');
482
- const menu = dropdown.querySelector('.dropdown__menu');
483
- const items = dropdown.querySelectorAll('.dropdown__item');
484
- const itemWrappers = dropdown.querySelectorAll('.dropdown__item-wrapper');
485
-
486
- if (!trigger || !menu) return;
487
-
488
- let currentIndex = -1;
489
-
490
- const getVisibleItems = () => {
491
- return Array.from(items).filter(item => {
492
- const isDisabled = item.getAttribute('aria-disabled') === 'true';
493
- const wrapper = item.closest('.dropdown__item-wrapper');
494
- const submenu = wrapper ? wrapper.querySelector('.dropdown__submenu') : null;
495
- // Don't include submenu items in main navigation
496
- if (submenu && item.closest('.dropdown__submenu')) {
497
- return false;
498
- }
499
- return !isDisabled && (item.offsetParent !== null || menu.classList.contains('dropdown__menu--open'));
500
- });
501
- };
502
-
503
- // Close all submenus except the one being opened
504
- const closeAllSubmenus = (exceptWrapper = null) => {
505
- itemWrappers.forEach((wrapper) => {
506
- if (wrapper === exceptWrapper) return; // Don't close the one we're opening
507
- const submenu = wrapper.querySelector('.dropdown__submenu');
508
- const item = wrapper.querySelector('.dropdown__item');
509
- if (submenu && item) {
510
- submenu.classList.remove('dropdown__submenu--open');
511
- submenu.setAttribute('aria-hidden', 'true');
512
- item.setAttribute('aria-expanded', 'false');
513
- }
514
- });
515
- };
516
-
517
- // Toggle submenu
518
- const toggleSubmenu = (wrapper, open) => {
519
- const submenu = wrapper.querySelector('.dropdown__submenu');
520
- const item = wrapper.querySelector('.dropdown__item');
521
- if (!submenu || !item) return;
522
-
523
- const isOpen = open !== undefined ? open : submenu.classList.contains('dropdown__submenu--open');
524
- const willBeOpen = !isOpen;
525
-
526
- // Close other submenus at the same level, but keep parent submenus open
527
- if (willBeOpen) {
528
- // Find all submenus at the same level (siblings of the current wrapper's parent)
529
- const parentSubmenu = wrapper.closest('.dropdown__submenu');
530
- if (parentSubmenu) {
531
- // Close siblings within the same parent submenu
532
- const siblingWrappers = parentSubmenu.querySelectorAll('.dropdown__item-wrapper');
533
- siblingWrappers.forEach((siblingWrapper) => {
534
- if (siblingWrapper === wrapper) return; // Don't close the one we're opening
535
- const siblingSubmenu = siblingWrapper.querySelector('.dropdown__submenu');
536
- const siblingItem = siblingWrapper.querySelector('.dropdown__item');
537
- if (siblingSubmenu && siblingItem) {
538
- siblingSubmenu.classList.remove('dropdown__submenu--open');
539
- siblingSubmenu.setAttribute('aria-hidden', 'true');
540
- siblingItem.setAttribute('aria-expanded', 'false');
541
- }
542
- });
543
- } else {
544
- // Main menu level - close all other main menu submenus
545
- closeAllSubmenus(wrapper);
546
- }
547
- }
548
-
549
- // Toggle the open class
550
- if (willBeOpen) {
551
- submenu.classList.add('dropdown__submenu--open');
552
- submenu.setAttribute('aria-hidden', 'false');
553
- item.setAttribute('aria-expanded', 'true');
554
- } else {
555
- submenu.classList.remove('dropdown__submenu--open');
556
- submenu.setAttribute('aria-hidden', 'true');
557
- item.setAttribute('aria-expanded', 'false');
558
- }
559
-
560
- // Position submenu - now positioned directly under the item
561
- if (willBeOpen) {
562
- // Submenu is positioned directly under via CSS (top: 100%, left: 0, right: 0)
563
- // No JavaScript positioning needed
564
- } else {
565
- // Reset any inline styles when closing
566
- submenu.style.left = '';
567
- submenu.style.right = '';
568
- submenu.style.top = '';
569
- submenu.style.marginLeft = '';
570
- submenu.style.marginRight = '';
571
- submenu.style.marginTop = '';
572
- submenu.style.maxWidth = '';
573
- submenu.style.width = '';
574
- }
575
- };
576
-
577
- const toggleMenu = (open) => {
578
- const isOpen = open !== undefined ? open : menu.classList.contains('dropdown__menu--open');
579
- const willBeOpen = !isOpen;
580
-
581
- menu.classList.toggle('dropdown__menu--open', willBeOpen);
582
- trigger.setAttribute('aria-expanded', willBeOpen.toString());
583
- menu.setAttribute('aria-hidden', (!willBeOpen).toString());
584
-
585
- items.forEach((item) => {
586
- item.setAttribute('tabindex', willBeOpen ? '0' : '-1');
587
- });
588
-
589
- if (!willBeOpen) {
590
- trigger.focus();
591
- currentIndex = -1;
592
- closeAllSubmenus();
593
- } else {
594
- const visibleItems = getVisibleItems();
595
- if (visibleItems.length > 0) {
596
- currentIndex = 0;
597
- setTimeout(() => visibleItems[0].focus(), 0);
598
- }
599
- }
600
- };
601
-
602
- const closeMenu = () => {
603
- menu.classList.remove('dropdown__menu--open');
604
- trigger.setAttribute('aria-expanded', 'false');
605
- menu.setAttribute('aria-hidden', 'true');
606
- items.forEach((item) => {
607
- item.setAttribute('tabindex', '-1');
608
- });
609
- closeAllSubmenus();
610
- currentIndex = -1;
611
- };
612
-
613
- // Handle outside click
614
- const handleOutsideClick = (e) => {
615
- if (e && e.target && !dropdown.contains(e.target)) {
616
- closeMenu();
617
- document.removeEventListener('click', handleOutsideClick);
618
- }
619
- };
620
-
621
- const wrappedToggleMenu = (open) => {
622
- const wasOpen = menu.classList.contains('dropdown__menu--open');
623
- toggleMenu(open);
624
- const isNowOpen = menu.classList.contains('dropdown__menu--open');
625
-
626
- if (isNowOpen && !wasOpen) {
627
- setTimeout(() => document.addEventListener('click', handleOutsideClick), 0);
628
- } else if (!isNowOpen && wasOpen) {
629
- document.removeEventListener('click', handleOutsideClick);
630
- }
631
- };
632
-
633
- // Trigger click
634
- trigger.addEventListener('click', () => wrappedToggleMenu(undefined));
635
-
636
- // Menu item click handler - handles all clicks including nested submenus
637
- menu.addEventListener('click', (e) => {
638
- const target = e.target;
639
- // Find the item - could be the button/a itself, or a child element (span, arrow icon, etc.)
640
- const item = target.closest('.dropdown__item');
641
- if (!item) return;
642
-
643
- // Stop propagation to prevent outside click handler from firing
644
- e.stopPropagation();
645
-
646
- const isDisabled = item.getAttribute('aria-disabled') === 'true';
647
- if (isDisabled) {
648
- e.preventDefault();
649
- return;
650
- }
651
-
652
- // FIRST: Check if item has submenu by finding wrapper and checking for submenu
653
- // This must be checked FIRST, regardless of whether item is in a submenu or not
654
- const wrapper = item.closest('.dropdown__item-wrapper');
655
-
656
- if (wrapper) {
657
- const submenu = wrapper.querySelector('.dropdown__submenu');
658
- if (submenu) {
659
- // Item has submenu - toggle it (works for main menu items AND nested submenu items)
660
- e.preventDefault();
661
- e.stopImmediatePropagation();
662
- toggleSubmenu(wrapper, undefined);
663
- return;
664
- }
665
- }
666
-
667
- // Item does NOT have a submenu - handle as regular item
668
- const href = item.getAttribute('data-dropdown-href');
669
- if (href) {
670
- window.location.href = href;
671
- }
672
- const onClick = item.getAttribute('data-dropdown-onclick');
673
- if (onClick && typeof window[onClick] === 'function') {
674
- const value = item.getAttribute('data-dropdown-value') || item.textContent?.trim() || '';
675
- window[onClick](value);
676
- }
677
-
678
- // Close menu for final items (items without submenus)
679
- closeMenu();
680
- });
681
-
682
- // Keyboard navigation on trigger
683
- trigger.addEventListener('keydown', (e) => {
684
- if (e && 'key' in e) {
685
- const keyEvent = e;
686
- if (keyEvent.key === 'Enter' || keyEvent.key === ' ') {
687
- keyEvent.preventDefault();
688
- wrappedToggleMenu(undefined);
689
- } else if (keyEvent.key === 'ArrowDown') {
690
- keyEvent.preventDefault();
691
- const visibleItems = getVisibleItems();
692
- if (visibleItems.length > 0) {
693
- currentIndex = 0;
694
- wrappedToggleMenu(true);
695
- setTimeout(() => visibleItems[0].focus(), 0);
696
- }
697
- } else if (keyEvent.key === 'ArrowUp') {
698
- keyEvent.preventDefault();
699
- const visibleItems = getVisibleItems();
700
- if (visibleItems.length > 0) {
701
- currentIndex = visibleItems.length - 1;
702
- wrappedToggleMenu(true);
703
- setTimeout(() => visibleItems[currentIndex].focus(), 0);
704
- }
705
- } else if (keyEvent.key === 'Escape') {
706
- keyEvent.preventDefault();
707
- closeMenu();
708
- }
709
- }
710
- });
711
-
712
- // Keyboard navigation in menu
713
- menu.addEventListener('keydown', (e) => {
714
- if (e && 'key' in e) {
715
- const keyEvent = e;
716
- const visibleItems = getVisibleItems();
717
-
718
- if (keyEvent.key === 'Escape') {
719
- keyEvent.preventDefault();
720
- closeMenu();
721
- trigger.focus();
722
- } else if (keyEvent.key === 'ArrowDown') {
723
- keyEvent.preventDefault();
724
- currentIndex = (currentIndex + 1) % visibleItems.length;
725
- visibleItems[currentIndex].focus();
726
- } else if (keyEvent.key === 'ArrowUp') {
727
- keyEvent.preventDefault();
728
- currentIndex = currentIndex <= 0 ? visibleItems.length - 1 : currentIndex - 1;
729
- visibleItems[currentIndex].focus();
730
- } else if (keyEvent.key === 'Home') {
731
- keyEvent.preventDefault();
732
- currentIndex = 0;
733
- visibleItems[0].focus();
734
- } else if (keyEvent.key === 'End') {
735
- keyEvent.preventDefault();
736
- currentIndex = visibleItems.length - 1;
737
- visibleItems[currentIndex].focus();
738
- } else if (keyEvent.key === 'ArrowRight') {
739
- // Open submenu if available
740
- const target = keyEvent.target;
741
- if (target && target instanceof HTMLElement) {
742
- const wrapper = target.closest('.dropdown__item-wrapper');
743
- if (wrapper) {
744
- const submenu = wrapper.querySelector('.dropdown__submenu');
745
- if (submenu) {
746
- keyEvent.preventDefault();
747
- toggleSubmenu(wrapper, true);
748
- const firstSubItem = submenu.querySelector('.dropdown__item');
749
- if (firstSubItem) {
750
- setTimeout(() => firstSubItem.focus(), 0);
751
- }
752
- }
753
- }
754
- }
755
- } else if (keyEvent.key === 'ArrowLeft') {
756
- // Close submenu if in one
757
- const target = keyEvent.target;
758
- if (target && target instanceof HTMLElement) {
759
- const submenu = target.closest('.dropdown__submenu');
760
- if (submenu) {
761
- keyEvent.preventDefault();
762
- const wrapper = submenu.closest('.dropdown__item-wrapper');
763
- if (wrapper) {
764
- toggleSubmenu(wrapper, false);
765
- const parentItem = wrapper.querySelector('.dropdown__item');
766
- if (parentItem) {
767
- parentItem.focus();
768
- }
769
- }
770
- }
771
- }
772
- } else if (keyEvent.key === 'Enter' || keyEvent.key === ' ') {
773
- keyEvent.preventDefault();
774
- const target = keyEvent.target;
775
- if (target && target instanceof HTMLElement) {
776
- const isDisabled = target.getAttribute('aria-disabled') === 'true';
777
- if (!isDisabled) {
778
- // Check if item has submenu
779
- const wrapper = target.closest('.dropdown__item-wrapper');
780
- const submenu = wrapper ? wrapper.querySelector('.dropdown__submenu') : null;
781
- if (submenu) {
782
- toggleSubmenu(wrapper, undefined);
783
- } else {
784
- if (target.tagName === 'A') {
785
- target.click();
786
- } else if (target.tagName === 'BUTTON') {
787
- target.click();
788
- }
789
- closeMenu();
790
- }
791
- }
792
- }
793
- } else if (keyEvent.key === 'Tab') {
794
- closeMenu();
795
- }
796
- }
797
- });
798
- });
799
- };
800
-
801
- if (document.readyState === 'loading') {
802
- document.addEventListener('DOMContentLoaded', init);
803
- } else {
804
- init();
805
- }
806
- })();
807
- </script>