@wordpress/components 28.8.4 → 28.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (329) hide show
  1. package/CHANGELOG.md +26 -3
  2. package/build/autocomplete/index.js +4 -1
  3. package/build/autocomplete/index.js.map +1 -1
  4. package/build/border-box-control/border-box-control/component.js +3 -14
  5. package/build/border-box-control/border-box-control/component.js.map +1 -1
  6. package/build/border-control/border-control/component.js +1 -2
  7. package/build/border-control/border-control/component.js.map +1 -1
  8. package/build/border-control/border-control-dropdown/component.js +2 -14
  9. package/build/border-control/border-control-dropdown/component.js.map +1 -1
  10. package/build/border-control/styles.js +13 -13
  11. package/build/border-control/styles.js.map +1 -1
  12. package/build/border-control/types.js.map +1 -1
  13. package/build/box-control/index.js +4 -4
  14. package/build/box-control/index.js.map +1 -1
  15. package/build/box-control/types.js.map +1 -1
  16. package/build/composite/group-label.js +7 -1
  17. package/build/composite/group-label.js.map +1 -1
  18. package/build/composite/group.js +7 -1
  19. package/build/composite/group.js.map +1 -1
  20. package/build/composite/hover.js +8 -2
  21. package/build/composite/hover.js.map +1 -1
  22. package/build/composite/index.js +5 -1
  23. package/build/composite/index.js.map +1 -1
  24. package/build/composite/item.js +16 -1
  25. package/build/composite/item.js.map +1 -1
  26. package/build/composite/row.js +7 -1
  27. package/build/composite/row.js.map +1 -1
  28. package/build/composite/typeahead.js +8 -2
  29. package/build/composite/typeahead.js.map +1 -1
  30. package/build/date-time/date/index.js +4 -2
  31. package/build/date-time/date/index.js.map +1 -1
  32. package/build/index.js +36 -5
  33. package/build/index.js.map +1 -1
  34. package/build/navigator/index.js +128 -32
  35. package/build/navigator/index.js.map +1 -1
  36. package/build/navigator/legacy.js +179 -0
  37. package/build/navigator/legacy.js.map +1 -0
  38. package/build/navigator/{navigator-provider → navigator}/component.js +5 -40
  39. package/build/navigator/navigator/component.js.map +1 -0
  40. package/build/navigator/navigator-back-button/component.js +2 -38
  41. package/build/navigator/navigator-back-button/component.js.map +1 -1
  42. package/build/navigator/navigator-back-button/hook.js +1 -1
  43. package/build/navigator/navigator-back-button/hook.js.map +1 -1
  44. package/build/navigator/navigator-button/component.js +2 -37
  45. package/build/navigator/navigator-button/component.js.map +1 -1
  46. package/build/navigator/navigator-button/hook.js +1 -1
  47. package/build/navigator/navigator-button/hook.js.map +1 -1
  48. package/build/navigator/navigator-screen/component.js +40 -62
  49. package/build/navigator/navigator-screen/component.js.map +1 -1
  50. package/build/navigator/navigator-screen/use-screen-animate-presence.js +114 -0
  51. package/build/navigator/navigator-screen/use-screen-animate-presence.js.map +1 -0
  52. package/build/navigator/navigator-to-parent-button/component.js +3 -7
  53. package/build/navigator/navigator-to-parent-button/component.js.map +1 -1
  54. package/build/navigator/styles.js +78 -35
  55. package/build/navigator/styles.js.map +1 -1
  56. package/build/navigator/types.js.map +1 -1
  57. package/build/navigator/use-navigator.js +4 -1
  58. package/build/navigator/use-navigator.js.map +1 -1
  59. package/build/search-control/index.js +5 -2
  60. package/build/search-control/index.js.map +1 -1
  61. package/build/tabs/styles.js +3 -3
  62. package/build/tabs/styles.js.map +1 -1
  63. package/build/tabs/tablist.js +61 -28
  64. package/build/tabs/tablist.js.map +1 -1
  65. package/build/tabs/use-track-overflow.js +73 -0
  66. package/build/tabs/use-track-overflow.js.map +1 -0
  67. package/build/toggle-group-control/toggle-group-control/as-button-group.js +4 -2
  68. package/build/toggle-group-control/toggle-group-control/as-button-group.js.map +1 -1
  69. package/build/toggle-group-control/toggle-group-control/as-radio-group.js +6 -2
  70. package/build/toggle-group-control/toggle-group-control/as-radio-group.js.map +1 -1
  71. package/build/toggle-group-control/toggle-group-control/component.js +73 -8
  72. package/build/toggle-group-control/toggle-group-control/component.js.map +1 -1
  73. package/build/toggle-group-control/toggle-group-control/styles.js +7 -7
  74. package/build/toggle-group-control/toggle-group-control/styles.js.map +1 -1
  75. package/build/toggle-group-control/toggle-group-control-option-base/component.js +10 -19
  76. package/build/toggle-group-control/toggle-group-control-option-base/component.js.map +1 -1
  77. package/build/toggle-group-control/toggle-group-control-option-base/styles.js +8 -9
  78. package/build/toggle-group-control/toggle-group-control-option-base/styles.js.map +1 -1
  79. package/build/toggle-group-control/types.js.map +1 -1
  80. package/build/utils/element-rect.js +22 -13
  81. package/build/utils/element-rect.js.map +1 -1
  82. package/build/utils/hooks/use-on-value-update.js +3 -7
  83. package/build/utils/hooks/use-on-value-update.js.map +1 -1
  84. package/build-module/autocomplete/index.js +4 -1
  85. package/build-module/autocomplete/index.js.map +1 -1
  86. package/build-module/border-box-control/border-box-control/component.js +3 -14
  87. package/build-module/border-box-control/border-box-control/component.js.map +1 -1
  88. package/build-module/border-control/border-control/component.js +1 -2
  89. package/build-module/border-control/border-control/component.js.map +1 -1
  90. package/build-module/border-control/border-control-dropdown/component.js +2 -14
  91. package/build-module/border-control/border-control-dropdown/component.js.map +1 -1
  92. package/build-module/border-control/styles.js +13 -13
  93. package/build-module/border-control/styles.js.map +1 -1
  94. package/build-module/border-control/types.js.map +1 -1
  95. package/build-module/box-control/index.js +4 -4
  96. package/build-module/box-control/index.js.map +1 -1
  97. package/build-module/box-control/types.js.map +1 -1
  98. package/build-module/composite/group-label.js +7 -1
  99. package/build-module/composite/group-label.js.map +1 -1
  100. package/build-module/composite/group.js +7 -1
  101. package/build-module/composite/group.js.map +1 -1
  102. package/build-module/composite/hover.js +8 -2
  103. package/build-module/composite/hover.js.map +1 -1
  104. package/build-module/composite/index.js +5 -1
  105. package/build-module/composite/index.js.map +1 -1
  106. package/build-module/composite/item.js +16 -1
  107. package/build-module/composite/item.js.map +1 -1
  108. package/build-module/composite/row.js +7 -1
  109. package/build-module/composite/row.js.map +1 -1
  110. package/build-module/composite/typeahead.js +8 -2
  111. package/build-module/composite/typeahead.js.map +1 -1
  112. package/build-module/date-time/date/index.js +4 -2
  113. package/build-module/date-time/date/index.js.map +1 -1
  114. package/build-module/index.js +14 -4
  115. package/build-module/index.js.map +1 -1
  116. package/build-module/navigator/index.js +130 -5
  117. package/build-module/navigator/index.js.map +1 -1
  118. package/build-module/navigator/legacy.js +167 -0
  119. package/build-module/navigator/legacy.js.map +1 -0
  120. package/build-module/navigator/{navigator-provider → navigator}/component.js +4 -39
  121. package/build-module/navigator/navigator/component.js.map +1 -0
  122. package/build-module/navigator/navigator-back-button/component.js +1 -37
  123. package/build-module/navigator/navigator-back-button/component.js.map +1 -1
  124. package/build-module/navigator/navigator-back-button/hook.js +1 -1
  125. package/build-module/navigator/navigator-back-button/hook.js.map +1 -1
  126. package/build-module/navigator/navigator-button/component.js +1 -36
  127. package/build-module/navigator/navigator-button/component.js.map +1 -1
  128. package/build-module/navigator/navigator-button/hook.js +1 -1
  129. package/build-module/navigator/navigator-button/hook.js.map +1 -1
  130. package/build-module/navigator/navigator-screen/component.js +39 -61
  131. package/build-module/navigator/navigator-screen/component.js.map +1 -1
  132. package/build-module/navigator/navigator-screen/use-screen-animate-presence.js +106 -0
  133. package/build-module/navigator/navigator-screen/use-screen-animate-presence.js.map +1 -0
  134. package/build-module/navigator/navigator-to-parent-button/component.js +2 -6
  135. package/build-module/navigator/navigator-to-parent-button/component.js.map +1 -1
  136. package/build-module/navigator/styles.js +77 -33
  137. package/build-module/navigator/styles.js.map +1 -1
  138. package/build-module/navigator/types.js.map +1 -1
  139. package/build-module/navigator/use-navigator.js +4 -1
  140. package/build-module/navigator/use-navigator.js.map +1 -1
  141. package/build-module/search-control/index.js +5 -2
  142. package/build-module/search-control/index.js.map +1 -1
  143. package/build-module/tabs/styles.js +3 -3
  144. package/build-module/tabs/styles.js.map +1 -1
  145. package/build-module/tabs/tablist.js +62 -29
  146. package/build-module/tabs/tablist.js.map +1 -1
  147. package/build-module/tabs/use-track-overflow.js +67 -0
  148. package/build-module/tabs/use-track-overflow.js.map +1 -0
  149. package/build-module/toggle-group-control/toggle-group-control/as-button-group.js +4 -2
  150. package/build-module/toggle-group-control/toggle-group-control/as-button-group.js.map +1 -1
  151. package/build-module/toggle-group-control/toggle-group-control/as-radio-group.js +6 -2
  152. package/build-module/toggle-group-control/toggle-group-control/as-radio-group.js.map +1 -1
  153. package/build-module/toggle-group-control/toggle-group-control/component.js +76 -10
  154. package/build-module/toggle-group-control/toggle-group-control/component.js.map +1 -1
  155. package/build-module/toggle-group-control/toggle-group-control/styles.js +7 -7
  156. package/build-module/toggle-group-control/toggle-group-control/styles.js.map +1 -1
  157. package/build-module/toggle-group-control/toggle-group-control-option-base/component.js +12 -22
  158. package/build-module/toggle-group-control/toggle-group-control-option-base/component.js.map +1 -1
  159. package/build-module/toggle-group-control/toggle-group-control-option-base/styles.js +7 -8
  160. package/build-module/toggle-group-control/toggle-group-control-option-base/styles.js.map +1 -1
  161. package/build-module/toggle-group-control/types.js.map +1 -1
  162. package/build-module/utils/element-rect.js +22 -12
  163. package/build-module/utils/element-rect.js.map +1 -1
  164. package/build-module/utils/hooks/use-on-value-update.js +3 -6
  165. package/build-module/utils/hooks/use-on-value-update.js.map +1 -1
  166. package/build-style/style-rtl.css +26 -13
  167. package/build-style/style.css +26 -13
  168. package/build-types/autocomplete/index.d.ts.map +1 -1
  169. package/build-types/border-box-control/border-box-control/component.d.ts +5 -15
  170. package/build-types/border-box-control/border-box-control/component.d.ts.map +1 -1
  171. package/build-types/border-box-control/border-box-control-split-controls/component.d.ts +2 -1
  172. package/build-types/border-box-control/border-box-control-split-controls/component.d.ts.map +1 -1
  173. package/build-types/border-box-control/stories/index.story.d.ts +3 -2
  174. package/build-types/border-box-control/stories/index.story.d.ts.map +1 -1
  175. package/build-types/border-control/border-control/component.d.ts +3 -2
  176. package/build-types/border-control/border-control/component.d.ts.map +1 -1
  177. package/build-types/border-control/border-control-dropdown/component.d.ts +2 -1
  178. package/build-types/border-control/border-control-dropdown/component.d.ts.map +1 -1
  179. package/build-types/border-control/border-control-style-picker/component.d.ts.map +1 -1
  180. package/build-types/border-control/stories/index.story.d.ts +15 -30
  181. package/build-types/border-control/stories/index.story.d.ts.map +1 -1
  182. package/build-types/border-control/styles.d.ts.map +1 -1
  183. package/build-types/border-control/types.d.ts +12 -7
  184. package/build-types/border-control/types.d.ts.map +1 -1
  185. package/build-types/box-control/index.d.ts +4 -4
  186. package/build-types/box-control/stories/index.story.d.ts.map +1 -1
  187. package/build-types/box-control/types.d.ts +3 -3
  188. package/build-types/composite/group-label.d.ts.map +1 -1
  189. package/build-types/composite/index.d.ts.map +1 -1
  190. package/build-types/composite/item.d.ts.map +1 -1
  191. package/build-types/composite/stories/index.story.d.ts +22 -0
  192. package/build-types/composite/stories/index.story.d.ts.map +1 -1
  193. package/build-types/composite/test/index.d.ts +2 -0
  194. package/build-types/composite/test/index.d.ts.map +1 -0
  195. package/build-types/date-time/date/index.d.ts.map +1 -1
  196. package/build-types/dropdown/stories/index.story.d.ts.map +1 -1
  197. package/build-types/dropdown-menu/stories/index.story.d.ts.map +1 -1
  198. package/build-types/index.d.ts +23 -4
  199. package/build-types/index.d.ts.map +1 -1
  200. package/build-types/navigator/index.d.ts +171 -5
  201. package/build-types/navigator/index.d.ts.map +1 -1
  202. package/build-types/navigator/legacy.d.ts +226 -0
  203. package/build-types/navigator/legacy.d.ts.map +1 -0
  204. package/build-types/navigator/navigator/component.d.ts +3 -0
  205. package/build-types/navigator/navigator/component.d.ts.map +1 -0
  206. package/build-types/navigator/navigator-back-button/component.d.ts +0 -35
  207. package/build-types/navigator/navigator-back-button/component.d.ts.map +1 -1
  208. package/build-types/navigator/navigator-button/component.d.ts +0 -34
  209. package/build-types/navigator/navigator-button/component.d.ts.map +1 -1
  210. package/build-types/navigator/navigator-screen/component.d.ts +0 -35
  211. package/build-types/navigator/navigator-screen/component.d.ts.map +1 -1
  212. package/build-types/navigator/navigator-screen/use-screen-animate-presence.d.ts +16 -0
  213. package/build-types/navigator/navigator-screen/use-screen-animate-presence.d.ts.map +1 -0
  214. package/build-types/navigator/navigator-to-parent-button/component.d.ts +0 -4
  215. package/build-types/navigator/navigator-to-parent-button/component.d.ts.map +1 -1
  216. package/build-types/navigator/stories/index.story.d.ts +5 -5
  217. package/build-types/navigator/stories/index.story.d.ts.map +1 -1
  218. package/build-types/navigator/styles.d.ts +20 -7
  219. package/build-types/navigator/styles.d.ts.map +1 -1
  220. package/build-types/navigator/types.d.ts +19 -1
  221. package/build-types/navigator/types.d.ts.map +1 -1
  222. package/build-types/navigator/use-navigator.d.ts +4 -1
  223. package/build-types/navigator/use-navigator.d.ts.map +1 -1
  224. package/build-types/select-control/stories/index.story.d.ts +7 -0
  225. package/build-types/select-control/stories/index.story.d.ts.map +1 -1
  226. package/build-types/tabs/stories/index.story.d.ts +2 -1
  227. package/build-types/tabs/stories/index.story.d.ts.map +1 -1
  228. package/build-types/tabs/styles.d.ts.map +1 -1
  229. package/build-types/tabs/tablist.d.ts.map +1 -1
  230. package/build-types/tabs/use-track-overflow.d.ts +17 -0
  231. package/build-types/tabs/use-track-overflow.d.ts.map +1 -0
  232. package/build-types/toggle-group-control/toggle-group-control/as-button-group.d.ts +2 -2
  233. package/build-types/toggle-group-control/toggle-group-control/as-button-group.d.ts.map +1 -1
  234. package/build-types/toggle-group-control/toggle-group-control/as-radio-group.d.ts +2 -2
  235. package/build-types/toggle-group-control/toggle-group-control/as-radio-group.d.ts.map +1 -1
  236. package/build-types/toggle-group-control/toggle-group-control/component.d.ts.map +1 -1
  237. package/build-types/toggle-group-control/toggle-group-control/styles.d.ts.map +1 -1
  238. package/build-types/toggle-group-control/toggle-group-control-option-base/component.d.ts.map +1 -1
  239. package/build-types/toggle-group-control/toggle-group-control-option-base/styles.d.ts +0 -1
  240. package/build-types/toggle-group-control/toggle-group-control-option-base/styles.d.ts.map +1 -1
  241. package/build-types/toggle-group-control/types.d.ts +2 -1
  242. package/build-types/toggle-group-control/types.d.ts.map +1 -1
  243. package/build-types/utils/element-rect.d.ts +8 -0
  244. package/build-types/utils/element-rect.d.ts.map +1 -1
  245. package/build-types/utils/hooks/use-on-value-update.d.ts.map +1 -1
  246. package/package.json +19 -19
  247. package/src/autocomplete/index.tsx +4 -1
  248. package/src/border-box-control/border-box-control/README.md +22 -26
  249. package/src/border-box-control/border-box-control/component.tsx +3 -14
  250. package/src/border-box-control/stories/index.story.tsx +2 -1
  251. package/src/border-control/border-control/README.md +26 -36
  252. package/src/border-control/border-control/component.tsx +1 -2
  253. package/src/border-control/border-control-dropdown/component.tsx +1 -15
  254. package/src/border-control/stories/index.story.tsx +4 -10
  255. package/src/border-control/styles.ts +0 -1
  256. package/src/border-control/test/index.js +2 -15
  257. package/src/border-control/types.ts +12 -7
  258. package/src/box-control/README.md +9 -12
  259. package/src/box-control/index.tsx +4 -4
  260. package/src/box-control/stories/index.story.tsx +1 -1
  261. package/src/box-control/types.ts +3 -3
  262. package/src/composite/group-label.tsx +7 -5
  263. package/src/composite/group.tsx +7 -7
  264. package/src/composite/hover.tsx +7 -7
  265. package/src/composite/index.tsx +6 -1
  266. package/src/composite/item.tsx +19 -1
  267. package/src/composite/legacy/test/index.tsx +22 -21
  268. package/src/composite/row.tsx +7 -7
  269. package/src/composite/stories/index.story.tsx +42 -0
  270. package/src/composite/test/index.tsx +123 -0
  271. package/src/composite/typeahead.tsx +7 -7
  272. package/src/date-time/date/index.tsx +2 -0
  273. package/src/dropdown/stories/index.story.tsx +1 -0
  274. package/src/dropdown/style.scss +10 -13
  275. package/src/dropdown-menu/stories/index.story.tsx +3 -0
  276. package/src/index.ts +19 -1
  277. package/src/menu-group/style.scss +4 -1
  278. package/src/menu-items-choice/style.scss +2 -0
  279. package/src/navigator/README.md +176 -0
  280. package/src/navigator/index.tsx +131 -0
  281. package/src/navigator/legacy.ts +169 -0
  282. package/src/navigator/{navigator-provider → navigator}/component.tsx +6 -44
  283. package/src/navigator/navigator-back-button/component.tsx +1 -37
  284. package/src/navigator/navigator-back-button/hook.ts +1 -1
  285. package/src/navigator/navigator-button/component.tsx +1 -36
  286. package/src/navigator/navigator-button/hook.ts +1 -1
  287. package/src/navigator/navigator-screen/component.tsx +48 -76
  288. package/src/navigator/navigator-screen/use-screen-animate-presence.ts +177 -0
  289. package/src/navigator/navigator-to-parent-button/component.tsx +2 -7
  290. package/src/navigator/stories/index.story.tsx +55 -54
  291. package/src/navigator/styles.ts +112 -41
  292. package/src/navigator/test/index.tsx +47 -47
  293. package/src/navigator/types.ts +19 -1
  294. package/src/navigator/use-navigator.ts +4 -1
  295. package/src/search-control/index.tsx +2 -2
  296. package/src/select-control/stories/index.story.tsx +14 -1
  297. package/src/tabs/stories/index.story.tsx +106 -0
  298. package/src/tabs/styles.ts +54 -20
  299. package/src/tabs/tablist.tsx +60 -26
  300. package/src/tabs/use-track-overflow.ts +76 -0
  301. package/src/toggle-group-control/test/__snapshots__/index.tsx.snap +208 -44
  302. package/src/toggle-group-control/toggle-group-control/as-button-group.tsx +18 -10
  303. package/src/toggle-group-control/toggle-group-control/as-radio-group.tsx +19 -9
  304. package/src/toggle-group-control/toggle-group-control/component.tsx +114 -6
  305. package/src/toggle-group-control/toggle-group-control/styles.ts +41 -0
  306. package/src/toggle-group-control/toggle-group-control-option-base/component.tsx +10 -27
  307. package/src/toggle-group-control/toggle-group-control-option-base/styles.ts +0 -11
  308. package/src/toggle-group-control/types.ts +3 -1
  309. package/src/tools-panel/tools-panel/README.md +10 -10
  310. package/src/utils/element-rect.ts +32 -15
  311. package/src/utils/hooks/use-on-value-update.ts +3 -6
  312. package/tsconfig.tsbuildinfo +1 -1
  313. package/build/navigator/navigator-provider/component.js.map +0 -1
  314. package/build/utils/hooks/use-event.js +0 -41
  315. package/build/utils/hooks/use-event.js.map +0 -1
  316. package/build-module/navigator/navigator-provider/component.js.map +0 -1
  317. package/build-module/utils/hooks/use-event.js +0 -35
  318. package/build-module/utils/hooks/use-event.js.map +0 -1
  319. package/build-types/navigator/navigator-provider/component.d.ts +0 -37
  320. package/build-types/navigator/navigator-provider/component.d.ts.map +0 -1
  321. package/build-types/utils/hooks/use-event.d.ts +0 -20
  322. package/build-types/utils/hooks/use-event.d.ts.map +0 -1
  323. package/src/navigator/index.ts +0 -6
  324. package/src/navigator/navigator-back-button/README.md +0 -15
  325. package/src/navigator/navigator-button/README.md +0 -38
  326. package/src/navigator/navigator-provider/README.md +0 -94
  327. package/src/navigator/navigator-screen/README.md +0 -33
  328. package/src/navigator/navigator-to-parent-button/README.md +0 -17
  329. package/src/utils/hooks/use-event.ts +0 -38
@@ -16,32 +16,40 @@ export const TabListWrapper = styled.div`
16
16
  align-items: stretch;
17
17
  flex-direction: row;
18
18
  text-align: center;
19
+ overflow-x: auto;
19
20
 
20
21
  &[aria-orientation='vertical'] {
21
22
  flex-direction: column;
22
23
  text-align: start;
23
24
  }
24
25
 
25
- @media not ( prefers-reduced-motion ) {
26
- &.is-animation-enabled::after {
27
- transition-property: transform;
28
- transition-duration: 0.2s;
29
- transition-timing-function: ease-out;
30
- }
26
+ :where( [aria-orientation='horizontal'] ) {
27
+ width: fit-content;
31
28
  }
29
+
32
30
  --direction-factor: 1;
33
- --direction-origin-x: left;
31
+ --direction-start: left;
32
+ --direction-end: right;
34
33
  --indicator-start: var( --indicator-left );
35
34
  &:dir( rtl ) {
36
35
  --direction-factor: -1;
37
- --direction-origin-x: right;
36
+ --direction-start: right;
37
+ --direction-end: left;
38
38
  --indicator-start: var( --indicator-right );
39
39
  }
40
- &::after {
40
+
41
+ @media not ( prefers-reduced-motion ) {
42
+ &.is-animation-enabled::before {
43
+ transition-property: transform;
44
+ transition-duration: 0.2s;
45
+ transition-timing-function: ease-out;
46
+ }
47
+ }
48
+ &::before {
41
49
  content: '';
42
50
  position: absolute;
43
51
  pointer-events: none;
44
- transform-origin: var( --direction-origin-x ) top;
52
+ transform-origin: var( --direction-start ) top;
45
53
 
46
54
  // Windows high contrast mode.
47
55
  outline: 2px solid transparent;
@@ -52,7 +60,31 @@ export const TabListWrapper = styled.div`
52
60
  when scaling in the transform, see: https://stackoverflow.com/a/52159123 */
53
61
  --antialiasing-factor: 100;
54
62
  &:not( [aria-orientation='vertical'] ) {
55
- &::after {
63
+ --fade-width: 4rem;
64
+ --fade-gradient-base: transparent 0%, black var( --fade-width );
65
+ --fade-gradient-composed: var( --fade-gradient-base ), black 60%,
66
+ transparent 50%;
67
+ &.is-overflowing-first {
68
+ mask-image: linear-gradient(
69
+ to var( --direction-end ),
70
+ var( --fade-gradient-base )
71
+ );
72
+ }
73
+ &.is-overflowing-last {
74
+ mask-image: linear-gradient(
75
+ to var( --direction-start ),
76
+ var( --fade-gradient-base )
77
+ );
78
+ }
79
+ &.is-overflowing-first.is-overflowing-last {
80
+ mask-image: linear-gradient(
81
+ to right,
82
+ var( --fade-gradient-composed )
83
+ ),
84
+ linear-gradient( to left, var( --fade-gradient-composed ) );
85
+ }
86
+
87
+ &::before {
56
88
  bottom: 0;
57
89
  height: 0;
58
90
  width: calc( var( --antialiasing-factor ) * 1px );
@@ -71,8 +103,7 @@ export const TabListWrapper = styled.div`
71
103
  ${ COLORS.theme.accent };
72
104
  }
73
105
  }
74
- &[aria-orientation='vertical']::after {
75
- z-index: -1;
106
+ &[aria-orientation='vertical']::before {
76
107
  top: 0;
77
108
  left: 0;
78
109
  width: 100%;
@@ -87,14 +118,14 @@ export const TabListWrapper = styled.div`
87
118
 
88
119
  export const Tab = styled( Ariakit.Tab )`
89
120
  & {
121
+ scroll-margin: 24px;
122
+ flex-grow: 1;
123
+ flex-shrink: 0;
90
124
  display: inline-flex;
91
125
  align-items: center;
92
126
  position: relative;
93
127
  border-radius: 0;
94
- min-height: ${ space(
95
- 12
96
- ) }; // Avoid fixed height to allow for long strings that go in multiple lines.
97
- height: auto;
128
+ height: ${ space( 12 ) };
98
129
  background: transparent;
99
130
  border: none;
100
131
  box-shadow: none;
@@ -104,7 +135,6 @@ export const Tab = styled( Ariakit.Tab )`
104
135
  margin-left: 0;
105
136
  font-weight: 500;
106
137
  text-align: inherit;
107
- hyphens: auto;
108
138
  color: ${ COLORS.theme.foreground };
109
139
 
110
140
  &[aria-disabled='true'] {
@@ -123,7 +153,7 @@ export const Tab = styled( Ariakit.Tab )`
123
153
  }
124
154
 
125
155
  // Focus.
126
- &::before {
156
+ &::after {
127
157
  content: '';
128
158
  position: absolute;
129
159
  top: ${ space( 3 ) };
@@ -146,7 +176,7 @@ export const Tab = styled( Ariakit.Tab )`
146
176
  }
147
177
  }
148
178
 
149
- &:focus-visible::before {
179
+ &:focus-visible::after {
150
180
  opacity: 1;
151
181
  }
152
182
  }
@@ -156,6 +186,10 @@ export const Tab = styled( Ariakit.Tab )`
156
186
  10
157
187
  ) }; // Avoid fixed height to allow for long strings that go in multiple lines.
158
188
  }
189
+
190
+ [aria-orientation='horizontal'] & {
191
+ justify-content: center;
192
+ }
159
193
  `;
160
194
 
161
195
  export const TabPanel = styled( Ariakit.TabPanel )`
@@ -8,7 +8,8 @@ import { useStoreState } from '@ariakit/react';
8
8
  * WordPress dependencies
9
9
  */
10
10
  import warning from '@wordpress/warning';
11
- import { forwardRef, useState } from '@wordpress/element';
11
+ import { forwardRef, useLayoutEffect, useState } from '@wordpress/element';
12
+ import { useMergeRefs } from '@wordpress/compose';
12
13
 
13
14
  /**
14
15
  * Internal dependencies
@@ -20,33 +21,58 @@ import type { WordPressComponentProps } from '../context';
20
21
  import clsx from 'clsx';
21
22
  import { useTrackElementOffsetRect } from '../utils/element-rect';
22
23
  import { useOnValueUpdate } from '../utils/hooks/use-on-value-update';
24
+ import { useTrackOverflow } from './use-track-overflow';
25
+
26
+ const SCROLL_MARGIN = 24;
23
27
 
24
28
  export const TabList = forwardRef<
25
29
  HTMLDivElement,
26
30
  WordPressComponentProps< TabListProps, 'div', false >
27
31
  >( function TabList( { children, ...otherProps }, ref ) {
28
- const context = useTabsContext();
32
+ const { store } = useTabsContext() ?? {};
33
+
34
+ const selectedId = useStoreState( store, 'selectedId' );
35
+ const activeId = useStoreState( store, 'activeId' );
36
+ const selectOnMove = useStoreState( store, 'selectOnMove' );
37
+ const items = useStoreState( store, 'items' );
38
+ const [ parent, setParent ] = useState< HTMLElement | null >();
39
+ const refs = useMergeRefs( [ ref, setParent ] );
40
+ const overflow = useTrackOverflow( parent, {
41
+ first: items?.at( 0 )?.element,
42
+ last: items?.at( -1 )?.element,
43
+ } );
29
44
 
30
- const tabStoreState = useStoreState( context?.store );
31
- const selectedId = tabStoreState?.selectedId;
32
- const indicatorPosition = useTrackElementOffsetRect(
33
- context?.store.item( selectedId )?.element
45
+ const selectedTabPosition = useTrackElementOffsetRect(
46
+ store?.item( selectedId )?.element
34
47
  );
35
48
 
36
49
  const [ animationEnabled, setAnimationEnabled ] = useState( false );
37
- useOnValueUpdate(
38
- selectedId,
39
- ( { previousValue } ) => previousValue && setAnimationEnabled( true )
40
- );
50
+ useOnValueUpdate( selectedId, ( { previousValue } ) => {
51
+ if ( previousValue ) {
52
+ setAnimationEnabled( true );
53
+ }
54
+ } );
41
55
 
42
- if ( ! context || ! tabStoreState ) {
43
- warning( '`Tabs.TabList` must be wrapped in a `Tabs` component.' );
44
- return null;
45
- }
56
+ // Make sure selected tab is scrolled into view.
57
+ useLayoutEffect( () => {
58
+ if ( ! parent || ! selectedTabPosition ) {
59
+ return;
60
+ }
61
+
62
+ const { scrollLeft: parentScroll } = parent;
63
+ const parentWidth = parent.getBoundingClientRect().width;
64
+ const { left: childLeft, width: childWidth } = selectedTabPosition;
46
65
 
47
- const { store } = context;
48
- const { activeId, selectOnMove } = tabStoreState;
49
- const { setActiveId } = store;
66
+ const parentRightEdge = parentScroll + parentWidth;
67
+ const childRightEdge = childLeft + childWidth;
68
+ const rightOverflow = childRightEdge + SCROLL_MARGIN - parentRightEdge;
69
+ const leftOverflow = parentScroll - ( childLeft - SCROLL_MARGIN );
70
+ if ( leftOverflow > 0 ) {
71
+ parent.scrollLeft = parentScroll - leftOverflow;
72
+ } else if ( rightOverflow > 0 ) {
73
+ parent.scrollLeft = parentScroll + rightOverflow;
74
+ }
75
+ }, [ parent, selectedTabPosition ] );
50
76
 
51
77
  const onBlur = () => {
52
78
  if ( ! selectOnMove ) {
@@ -58,35 +84,43 @@ export const TabList = forwardRef<
58
84
  // that the selected tab will receive keyboard focus when tabbing back into
59
85
  // the tablist.
60
86
  if ( selectedId !== activeId ) {
61
- setActiveId( selectedId );
87
+ store?.setActiveId( selectedId );
62
88
  }
63
89
  };
64
90
 
91
+ if ( ! store ) {
92
+ warning( '`Tabs.TabList` must be wrapped in a `Tabs` component.' );
93
+ return null;
94
+ }
95
+
65
96
  return (
66
97
  <Ariakit.TabList
67
- ref={ ref }
98
+ ref={ refs }
68
99
  store={ store }
69
100
  render={
70
101
  <TabListWrapper
71
102
  onTransitionEnd={ ( event ) => {
72
- if ( event.pseudoElement === '::after' ) {
103
+ if ( event.pseudoElement === '::before' ) {
73
104
  setAnimationEnabled( false );
74
105
  }
75
106
  } }
76
107
  />
77
108
  }
78
109
  onBlur={ onBlur }
110
+ tabIndex={ -1 }
79
111
  { ...otherProps }
80
112
  style={ {
81
- '--indicator-top': indicatorPosition.top,
82
- '--indicator-right': indicatorPosition.right,
83
- '--indicator-left': indicatorPosition.left,
84
- '--indicator-width': indicatorPosition.width,
85
- '--indicator-height': indicatorPosition.height,
113
+ '--indicator-top': selectedTabPosition.top,
114
+ '--indicator-right': selectedTabPosition.right,
115
+ '--indicator-left': selectedTabPosition.left,
116
+ '--indicator-width': selectedTabPosition.width,
117
+ '--indicator-height': selectedTabPosition.height,
86
118
  ...otherProps.style,
87
119
  } }
88
120
  className={ clsx(
89
- animationEnabled ? 'is-animation-enabled' : '',
121
+ overflow.first && 'is-overflowing-first',
122
+ overflow.last && 'is-overflowing-last',
123
+ animationEnabled && 'is-animation-enabled',
90
124
  otherProps.className
91
125
  ) }
92
126
  >
@@ -0,0 +1,76 @@
1
+ /* eslint-disable jsdoc/require-param */
2
+ /**
3
+ * WordPress dependencies
4
+ */
5
+ import { useState, useEffect } from '@wordpress/element';
6
+ import { useEvent } from '@wordpress/compose';
7
+
8
+ /**
9
+ * Tracks if an element contains overflow and on which end by tracking the
10
+ * first and last child elements with an `IntersectionObserver` in relation
11
+ * to the parent element.
12
+ *
13
+ * Note that the returned value will only indicate whether the first or last
14
+ * element is currently "going out of bounds" but not whether it happens on
15
+ * the X or Y axis.
16
+ */
17
+ export function useTrackOverflow(
18
+ parent: HTMLElement | undefined | null,
19
+ children: {
20
+ first: HTMLElement | undefined | null;
21
+ last: HTMLElement | undefined | null;
22
+ }
23
+ ) {
24
+ const [ first, setFirst ] = useState( false );
25
+ const [ last, setLast ] = useState( false );
26
+ const [ observer, setObserver ] = useState< IntersectionObserver >();
27
+
28
+ const callback: IntersectionObserverCallback = useEvent( ( entries ) => {
29
+ for ( const entry of entries ) {
30
+ if ( entry.target === children.first ) {
31
+ setFirst( ! entry.isIntersecting );
32
+ }
33
+ if ( entry.target === children.last ) {
34
+ setLast( ! entry.isIntersecting );
35
+ }
36
+ }
37
+ } );
38
+
39
+ useEffect( () => {
40
+ if ( ! parent || ! window.IntersectionObserver ) {
41
+ return;
42
+ }
43
+ const newObserver = new IntersectionObserver( callback, {
44
+ root: parent,
45
+ threshold: 0.9,
46
+ } );
47
+ setObserver( newObserver );
48
+
49
+ return () => newObserver.disconnect();
50
+ }, [ callback, parent ] );
51
+
52
+ useEffect( () => {
53
+ if ( ! observer ) {
54
+ return;
55
+ }
56
+
57
+ if ( children.first ) {
58
+ observer.observe( children.first );
59
+ }
60
+ if ( children.last ) {
61
+ observer.observe( children.last );
62
+ }
63
+
64
+ return () => {
65
+ if ( children.first ) {
66
+ observer.unobserve( children.first );
67
+ }
68
+ if ( children.last ) {
69
+ observer.unobserve( children.last );
70
+ }
71
+ };
72
+ }, [ children.first, children.last, observer ] );
73
+
74
+ return { first, last };
75
+ }
76
+ /* eslint-enable jsdoc/require-param */