@sapudex/web-components 2.60.0 → 2.62.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 (385) hide show
  1. package/cypress/specs/AccordionSpotlight.cy.tsx +43 -2
  2. package/cypress/specs/Carousel.cy.tsx +134 -0
  3. package/cypress/specs/CountrySelector.cy.tsx +233 -6
  4. package/cypress/specs/FilterMenu.cy.tsx +39 -45
  5. package/cypress/specs/List.cy.tsx +624 -10
  6. package/cypress/specs/ListItem.cy.tsx +50 -0
  7. package/cypress/specs/SecondaryNavigationDesktop.cy.tsx +52 -3
  8. package/cypress/specs/SelectBox.cy.tsx +276 -136
  9. package/cypress/specs/SelectBoxAccessibility.cy.tsx +3109 -0
  10. package/cypress/specs/SideNavigation.cy.tsx +509 -0
  11. package/cypress/specs/Table.cy.tsx +90 -0
  12. package/cypress/specs/TagGroup.cy.tsx +168 -0
  13. package/cypress/support/component-imports.instrumented.ts +6 -0
  14. package/cypress/support/component-imports.src.ts +6 -0
  15. package/dist/AccordionSpotlight.d.ts +7 -2
  16. package/dist/AccordionSpotlight.js +31 -6
  17. package/dist/AccordionSpotlight.js.map +1 -1
  18. package/dist/AccordionSpotlightItem.d.ts +3 -1
  19. package/dist/AccordionSpotlightItem.js +3 -1
  20. package/dist/AccordionSpotlightItem.js.map +1 -1
  21. package/dist/Carousel.d.ts +2 -0
  22. package/dist/Carousel.js +35 -4
  23. package/dist/Carousel.js.map +1 -1
  24. package/dist/CountrySelector.js +1 -3
  25. package/dist/CountrySelector.js.map +1 -1
  26. package/dist/List.d.ts +2 -0
  27. package/dist/List.js +22 -4
  28. package/dist/List.js.map +1 -1
  29. package/dist/ListGroupHeader.js +5 -1
  30. package/dist/ListGroupHeader.js.map +1 -1
  31. package/dist/ListGroupHeaderBase.d.ts +2 -0
  32. package/dist/ListGroupHeaderBase.js +15 -2
  33. package/dist/ListGroupHeaderBase.js.map +1 -1
  34. package/dist/ListGroupHeaderTemplate.js +14 -22
  35. package/dist/ListGroupHeaderTemplate.js.map +1 -1
  36. package/dist/ListItem.d.ts +1 -2
  37. package/dist/ListItem.js +14 -12
  38. package/dist/ListItem.js.map +1 -1
  39. package/dist/ListItemBase.d.ts +5 -0
  40. package/dist/ListItemBase.js +11 -1
  41. package/dist/ListItemBase.js.map +1 -1
  42. package/dist/ListItemTemplate.js +1 -1
  43. package/dist/ListItemTemplate.js.map +1 -1
  44. package/dist/ListSelectAllTemplate.js +1 -1
  45. package/dist/ListSelectAllTemplate.js.map +1 -1
  46. package/dist/ListTemplate.js +2 -1
  47. package/dist/ListTemplate.js.map +1 -1
  48. package/dist/Pagination.d.ts +0 -1
  49. package/dist/Pagination.js +2 -2
  50. package/dist/Pagination.js.map +1 -1
  51. package/dist/Search.d.ts +13 -3
  52. package/dist/Search.js +36 -11
  53. package/dist/Search.js.map +1 -1
  54. package/dist/SearchableListBase.d.ts +2 -0
  55. package/dist/SearchableListBase.js +13 -3
  56. package/dist/SearchableListBase.js.map +1 -1
  57. package/dist/SearchableListBaseTemplate.js +42 -34
  58. package/dist/SearchableListBaseTemplate.js.map +1 -1
  59. package/dist/SecondaryNavigation.d.ts +2 -1
  60. package/dist/SecondaryNavigation.js.map +1 -1
  61. package/dist/SecondaryNavigationItem.js +12 -6
  62. package/dist/SecondaryNavigationItem.js.map +1 -1
  63. package/dist/SecondaryNavigationTemplate.js +1 -2
  64. package/dist/SecondaryNavigationTemplate.js.map +1 -1
  65. package/dist/SelectBase.d.ts +18 -33
  66. package/dist/SelectBase.js +125 -140
  67. package/dist/SelectBase.js.map +1 -1
  68. package/dist/SelectBox.d.ts +3 -0
  69. package/dist/SelectBox.js +19 -7
  70. package/dist/SelectBox.js.map +1 -1
  71. package/dist/SelectBoxTemplate.js +3 -3
  72. package/dist/SelectBoxTemplate.js.map +1 -1
  73. package/dist/SideNavigation.d.ts +23 -0
  74. package/dist/SideNavigation.js +39 -0
  75. package/dist/SideNavigation.js.map +1 -1
  76. package/dist/SideNavigationItem.d.ts +10 -0
  77. package/dist/SideNavigationItem.js +69 -0
  78. package/dist/SideNavigationItem.js.map +1 -1
  79. package/dist/SideNavigationItemTemplate.d.ts +2 -0
  80. package/dist/SideNavigationItemTemplate.js +15 -0
  81. package/dist/SideNavigationItemTemplate.js.map +1 -0
  82. package/dist/SideNavigationMobile.js +1 -2
  83. package/dist/SideNavigationMobile.js.map +1 -1
  84. package/dist/SideNavigationMobileTemplate.js +1 -1
  85. package/dist/SideNavigationMobileTemplate.js.map +1 -1
  86. package/dist/SideNavigationSubItem.d.ts +23 -0
  87. package/dist/SideNavigationSubItem.js +105 -1
  88. package/dist/SideNavigationSubItem.js.map +1 -1
  89. package/dist/SideNavigationSubItemTemplate.d.ts +2 -0
  90. package/dist/SideNavigationSubItemTemplate.js +9 -0
  91. package/dist/SideNavigationSubItemTemplate.js.map +1 -0
  92. package/dist/Table.js +1 -1
  93. package/dist/Table.js.map +1 -1
  94. package/dist/TableCell.d.ts +8 -2
  95. package/dist/TableCell.js +13 -11
  96. package/dist/TableCell.js.map +1 -1
  97. package/dist/TableCellBase.d.ts +2 -1
  98. package/dist/TableCellBase.js +9 -0
  99. package/dist/TableCellBase.js.map +1 -1
  100. package/dist/TableHeaderCell.d.ts +0 -1
  101. package/dist/TableHeaderCell.js +0 -4
  102. package/dist/TableHeaderCell.js.map +1 -1
  103. package/dist/TableRow.d.ts +10 -0
  104. package/dist/TableRow.js +23 -0
  105. package/dist/TableRow.js.map +1 -1
  106. package/dist/TagGroup.d.ts +3 -0
  107. package/dist/TagGroup.js +31 -0
  108. package/dist/TagGroup.js.map +1 -1
  109. package/dist/TagGroupTemplate.js +1 -1
  110. package/dist/TagGroupTemplate.js.map +1 -1
  111. package/dist/UploadItem.js +3 -4
  112. package/dist/UploadItem.js.map +1 -1
  113. package/dist/assets/{InputSuggestions-DyNcKgip.js → InputSuggestions-BPKrPqPb.js} +1 -1
  114. package/dist/assets/{ListItemStandardExpandableTextTemplate-qdKPzaOQ.js → ListItemStandardExpandableTextTemplate-DkdOcCxC.js} +1 -1
  115. package/dist/assets/{bundle.esm-sUYwSJOp.js → bundle.esm-17Yt5gDr.js} +234 -235
  116. package/dist/css/themes/AccordionSpotlight.css +1 -1
  117. package/dist/css/themes/Contact.css +1 -1
  118. package/dist/css/themes/EventRibbon.css +1 -1
  119. package/dist/css/themes/Feed.css +1 -1
  120. package/dist/css/themes/HeroBanner.css +1 -1
  121. package/dist/css/themes/ImageGridCloud.css +1 -1
  122. package/dist/css/themes/ImageGridTicker.css +1 -1
  123. package/dist/css/themes/ImageGridTickerItem.css +1 -1
  124. package/dist/css/themes/LinkList.css +1 -1
  125. package/dist/css/themes/ListGroupHeader.css +1 -1
  126. package/dist/css/themes/MastheadCountrySelector.css +1 -1
  127. package/dist/css/themes/MastheadItem.css +1 -1
  128. package/dist/css/themes/MastheadMenu.css +1 -1
  129. package/dist/css/themes/MastheadMenuItem.css +1 -1
  130. package/dist/css/themes/MastheadMobileMenu.css +1 -1
  131. package/dist/css/themes/MastheadProfileMenu.css +1 -1
  132. package/dist/css/themes/MastheadShell.css +1 -1
  133. package/dist/css/themes/MessageStrip.css +1 -1
  134. package/dist/css/themes/Modal.css +1 -1
  135. package/dist/css/themes/PromoTile.css +1 -1
  136. package/dist/css/themes/Quote.css +1 -1
  137. package/dist/css/themes/Review.css +1 -1
  138. package/dist/css/themes/ReviewItem.css +1 -1
  139. package/dist/css/themes/SecondaryNavigation.css +1 -1
  140. package/dist/css/themes/SecondaryNavigationItem.css +1 -1
  141. package/dist/css/themes/SelectBase.css +1 -1
  142. package/dist/css/themes/SideNavigation.css +1 -1
  143. package/dist/css/themes/SideNavigationItem.css +1 -1
  144. package/dist/css/themes/SideNavigationMobile.css +1 -1
  145. package/dist/css/themes/SideNavigationSubItem.css +1 -1
  146. package/dist/css/themes/TabNavigation.css +1 -1
  147. package/dist/css/themes/Table.css +1 -1
  148. package/dist/css/themes/TableCellBase.css +1 -1
  149. package/dist/css/themes/Upload.css +1 -1
  150. package/dist/css/themes/UploadItem.css +1 -1
  151. package/dist/custom-elements-internal.json +162 -19
  152. package/dist/custom-elements.json +151 -26
  153. package/dist/generated/i18n/i18n-defaults.d.ts +2 -1
  154. package/dist/generated/i18n/i18n-defaults.js +2 -1
  155. package/dist/generated/i18n/i18n-defaults.js.map +1 -1
  156. package/dist/generated/themes/AccordionSpotlight.css.d.ts +1 -1
  157. package/dist/generated/themes/AccordionSpotlight.css.js +1 -1
  158. package/dist/generated/themes/AccordionSpotlight.css.js.map +1 -1
  159. package/dist/generated/themes/Contact.css.d.ts +1 -1
  160. package/dist/generated/themes/Contact.css.js +1 -1
  161. package/dist/generated/themes/Contact.css.js.map +1 -1
  162. package/dist/generated/themes/EventRibbon.css.d.ts +1 -1
  163. package/dist/generated/themes/EventRibbon.css.js +1 -1
  164. package/dist/generated/themes/EventRibbon.css.js.map +1 -1
  165. package/dist/generated/themes/Feed.css.d.ts +1 -1
  166. package/dist/generated/themes/Feed.css.js +1 -1
  167. package/dist/generated/themes/Feed.css.js.map +1 -1
  168. package/dist/generated/themes/HeroBanner.css.d.ts +1 -1
  169. package/dist/generated/themes/HeroBanner.css.js +1 -1
  170. package/dist/generated/themes/HeroBanner.css.js.map +1 -1
  171. package/dist/generated/themes/ImageGridCloud.css.d.ts +1 -1
  172. package/dist/generated/themes/ImageGridCloud.css.js +1 -1
  173. package/dist/generated/themes/ImageGridCloud.css.js.map +1 -1
  174. package/dist/generated/themes/ImageGridTicker.css.d.ts +1 -1
  175. package/dist/generated/themes/ImageGridTicker.css.js +1 -1
  176. package/dist/generated/themes/ImageGridTicker.css.js.map +1 -1
  177. package/dist/generated/themes/ImageGridTickerItem.css.d.ts +1 -1
  178. package/dist/generated/themes/ImageGridTickerItem.css.js +1 -1
  179. package/dist/generated/themes/ImageGridTickerItem.css.js.map +1 -1
  180. package/dist/generated/themes/LinkList.css.d.ts +1 -1
  181. package/dist/generated/themes/LinkList.css.js +1 -1
  182. package/dist/generated/themes/LinkList.css.js.map +1 -1
  183. package/dist/generated/themes/ListGroupHeader.css.d.ts +1 -1
  184. package/dist/generated/themes/ListGroupHeader.css.js +1 -1
  185. package/dist/generated/themes/ListGroupHeader.css.js.map +1 -1
  186. package/dist/generated/themes/MastheadCountrySelector.css.d.ts +1 -1
  187. package/dist/generated/themes/MastheadCountrySelector.css.js +1 -1
  188. package/dist/generated/themes/MastheadCountrySelector.css.js.map +1 -1
  189. package/dist/generated/themes/MastheadItem.css.d.ts +1 -1
  190. package/dist/generated/themes/MastheadItem.css.js +1 -1
  191. package/dist/generated/themes/MastheadItem.css.js.map +1 -1
  192. package/dist/generated/themes/MastheadMenu.css.d.ts +1 -1
  193. package/dist/generated/themes/MastheadMenu.css.js +1 -1
  194. package/dist/generated/themes/MastheadMenu.css.js.map +1 -1
  195. package/dist/generated/themes/MastheadMenuItem.css.d.ts +1 -1
  196. package/dist/generated/themes/MastheadMenuItem.css.js +1 -1
  197. package/dist/generated/themes/MastheadMenuItem.css.js.map +1 -1
  198. package/dist/generated/themes/MastheadMobileMenu.css.d.ts +1 -1
  199. package/dist/generated/themes/MastheadMobileMenu.css.js +1 -1
  200. package/dist/generated/themes/MastheadMobileMenu.css.js.map +1 -1
  201. package/dist/generated/themes/MastheadProfileMenu.css.d.ts +1 -1
  202. package/dist/generated/themes/MastheadProfileMenu.css.js +1 -1
  203. package/dist/generated/themes/MastheadProfileMenu.css.js.map +1 -1
  204. package/dist/generated/themes/MastheadShell.css.d.ts +1 -1
  205. package/dist/generated/themes/MastheadShell.css.js +1 -1
  206. package/dist/generated/themes/MastheadShell.css.js.map +1 -1
  207. package/dist/generated/themes/MessageStrip.css.d.ts +1 -1
  208. package/dist/generated/themes/MessageStrip.css.js +1 -1
  209. package/dist/generated/themes/MessageStrip.css.js.map +1 -1
  210. package/dist/generated/themes/Modal.css.d.ts +1 -1
  211. package/dist/generated/themes/Modal.css.js +1 -1
  212. package/dist/generated/themes/Modal.css.js.map +1 -1
  213. package/dist/generated/themes/PromoTile.css.d.ts +1 -1
  214. package/dist/generated/themes/PromoTile.css.js +1 -1
  215. package/dist/generated/themes/PromoTile.css.js.map +1 -1
  216. package/dist/generated/themes/Quote.css.d.ts +1 -1
  217. package/dist/generated/themes/Quote.css.js +1 -1
  218. package/dist/generated/themes/Quote.css.js.map +1 -1
  219. package/dist/generated/themes/Review.css.d.ts +1 -1
  220. package/dist/generated/themes/Review.css.js +1 -1
  221. package/dist/generated/themes/Review.css.js.map +1 -1
  222. package/dist/generated/themes/ReviewItem.css.d.ts +1 -1
  223. package/dist/generated/themes/ReviewItem.css.js +1 -1
  224. package/dist/generated/themes/ReviewItem.css.js.map +1 -1
  225. package/dist/generated/themes/SecondaryNavigation.css.d.ts +1 -1
  226. package/dist/generated/themes/SecondaryNavigation.css.js +1 -1
  227. package/dist/generated/themes/SecondaryNavigation.css.js.map +1 -1
  228. package/dist/generated/themes/SecondaryNavigationItem.css.d.ts +1 -1
  229. package/dist/generated/themes/SecondaryNavigationItem.css.js +1 -1
  230. package/dist/generated/themes/SecondaryNavigationItem.css.js.map +1 -1
  231. package/dist/generated/themes/SelectBase.css.d.ts +1 -1
  232. package/dist/generated/themes/SelectBase.css.js +1 -1
  233. package/dist/generated/themes/SelectBase.css.js.map +1 -1
  234. package/dist/generated/themes/SideNavigation.css.d.ts +1 -1
  235. package/dist/generated/themes/SideNavigation.css.js +1 -1
  236. package/dist/generated/themes/SideNavigation.css.js.map +1 -1
  237. package/dist/generated/themes/SideNavigationItem.css.d.ts +1 -1
  238. package/dist/generated/themes/SideNavigationItem.css.js +1 -1
  239. package/dist/generated/themes/SideNavigationItem.css.js.map +1 -1
  240. package/dist/generated/themes/SideNavigationMobile.css.d.ts +1 -1
  241. package/dist/generated/themes/SideNavigationMobile.css.js +1 -1
  242. package/dist/generated/themes/SideNavigationMobile.css.js.map +1 -1
  243. package/dist/generated/themes/SideNavigationSubItem.css.d.ts +1 -1
  244. package/dist/generated/themes/SideNavigationSubItem.css.js +1 -1
  245. package/dist/generated/themes/SideNavigationSubItem.css.js.map +1 -1
  246. package/dist/generated/themes/TabNavigation.css.d.ts +1 -1
  247. package/dist/generated/themes/TabNavigation.css.js +1 -1
  248. package/dist/generated/themes/TabNavigation.css.js.map +1 -1
  249. package/dist/generated/themes/Table.css.d.ts +1 -1
  250. package/dist/generated/themes/Table.css.js +1 -1
  251. package/dist/generated/themes/Table.css.js.map +1 -1
  252. package/dist/generated/themes/TableCellBase.css.d.ts +1 -1
  253. package/dist/generated/themes/TableCellBase.css.js +1 -1
  254. package/dist/generated/themes/TableCellBase.css.js.map +1 -1
  255. package/dist/generated/themes/Upload.css.d.ts +1 -1
  256. package/dist/generated/themes/Upload.css.js +1 -1
  257. package/dist/generated/themes/Upload.css.js.map +1 -1
  258. package/dist/generated/themes/UploadItem.css.d.ts +1 -1
  259. package/dist/generated/themes/UploadItem.css.js +1 -1
  260. package/dist/generated/themes/UploadItem.css.js.map +1 -1
  261. package/dist/messagebundle.properties +3 -0
  262. package/dist/types/Table.d.ts +6 -2
  263. package/dist/types/Table.js +7 -2
  264. package/dist/types/Table.js.map +1 -1
  265. package/dist/vscode.html-custom-data.json +48 -7
  266. package/dist/web-types.json +88 -14
  267. package/package.json +1 -1
  268. package/run-cypress.js +8 -1
  269. package/src/AccordionSpotlight.ts +35 -6
  270. package/src/AccordionSpotlightItem.ts +3 -1
  271. package/src/Carousel.ts +39 -4
  272. package/src/CountrySelector.ts +1 -3
  273. package/src/List.ts +21 -4
  274. package/src/ListGroupHeader.ts +5 -1
  275. package/src/ListGroupHeaderBase.ts +16 -2
  276. package/src/ListGroupHeaderTemplate.tsx +29 -47
  277. package/src/ListItem.ts +14 -13
  278. package/src/ListItemBase.ts +14 -1
  279. package/src/ListItemTemplate.tsx +4 -4
  280. package/src/ListSelectAllTemplate.tsx +10 -8
  281. package/src/ListTemplate.tsx +14 -10
  282. package/src/Pagination.ts +2 -3
  283. package/src/Search.ts +48 -13
  284. package/src/SearchableListBase.ts +15 -3
  285. package/src/SearchableListBaseTemplate.tsx +51 -37
  286. package/src/SecondaryNavigation.ts +2 -1
  287. package/src/SecondaryNavigationItem.ts +14 -6
  288. package/src/SecondaryNavigationTemplate.tsx +4 -6
  289. package/src/SelectBase.ts +131 -145
  290. package/src/SelectBox.ts +21 -7
  291. package/src/SelectBoxTemplate.tsx +10 -9
  292. package/src/SideNavigation.ts +35 -0
  293. package/src/SideNavigationItem.ts +77 -0
  294. package/src/SideNavigationItemTemplate.tsx +97 -0
  295. package/src/SideNavigationMobile.ts +1 -2
  296. package/src/SideNavigationMobileTemplate.tsx +2 -1
  297. package/src/SideNavigationSubItem.ts +119 -2
  298. package/src/SideNavigationSubItemTemplate.tsx +57 -0
  299. package/src/Table.ts +1 -2
  300. package/src/TableCell.ts +9 -12
  301. package/src/TableCellBase.ts +10 -1
  302. package/src/TableHeaderCell.ts +0 -5
  303. package/src/TableRow.ts +20 -0
  304. package/src/TagGroup.ts +32 -0
  305. package/src/TagGroupTemplate.tsx +1 -1
  306. package/src/UploadItem.ts +3 -5
  307. package/src/generated/i18n/i18n-defaults.ts +2 -2
  308. package/src/generated/themes/AccordionSpotlight.css.ts +1 -1
  309. package/src/generated/themes/Contact.css.ts +1 -1
  310. package/src/generated/themes/EventRibbon.css.ts +1 -1
  311. package/src/generated/themes/Feed.css.ts +1 -1
  312. package/src/generated/themes/HeroBanner.css.ts +1 -1
  313. package/src/generated/themes/ImageGridCloud.css.ts +1 -1
  314. package/src/generated/themes/ImageGridTicker.css.ts +1 -1
  315. package/src/generated/themes/ImageGridTickerItem.css.ts +1 -1
  316. package/src/generated/themes/LinkList.css.ts +1 -1
  317. package/src/generated/themes/ListGroupHeader.css.ts +1 -1
  318. package/src/generated/themes/MastheadCountrySelector.css.ts +1 -1
  319. package/src/generated/themes/MastheadItem.css.ts +1 -1
  320. package/src/generated/themes/MastheadMenu.css.ts +1 -1
  321. package/src/generated/themes/MastheadMenuItem.css.ts +1 -1
  322. package/src/generated/themes/MastheadMobileMenu.css.ts +1 -1
  323. package/src/generated/themes/MastheadProfileMenu.css.ts +1 -1
  324. package/src/generated/themes/MastheadShell.css.ts +1 -1
  325. package/src/generated/themes/MessageStrip.css.ts +1 -1
  326. package/src/generated/themes/Modal.css.ts +1 -1
  327. package/src/generated/themes/PromoTile.css.ts +1 -1
  328. package/src/generated/themes/Quote.css.ts +1 -1
  329. package/src/generated/themes/Review.css.ts +1 -1
  330. package/src/generated/themes/ReviewItem.css.ts +1 -1
  331. package/src/generated/themes/SecondaryNavigation.css.ts +1 -1
  332. package/src/generated/themes/SecondaryNavigationItem.css.ts +1 -1
  333. package/src/generated/themes/SelectBase.css.ts +1 -1
  334. package/src/generated/themes/SideNavigation.css.ts +1 -1
  335. package/src/generated/themes/SideNavigationItem.css.ts +1 -1
  336. package/src/generated/themes/SideNavigationMobile.css.ts +1 -1
  337. package/src/generated/themes/SideNavigationSubItem.css.ts +1 -1
  338. package/src/generated/themes/TabNavigation.css.ts +1 -1
  339. package/src/generated/themes/Table.css.ts +1 -1
  340. package/src/generated/themes/TableCellBase.css.ts +1 -1
  341. package/src/generated/themes/Upload.css.ts +1 -1
  342. package/src/generated/themes/UploadItem.css.ts +1 -1
  343. package/src/i18n/messagebundle.properties +3 -0
  344. package/src/themes/AccordionSpotlight.css +11 -8
  345. package/src/themes/Contact.css +1 -1
  346. package/src/themes/EventRibbon.css +4 -4
  347. package/src/themes/Feed.css +2 -2
  348. package/src/themes/HeroBanner.css +3 -3
  349. package/src/themes/ImageGridCloud.css +1 -1
  350. package/src/themes/ImageGridTicker.css +1 -1
  351. package/src/themes/ImageGridTickerItem.css +1 -1
  352. package/src/themes/LinkList.css +4 -4
  353. package/src/themes/ListGroupHeader.css +2 -43
  354. package/src/themes/MastheadCountrySelector.css +1 -1
  355. package/src/themes/MastheadItem.css +4 -4
  356. package/src/themes/MastheadMenu.css +1 -1
  357. package/src/themes/MastheadMenuItem.css +1 -1
  358. package/src/themes/MastheadMobileMenu.css +2 -2
  359. package/src/themes/MastheadProfileMenu.css +1 -1
  360. package/src/themes/MastheadShell.css +4 -4
  361. package/src/themes/MessageStrip.css +7 -2
  362. package/src/themes/Modal.css +1 -1
  363. package/src/themes/PromoTile.css +4 -3
  364. package/src/themes/Quote.css +2 -2
  365. package/src/themes/Review.css +2 -2
  366. package/src/themes/ReviewItem.css +2 -2
  367. package/src/themes/SecondaryNavigation.css +1 -2
  368. package/src/themes/SecondaryNavigationItem.css +3 -6
  369. package/src/themes/SelectBase.css +1 -1
  370. package/src/themes/SideNavigation.css +31 -8
  371. package/src/themes/SideNavigationItem.css +100 -22
  372. package/src/themes/SideNavigationMobile.css +65 -20
  373. package/src/themes/SideNavigationSubItem.css +15 -54
  374. package/src/themes/TabNavigation.css +2 -2
  375. package/src/themes/Table.css +7 -2
  376. package/src/themes/TableCellBase.css +8 -0
  377. package/src/themes/Upload.css +1 -1
  378. package/src/themes/UploadItem.css +1 -1
  379. package/src/types/Table.ts +6 -2
  380. package/dist/css/themes/SideNavigationMobileDropdown.css +0 -1
  381. package/dist/generated/themes/SideNavigationMobileDropdown.css.d.ts +0 -2
  382. package/dist/generated/themes/SideNavigationMobileDropdown.css.js +0 -8
  383. package/dist/generated/themes/SideNavigationMobileDropdown.css.js.map +0 -1
  384. package/src/generated/themes/SideNavigationMobileDropdown.css.ts +0 -9
  385. package/src/themes/SideNavigationMobileDropdown.css +0 -29
package/src/SelectBase.ts CHANGED
@@ -10,11 +10,12 @@ import { cleanLabel } from "./utils/listItemLabelUtils.js";
10
10
  import type { UDExListItemBase } from "./List.js";
11
11
  import type Popover from "@ui5/webcomponents/dist/Popover.js";
12
12
  import type UDExList from "./List.js";
13
+ import type UDExListSelectAll from "./ListSelectAll.js";
13
14
  import type UDExSearch from "./Search.js";
14
15
  import "@ui5/webcomponents-icons/dist/decline.js";
15
16
  import "@ui5/webcomponents-icons/dist/navigation-down-arrow.js";
16
17
  import {
17
- COUNTRY_SELECT, STARS, SELECTED, UNSELECTED, INDETERMINATE, DISABLED, EXPANDED, COLLAPSED,
18
+ COUNTRY_SELECT, STARS, SELECTED, UNSELECTED, INDETERMINATE, EXPANDED,
18
19
  } from "./generated/i18n/i18n-defaults.js";
19
20
  import SearchableListBaseTemplate from "./SearchableListBaseTemplate.js";
20
21
  import CountrySelectorTemplate from "./CountrySelectorTemplate.js";
@@ -178,10 +179,9 @@ class UDExSelectBase extends UDExSearchableListBase {
178
179
  _navigating: boolean = false;
179
180
 
180
181
  /**
181
- * Text read by screen readers when the active item changes.
182
- * Announced via an aria-live="assertive" region in the template.
183
- * This works regardless of shadow DOM / popover teleportation because
184
- * the live region lives inside SelectBox's own shadow root.
182
+ * Supplemental status announced by the polite live region.
183
+ * Navigation uses native host semantics only. Opening and explicit selection
184
+ * changes retain feedback without repeating the hierarchy or input token count.
185
185
  *
186
186
  * @private
187
187
  */
@@ -215,6 +215,7 @@ class UDExSelectBase extends UDExSearchableListBase {
215
215
  _handleListKeyDownBound: (e: KeyboardEvent) => void;
216
216
  _listKeyDownListenerAdded: boolean = false;
217
217
  _activeDescendantItem: UDExListItemBase | null = null;
218
+ _pendingSelectionAnnouncement = "";
218
219
 
219
220
  constructor() {
220
221
  super();
@@ -288,14 +289,14 @@ class UDExSelectBase extends UDExSearchableListBase {
288
289
  }
289
290
 
290
291
  /**
291
- * Sets or clears the aria-activedescendant on the combobox input and updates
292
- * the aria-live region so JAWS/VoiceOver announce the item name and position.
293
- * The live region is the primary announcement mechanism because aria-activedescendant
294
- * across a UI5 Popover (which teleports content to document.body) is unreliable —
295
- * screen readers cannot follow the ID reference across shadow root boundaries.
292
+ * Sets or clears the aria-activedescendant on the combobox input.
293
+ * The referenced host owns its name, hierarchy and state; do not repeat these
294
+ * in the live region on navigation.
296
295
  */
297
296
  _setActiveDescendant(item: UDExListItemBase | null, scroll = true): void {
298
297
  this._activeDescendantItem = item;
298
+ this._navigating = !!item;
299
+ this._liveRegionText = "";
299
300
 
300
301
  // Query the SelectBox's OWN shadow DOM for all elements bearing the class —
301
302
  // this reaches the rendered udex-list-group-header / udex-list-item elements
@@ -308,23 +309,12 @@ class UDExSelectBase extends UDExSearchableListBase {
308
309
 
309
310
  if (!item) {
310
311
  (this._search as HTMLElement).removeAttribute("aria-activedescendant");
311
- this._liveRegionText = "";
312
312
  return;
313
313
  }
314
314
 
315
315
  item.classList.add("_udex-active-descendant");
316
316
  item.setAttribute("_active-descendant", "");
317
- (this._search as HTMLElement).setAttribute("aria-activedescendant", item._id);
318
-
319
- // Update the live region with tree-aware position and state so JAWS/VoiceOver
320
- // announce the active item regardless of whether the popover is teleported to document.body.
321
- if (this._list) {
322
- const label = cleanLabel(item.label ?? "");
323
- const supporting = item.supportingText ? cleanLabel(item.supportingText) : "";
324
- const stateParts = this._itemStateLabels(item);
325
- const posText = this._treePositionText(item);
326
- this._liveRegionText = [label, supporting, posText, ...stateParts].filter(Boolean).join(", ");
327
- }
317
+ (this._search as HTMLElement).setAttribute("aria-activedescendant", item.id);
328
318
 
329
319
  if (scroll && this._list?._scrollIntoView) {
330
320
  // Only scroll if the item is not already fully visible in the dropdown.
@@ -342,6 +332,42 @@ class UDExSelectBase extends UDExSearchableListBase {
342
332
  }
343
333
  }
344
334
 
335
+ /** Announce explicit selection after the rendered host has caught up with source changes. @private */
336
+ _announceSelectionChange(): void {
337
+ const item = this._activeDescendantItem;
338
+ this._liveRegionText = "";
339
+ renderFinished().then(() => {
340
+ if (this._open && item && this._activeDescendantItem === item) {
341
+ this._liveRegionText = this._selectionAnnouncement(item);
342
+ }
343
+ }).catch(() => {});
344
+ }
345
+
346
+ /** Explicit activation feedback is distinct from native navigation announcements. @private */
347
+ _selectionAnnouncement(item: Pick<UDExListItemBase, "label" | "supportingText" | "getAttribute" | "selected" | "indeterminate" | "hasRating" | "ratingAriaLabel">): string {
348
+ // CountrySelector sources are data objects, not DOM elements.
349
+ const name = item.getAttribute?.("aria-label") || [item.label, item.supportingText, item.getAttribute?.("additional-text"), item.hasRating ? item.ratingAriaLabel : undefined]
350
+ .filter(Boolean).map(text => cleanLabel(text!)).join(" ");
351
+ const selectionState = item.selected ? SELECTED : UNSELECTED;
352
+ const state = translate(UDExSelectBase, item.indeterminate ? INDETERMINATE : selectionState);
353
+ return [name, state].filter(Boolean).join(", ");
354
+ }
355
+
356
+ /** Close feedback must survive clearing the active descendant. @private */
357
+ _finishDropdownClose(): void {
358
+ this._setActiveDescendant(null);
359
+ this._open = false;
360
+ this._liveRegionText = this._pendingSelectionAnnouncement;
361
+ this._pendingSelectionAnnouncement = "";
362
+ this.fireEventDropdownClose();
363
+ }
364
+
365
+ override handleAccordionIconClick(e: CustomEvent<{ collapsed: boolean }>): void {
366
+ super.handleAccordionIconClick(e);
367
+ // The host's aria-expanded owns this feedback; discard stale selection status.
368
+ this._liveRegionText = "";
369
+ }
370
+
345
371
  /**
346
372
  * Activates the first navigable item as the aria-activedescendant without moving DOM focus.
347
373
  */
@@ -359,7 +385,7 @@ class UDExSelectBase extends UDExSearchableListBase {
359
385
  * restores focus to it; when nothing is selected (or in other modes) the first navigable
360
386
  * item is activated instead.
361
387
  */
362
- _activateSelectedOrFirstItem(): void {
388
+ _activateSelectedOrFirstItem(): UDExListItemBase | undefined {
363
389
  const items = this._list?.getKeyboardNavigationItems();
364
390
  if (!items?.length) {
365
391
  return;
@@ -376,6 +402,7 @@ class UDExSelectBase extends UDExSearchableListBase {
376
402
  if (this.showImageFlags) {
377
403
  this.handleImagePosition(items, targetIndex);
378
404
  }
405
+ return items[targetIndex];
379
406
  }
380
407
 
381
408
  /**
@@ -542,8 +569,14 @@ class UDExSelectBase extends UDExSearchableListBase {
542
569
 
543
570
  if (this.modeSingleSelect) {
544
571
  // SingleSelect closes the dropdown — clear active descendant.
572
+ const selectedItem = this.getItemFromList(this.getDataTokenId(item));
573
+ if (selectedItem) {
574
+ this._pendingSelectionAnnouncement = this._selectionAnnouncement(selectedItem);
575
+ }
545
576
  this._setActiveDescendant(null);
546
- this._search.focus();
577
+ if (this.shadowRoot?.activeElement !== this._search) {
578
+ this._search.focus();
579
+ }
547
580
  this.closeDropdown();
548
581
  return;
549
582
  }
@@ -564,12 +597,10 @@ class UDExSelectBase extends UDExSearchableListBase {
564
597
  // Return DOM focus to the input so the clicked item loses its :focus ring.
565
598
  // Without this, the browser keeps focus on the item (from the click) and a
566
599
  // second ring appears when arrow keys move _activeDescendantItem elsewhere.
567
- (this._search as HTMLElement).focus();
568
-
569
- // Re-announce with the updated checked/unchecked state. The rendered item's
570
- // `selected` prop is updated on the next render cycle (template re-render),
571
- // so we wait for it before re-reading state labels.
572
- renderFinished().then(() => this._announceCurrentOrFirst()).catch(() => {});
600
+ if (this.shadowRoot?.activeElement !== this._search) {
601
+ (this._search as HTMLElement).focus();
602
+ }
603
+ this._announceSelectionChange();
573
604
  }
574
605
 
575
606
  onKeyDownSearch(e: KeyboardEvent) {
@@ -620,8 +651,9 @@ class UDExSelectBase extends UDExSearchableListBase {
620
651
 
621
652
  if (isDownAndPopoverClosed) {
622
653
  e.preventDefault();
654
+ // Opening establishes the active descendant and its visual highlight;
655
+ // DOM focus remains on the input for the combobox interaction pattern.
623
656
  this.openDropdown();
624
- this._activateSelectedOrFirstItem();
625
657
  return;
626
658
  }
627
659
 
@@ -634,9 +666,9 @@ class UDExSelectBase extends UDExSearchableListBase {
634
666
  const nextIndex = this._skipNonInteractive(items, raw, lastIndex, "down");
635
667
  this._navigateToIndex(items, nextIndex);
636
668
  } else {
637
- this._activateFirstItem();
669
+ this._activateSelectedOrFirstItem();
638
670
  // Also update _selectedOption so the input reflects the active item.
639
- const activeIdx = (items[0]?.nonInteractive && !items[0]?.collapsible) ? 1 : 0;
671
+ const activeIdx = this._activeDescendantItem ? items.indexOf(this._activeDescendantItem) : firstIndex;
640
672
  this._selectedOption = items[activeIdx].label;
641
673
  if (this.showImageFlags) {
642
674
  this.handleImagePosition(items, activeIdx);
@@ -685,7 +717,14 @@ class UDExSelectBase extends UDExSearchableListBase {
685
717
  }
686
718
  // Group header: fire header-press (same event the click handler fires) so
687
719
  // handleHeaderPress → onHeaderPress → handleGroupHeaderSelection runs.
688
- activeItem.fireDecoratorEvent("header-press", { item: activeItem });
720
+ // List's legacy intersection type omits SelectAll although it is a
721
+ // navigable group. Narrow using its explicit discriminator.
722
+ const selectAllItem = activeItem as unknown as UDExListSelectAll;
723
+ if (selectAllItem.isSelectAllHeader) {
724
+ selectAllItem.fireDecoratorEvent("select-all", { item: activeItem });
725
+ } else {
726
+ activeItem.fireDecoratorEvent("header-press", { item: activeItem });
727
+ }
689
728
  } else {
690
729
  // Leaf item: fire item-press so the list handles selection consistently.
691
730
  // Do NOT toggle .selected directly — handleItemClick (called via onItemPress)
@@ -720,7 +759,7 @@ class UDExSelectBase extends UDExSearchableListBase {
720
759
  }
721
760
 
722
761
  // Sync _selectedOption display for the first item (used when popover just opened via click).
723
- if (!this._activeDescendantItem && hasItems) {
762
+ if (popoverOpened && !this._activeDescendantItem && hasItems) {
724
763
  this._selectedOption = items[firstIndex].label;
725
764
  }
726
765
  }
@@ -742,11 +781,10 @@ class UDExSelectBase extends UDExSearchableListBase {
742
781
 
743
782
  override onSearch(value: string): void {
744
783
  super.onSearch(value);
745
- // Route search result count into the shared live region so SelectBox
746
- // only needs one aria-live span (no separate polite span in the template).
747
- if (this._accSearchResultInfo) {
748
- this._liveRegionText = this._accSearchResultInfo;
749
- }
784
+ // Filtering may remove the active item. Announce only the result count until
785
+ // the user navigates to an item in the updated list.
786
+ this._setActiveDescendant(null);
787
+ this._liveRegionText = this._accSearchResultInfo ?? "";
750
788
  }
751
789
 
752
790
  handleDirection() {
@@ -767,9 +805,7 @@ class UDExSelectBase extends UDExSearchableListBase {
767
805
  }
768
806
 
769
807
  handleDropdownOpen() {
770
- // Clear first so the live-region mutation fires even if text is unchanged.
771
- this._liveRegionText = "";
772
- // Defer scroll and announcement until rendering settles.
808
+ // Defer scrolling until rendering settles.
773
809
  // Calling _handleDropdownScroll synchronously causes getBoundingClientRect
774
810
  // to read mid-transition positions (e.g. the max-height animation on
775
811
  // collapsible group headers), producing an incorrect scroll offset.
@@ -779,67 +815,25 @@ class UDExSelectBase extends UDExSearchableListBase {
779
815
  this._expandCollapsedGroupsWithSelection();
780
816
  return renderFinished();
781
817
  }).then(() => {
782
- if (!this._activeDescendantItem) {
783
- this._activateSelectedOrFirstItem();
818
+ // The popup may have closed while its opening render was pending.
819
+ if (!this._open) {
820
+ return;
821
+ }
822
+ if (!this._activeDescendantItem && !this._shouldFilterItems) {
823
+ const activeItem = this._activateSelectedOrFirstItem();
824
+ // JAWS can miss the input's native expanded change when opening also
825
+ // establishes an active descendant. Retain the popup fallback unless an
826
+ // expanded group already supplies native "open"/"expanded" feedback.
827
+ // Never repeat the host's hierarchy or state after the native usage hint.
828
+ this._liveRegionText = activeItem?.getAttribute("aria-expanded") === "true"
829
+ ? "" : translate(UDExSelectBase, EXPANDED);
784
830
  }
785
831
  this._handleDropdownScroll();
786
- this._announceCurrentOrFirst();
787
832
  }).catch(() => {});
788
833
 
789
834
  this.fireEventDropdownOpen();
790
835
  }
791
836
 
792
- /**
793
- * Announces the currently active descendant item (if set), or the first
794
- * navigable item as a fallback. Used on open and after state changes.
795
- */
796
- _announceCurrentOrFirst(): void {
797
- const items = this._list?.getKeyboardNavigationItems();
798
- if (!items?.length) { return; }
799
- const item = this._activeDescendantItem ?? items.find(i => !i.nonInteractive || i.collapsible) ?? items[0];
800
- if (!item) { return; }
801
- const label = cleanLabel(item.label ?? "");
802
- const stateParts = this._itemStateLabels(item);
803
- const posText = this._treePositionText(item);
804
- this._liveRegionText = [label, posText, ...stateParts].filter(Boolean).join(", ");
805
- }
806
-
807
- /**
808
- * Returns the positional announcement text for an item, tree-aware when the
809
- * list has groups. Matches the JAWS reading pattern of FilterMenu:
810
- * group header → "level 0, X of Y" (Y = total navigable groups)
811
- * group child → "level 1, X of Y" (Y = siblings in that group)
812
- * flat item → "X of Y" (Y = total items, no level prefix)
813
- */
814
- _treePositionText(item: UDExListItemBase): string {
815
- if (!this.isTreeStructure) {
816
- const items = this._list?.getKeyboardNavigationItems() ?? [];
817
- const pos = items.indexOf(item);
818
- return pos >= 0 ? `${pos + 1} of ${items.length}` : "";
819
- }
820
-
821
- if (item.isGroup) {
822
- // Position among navigable group headers.
823
- const groups = (this._list?.getKeyboardNavigationItems() ?? []).filter(i => i.isGroup);
824
- const pos = groups.indexOf(item);
825
- return pos >= 0 ? `level 0, ${pos + 1} of ${groups.length}` : "level 0";
826
- }
827
-
828
- // Child item — find parent group and count siblings visible in navigation.
829
- const parentGroup = item.parentElement as UDExListItemBase | null;
830
- if (parentGroup?.isGroup) {
831
- const navItems = this._list?.getKeyboardNavigationItems() ?? [];
832
- const siblings = navItems.filter(i => !i.isGroup && i.parentElement === parentGroup);
833
- const pos = siblings.indexOf(item);
834
- return pos >= 0 ? `level 1, ${pos + 1} of ${siblings.length}` : "level 1";
835
- }
836
-
837
- // Fallback: flat position.
838
- const all = this._list?.getKeyboardNavigationItems() ?? [];
839
- const pos = all.indexOf(item);
840
- return pos >= 0 ? `${pos + 1} of ${all.length}` : "";
841
- }
842
-
843
837
  fireEventDropdownBeforeOClose() {
844
838
  this.fireDecoratorEvent("before-close");
845
839
  }
@@ -876,10 +870,21 @@ class UDExSelectBase extends UDExSearchableListBase {
876
870
  }
877
871
 
878
872
  openDropdown() {
873
+ if (this._popover.open) {
874
+ return;
875
+ }
876
+ this._pendingSelectionAnnouncement = "";
877
+ // Typing computes its result count before opening; preserve that status.
878
+ if (!this._shouldFilterItems) {
879
+ this._liveRegionText = "";
880
+ }
879
881
  this._popover.opener = this._trigger;
880
- this._popover.open = true;
881
882
  this._open = true;
882
- this._navigating = true;
883
+ this._navigating = false;
884
+ // Expose native state immediately. handleDropdownOpen supplements it after
885
+ // rendering because JAWS may miss this change on the first opening.
886
+ (this._search as HTMLElement).setAttribute("aria-expanded", "true");
887
+ this._popover.open = true;
883
888
  this._focused = false;
884
889
  }
885
890
 
@@ -888,6 +893,7 @@ class UDExSelectBase extends UDExSearchableListBase {
888
893
  this._open = false;
889
894
  this._popover.open = false;
890
895
  this._navigating = false;
896
+ (this._search as HTMLElement).setAttribute("aria-expanded", "false");
891
897
  }
892
898
  }
893
899
 
@@ -954,16 +960,12 @@ class UDExSelectBase extends UDExSearchableListBase {
954
960
  if (!header) { return false; }
955
961
 
956
962
  // Left only collapses an expanded group; Right only expands a collapsed one.
957
- if (collapse && !header.collapsed) {
958
- header.collapsed = true;
959
- this._list.setCollapsedItems(true, header);
960
- renderFinished().then(() => this._announceCurrentOrFirst()).catch(() => {});
961
- return true;
962
- }
963
- if (!collapse && header.collapsed) {
964
- header.collapsed = false;
965
- this._list.setCollapsedItems(false, header);
966
- renderFinished().then(() => this._announceCurrentOrFirst()).catch(() => {});
963
+ if (header.collapsed !== collapse) {
964
+ header.collapsed = collapse;
965
+ this._list.setCollapsedItems(collapse, header);
966
+ // Synchronize the slotted source header just like a chevron click;
967
+ // UI5 template listeners subscribe to the prefixed decorator event.
968
+ header.fireDecoratorEvent("accordion-icon-click", { collapsed: collapse });
967
969
  return true;
968
970
  }
969
971
  // Target is a collapsible header but already in the requested state — still consume
@@ -1114,50 +1116,26 @@ class UDExSelectBase extends UDExSearchableListBase {
1114
1116
  findAndFocus(this);
1115
1117
  }
1116
1118
 
1117
- /**
1118
- * Builds the state portion of the live region announcement for a navigation item.
1119
- * Returns an array of state strings (e.g. ["collapsed", "Checked"]) to be joined
1120
- * with the label and position. Handles:
1121
- * - collapsible group headers: expanded / collapsed
1122
- * - MultiSelect: Checked / Unchecked / Indeterminate
1123
- * - SingleSelect (tree): Selected / Unselected
1124
- * - disabled: Disabled
1125
- */
1126
- _itemStateLabels(item: UDExListItemBase): string[] {
1127
- const parts: string[] = [];
1128
-
1129
- if (item.collapsible) {
1130
- parts.push(translate(UDExSearchableListBase, item.expanded ? EXPANDED : COLLAPSED));
1131
- }
1132
-
1133
- if (item.disabled) {
1134
- parts.push(translate(UDExSearchableListBase, DISABLED));
1135
- } else if (item.modeMultiSelect || (item.isGroup && this.modeMultiSelect)) {
1136
- if (item.indeterminate) {
1137
- parts.push(translate(UDExSearchableListBase, INDETERMINATE));
1138
- } else {
1139
- parts.push(translate(UDExSearchableListBase, item.selected ? SELECTED : UNSELECTED));
1140
- }
1141
- } else if (this.isTreeStructure && item.selected) {
1142
- // SingleSelect tree: only announce "Selected" when the item is actually selected.
1143
- parts.push(translate(UDExSearchableListBase, SELECTED));
1144
- }
1145
-
1146
- return parts;
1147
- }
1148
-
1149
1119
  get ariaDescribedbyText(): string {
1120
+ const descriptions = [this.supportingText];
1121
+ // Updating the token-count description while an item is active makes JAWS
1122
+ // reread the input instead of the item whose selection just changed.
1123
+ if (this._navigating) {
1124
+ return descriptions.filter(Boolean).join(" ");
1125
+ }
1150
1126
  if (this.modeSingleSelect) {
1151
- return this._navigating ? "" : this._selectedOption;
1127
+ descriptions.push(this._selectedOption);
1128
+ return descriptions.filter(Boolean).join(" ");
1152
1129
  }
1153
1130
  const tags = this.selectedItems.filter(item => !item.isGroup);
1154
1131
  // Tokenizer.i18nBundle may not be loaded yet on direct page load.
1155
1132
  // Return empty string until the bundle is available; the component re-renders
1156
1133
  // once i18n is ready and will pick up the correct text.
1157
1134
  if (!Tokenizer.i18nBundle) {
1158
- return "";
1135
+ return descriptions.filter(Boolean).join(" ");
1159
1136
  }
1160
- return getTokensCountText(tags.length);
1137
+ descriptions.push(getTokensCountText(tags.length));
1138
+ return descriptions.filter(Boolean).join(" ");
1161
1139
  }
1162
1140
 
1163
1141
  get trigger(): HTMLElement {
@@ -1198,6 +1176,10 @@ class UDExSelectBase extends UDExSearchableListBase {
1198
1176
  };
1199
1177
  }
1200
1178
 
1179
+ override get listAccessibleName(): string {
1180
+ return this.accInfo.ariaLabel;
1181
+ }
1182
+
1201
1183
  get popoverId(): string {
1202
1184
  return `${this._id}_${this._dropdownClass}`;
1203
1185
  }
@@ -1215,7 +1197,11 @@ class UDExSelectBase extends UDExSearchableListBase {
1215
1197
  }
1216
1198
 
1217
1199
  override get isTreeStructure(): boolean {
1218
- return this._filteredItems.some(e => e.isGroup);
1200
+ // Options flatten their descendants in the accessibility tree. Action
1201
+ // buttons therefore need treeitems even in an otherwise flat popup, so
1202
+ // their own names, roles and keyboard interaction remain available.
1203
+ return this._filteredItems.some(({ isGroup, item }) => isGroup
1204
+ || !!item.querySelector?.("[slot='firstIcon'], [slot='secondIcon']"));
1219
1205
  }
1220
1206
 
1221
1207
  get hideDropdownSearch(): boolean {
package/src/SelectBox.ts CHANGED
@@ -182,10 +182,16 @@ class UDExSelectBox extends UDExSelectBase {
182
182
 
183
183
  handleSelectAll(e:CustomEvent) {
184
184
  this.onSelectAllHeaderPress(e);
185
+ this._activatePressedHeader(e);
185
186
  }
186
187
 
187
188
  handleHeaderPress(e:CustomEvent) {
188
189
  this.onHeaderPress(e);
190
+ this._activatePressedHeader(e);
191
+ }
192
+
193
+ /** Keep selection feedback attached to the header, without refocusing the input. @private */
194
+ _activatePressedHeader(e: CustomEvent): void {
189
195
  // After the click, find the rendered nav item for this header and set it as
190
196
  // the active descendant so the outline ring is visible. Then return DOM focus
191
197
  // to the input to prevent a double ring if the user navigates with arrows.
@@ -194,18 +200,28 @@ class UDExSelectBox extends UDExSelectBase {
194
200
  const renderedItem = navItems?.find(
195
201
  i => (i.getAttribute("data-token-id") ?? i._id) === tokenId,
196
202
  );
197
- if (renderedItem) {
203
+ if (renderedItem && renderedItem !== this._activeDescendantItem) {
198
204
  this._setActiveDescendant(renderedItem);
199
205
  }
200
- (this._search as HTMLElement).focus();
201
- // Re-announce with updated checked/indeterminate state after the render cycle.
202
- renderFinished().then(() => this._announceCurrentOrFirst()).catch(() => {});
206
+ if (this.shadowRoot?.activeElement !== this._search) {
207
+ (this._search as HTMLElement).focus();
208
+ }
209
+ this._announceSelectionChange();
203
210
  }
204
211
 
205
212
  handleItemPress(e:CustomEvent) {
206
213
  this.handleItemSelection(e);
207
214
  }
208
215
 
216
+ handleDropdownClick(e: MouseEvent) {
217
+ const header = e.target as UDExListItemBase;
218
+ // Host-ARIA header rows are not focusable, so activate them directly
219
+ // instead of relying on the input's focusout handler.
220
+ if (header.isGroup && header.collapsible && !header.modeMultiSelect && !header.disabled) {
221
+ this._setActiveDescendant(header);
222
+ }
223
+ }
224
+
209
225
  handlerShowMoreItems(e: CustomEvent) {
210
226
  if (!this.displayonly) {
211
227
  this.showMoreItems(e);
@@ -303,9 +319,7 @@ class UDExSelectBox extends UDExSelectBase {
303
319
  this._selectedOption = "";
304
320
  }
305
321
 
306
- this._setActiveDescendant(null);
307
- this._open = false;
308
- this.fireEventDropdownClose();
322
+ this._finishDropdownClose();
309
323
  }
310
324
 
311
325
  async handleRemoveTag(e: CustomEvent | null, tag?: UI5Element) {
@@ -23,13 +23,11 @@ export default function SelectBoxTemplate(this: UDExSelectBox) {
23
23
  {...(this.isDisabled ? { disabled: "" } : {})}
24
24
  {...(this._open ? { open: "" } : {})}>
25
25
  {this.label && (
26
- <>
27
- <label for="search-input" class={this.labelClass}>
28
- {this.label}{this.required && " * "}
29
- </label>
30
- <span class="hidden" id={`${this._id}-aria-describedby`}>{this.ariaDescribedbyText}</span>
31
- </>
26
+ <label for="search-input" class={this.labelClass}>
27
+ {this.label}{this.required && " * "}
28
+ </label>
32
29
  )}
30
+ <span class="hidden" id={`${this._id}-aria-describedby`}>{this.ariaDescribedbyText}</span>
33
31
  {this.showImageFlags && this.countryFlag}
34
32
  <div class="udex-text-field__holder">
35
33
  <input
@@ -51,7 +49,7 @@ export default function SelectBoxTemplate(this: UDExSelectBox) {
51
49
  aria-haspopup={this.listboxRole}
52
50
  aria-controls={this.listAriaControlsId}
53
51
  aria-expanded={this._open}
54
- aria-activedescendant={this._activeDescendantItem ? this._activeDescendantItem._id : undefined}
52
+ aria-activedescendant={this._activeDescendantItem ? this._activeDescendantItem.id : undefined}
55
53
  aria-autocomplete={this._ariaAutoComplete}
56
54
  aria-describedby={`${this._id}-aria-describedby`}
57
55
  autocomplete="off"
@@ -81,6 +79,7 @@ export default function SelectBoxTemplate(this: UDExSelectBox) {
81
79
  accessibleRole={PopupAccessibleRole.None}
82
80
  allow-target-overlap={this.allowTargetOverlap}
83
81
  onKeyDown={this.handleKeyDownDropdown}
82
+ onClick={this.handleDropdownClick}
84
83
  {...({
85
84
  onSelectAll: this.handleSelectAll,
86
85
  onItemPress: this.handleItemPress,
@@ -138,14 +137,16 @@ function renderTagGroup(this: UDExSelectBox) {
138
137
  <UDExTag
139
138
  key={index}
140
139
  text={cleanLabel(item.label)}
141
- id={item._id}
140
+ id={`${this._id}-tag-${item._id}`}
141
+ data-id={item._id}
142
142
  icon="decline">
143
143
  </UDExTag>
144
144
  ) : (
145
145
  <UDExTag
146
146
  key={index}
147
147
  text={`${item.rating} ${this.startsText}`}
148
- id={item._id}
148
+ id={`${this._id}-tag-${item._id}`}
149
+ data-id={item._id}
149
150
  icon="decline">
150
151
  </UDExTag>
151
152
  )
@@ -6,6 +6,16 @@ import SideNavigation from "@ui5/webcomponents-fiori/dist/SideNavigation.js";
6
6
  // Styles
7
7
  import SideNavigationCss from "./generated/themes/SideNavigation.css.js";
8
8
 
9
+ export enum UDExSideNavigationVariant {
10
+ Full = "Full",
11
+ Content = "Content",
12
+ }
13
+
14
+ export enum UDExSideNavigationPlacement {
15
+ Left = "Left",
16
+ Right = "Right",
17
+ }
18
+
9
19
  /**
10
20
  * @class
11
21
  *
@@ -38,6 +48,31 @@ class UDExSideNavigation extends SideNavigation {
38
48
  */
39
49
  @property({ type: Boolean })
40
50
  isFixedInPlace!: boolean;
51
+
52
+ /**
53
+ * Defines the variant of the component.
54
+ *
55
+ * @default "Full"
56
+ * @public
57
+ */
58
+ @property()
59
+ variant: `${UDExSideNavigationVariant}` = UDExSideNavigationVariant.Full;
60
+
61
+ /**
62
+ * Defines which side the navigation panel is on.
63
+ *
64
+ * @default "Left"
65
+ * @public
66
+ */
67
+ @property()
68
+ placement: `${UDExSideNavigationPlacement}` = UDExSideNavigationPlacement.Left;
69
+
70
+ onBeforeRendering() {
71
+ super.onBeforeRendering();
72
+ this.querySelectorAll("[udex-side-navigation-item], [udex-side-navigation-sub-item]").forEach(item => {
73
+ item.setAttribute("variant", this.variant);
74
+ });
75
+ }
41
76
  }
42
77
 
43
78
  UDExSideNavigation.define();