@wordpress/components 25.9.0 → 25.10.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 (308) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/build/alignment-matrix-control/cell.js +8 -5
  3. package/build/alignment-matrix-control/cell.js.map +1 -1
  4. package/build/alignment-matrix-control/index.js +27 -43
  5. package/build/alignment-matrix-control/index.js.map +1 -1
  6. package/build/alignment-matrix-control/utils.js +29 -9
  7. package/build/alignment-matrix-control/utils.js.map +1 -1
  8. package/build/circular-option-picker/circular-option-picker-option.js +20 -39
  9. package/build/circular-option-picker/circular-option-picker-option.js.map +1 -1
  10. package/build/circular-option-picker/circular-option-picker.js +11 -32
  11. package/build/circular-option-picker/circular-option-picker.js.map +1 -1
  12. package/build/circular-option-picker/types.js.map +1 -1
  13. package/build/color-palette/index.js +7 -2
  14. package/build/color-palette/index.js.map +1 -1
  15. package/build/color-picker/component.js +12 -2
  16. package/build/color-picker/component.js.map +1 -1
  17. package/build/color-picker/picker.js +77 -1
  18. package/build/color-picker/picker.js.map +1 -1
  19. package/build/color-picker/styles.js +8 -8
  20. package/build/color-picker/styles.js.map +1 -1
  21. package/build/color-picker/types.js.map +1 -1
  22. package/build/composite/v2.js +43 -0
  23. package/build/composite/v2.js.map +1 -0
  24. package/build/confirm-dialog/component.js +74 -8
  25. package/build/confirm-dialog/component.js.map +1 -1
  26. package/build/confirm-dialog/types.js.map +1 -1
  27. package/build/custom-gradient-picker/gradient-bar/control-points.js +13 -4
  28. package/build/custom-gradient-picker/gradient-bar/control-points.js.map +1 -1
  29. package/build/font-size-picker/utils.js +1 -1
  30. package/build/font-size-picker/utils.js.map +1 -1
  31. package/build/modal/index.js +45 -16
  32. package/build/modal/index.js.map +1 -1
  33. package/build/palette-edit/index.js +4 -0
  34. package/build/palette-edit/index.js.map +1 -1
  35. package/build/popover/index.js +34 -6
  36. package/build/popover/index.js.map +1 -1
  37. package/build/private-apis.js +9 -1
  38. package/build/private-apis.js.map +1 -1
  39. package/build/progress-bar/styles.js +5 -5
  40. package/build/progress-bar/styles.js.map +1 -1
  41. package/build/sandbox/index.js +1 -1
  42. package/build/sandbox/index.js.map +1 -1
  43. package/build/sandbox/index.native.js +1 -1
  44. package/build/sandbox/index.native.js.map +1 -1
  45. package/build/tabs/context.js +16 -0
  46. package/build/tabs/context.js.map +1 -0
  47. package/build/tabs/index.js +147 -0
  48. package/build/tabs/index.js.map +1 -0
  49. package/build/tabs/styles.js +38 -0
  50. package/build/tabs/styles.js.map +1 -0
  51. package/build/tabs/tab.js +46 -0
  52. package/build/tabs/tab.js.map +1 -0
  53. package/build/tabs/tablist.js +47 -0
  54. package/build/tabs/tablist.js.map +1 -0
  55. package/build/tabs/tabpanel.js +48 -0
  56. package/build/tabs/tabpanel.js.map +1 -0
  57. package/build/tabs/types.js +6 -0
  58. package/build/tabs/types.js.map +1 -0
  59. package/build/text/component.js +7 -6
  60. package/build/text/component.js.map +1 -1
  61. package/build/text/hook.js +6 -15
  62. package/build/text/hook.js.map +1 -1
  63. package/build/text/index.js.map +1 -1
  64. package/build/text/styles.js +7 -7
  65. package/build/text/styles.js.map +1 -1
  66. package/build/text/types.js.map +1 -1
  67. package/build/text/utils.js +17 -33
  68. package/build/text/utils.js.map +1 -1
  69. package/build/toggle-group-control/toggle-group-control-option-base/component.js +1 -0
  70. package/build/toggle-group-control/toggle-group-control-option-base/component.js.map +1 -1
  71. package/build/toolbar/toolbar/index.js +17 -10
  72. package/build/toolbar/toolbar/index.js.map +1 -1
  73. package/build/toolbar/toolbar/types.js.map +1 -1
  74. package/build/tools-panel/tools-panel-item/hook.js +2 -2
  75. package/build/tools-panel/tools-panel-item/hook.js.map +1 -1
  76. package/build/tools-panel/types.js.map +1 -1
  77. package/build/unit-control/utils.js +108 -0
  78. package/build/unit-control/utils.js.map +1 -1
  79. package/build/utils/unit-values.js +1 -1
  80. package/build/utils/unit-values.js.map +1 -1
  81. package/build-module/alignment-matrix-control/cell.js +7 -4
  82. package/build-module/alignment-matrix-control/cell.js.map +1 -1
  83. package/build-module/alignment-matrix-control/index.js +27 -43
  84. package/build-module/alignment-matrix-control/index.js.map +1 -1
  85. package/build-module/alignment-matrix-control/utils.js +29 -8
  86. package/build-module/alignment-matrix-control/utils.js.map +1 -1
  87. package/build-module/circular-option-picker/circular-option-picker-option.js +20 -39
  88. package/build-module/circular-option-picker/circular-option-picker-option.js.map +1 -1
  89. package/build-module/circular-option-picker/circular-option-picker.js +10 -31
  90. package/build-module/circular-option-picker/circular-option-picker.js.map +1 -1
  91. package/build-module/circular-option-picker/types.js.map +1 -1
  92. package/build-module/color-palette/index.js +7 -2
  93. package/build-module/color-palette/index.js.map +1 -1
  94. package/build-module/color-picker/component.js +13 -3
  95. package/build-module/color-picker/component.js.map +1 -1
  96. package/build-module/color-picker/picker.js +78 -2
  97. package/build-module/color-picker/picker.js.map +1 -1
  98. package/build-module/color-picker/styles.js +8 -8
  99. package/build-module/color-picker/styles.js.map +1 -1
  100. package/build-module/color-picker/types.js.map +1 -1
  101. package/build-module/composite/v2.js +15 -0
  102. package/build-module/composite/v2.js.map +1 -0
  103. package/build-module/confirm-dialog/component.js +72 -7
  104. package/build-module/confirm-dialog/component.js.map +1 -1
  105. package/build-module/confirm-dialog/types.js.map +1 -1
  106. package/build-module/custom-gradient-picker/gradient-bar/control-points.js +13 -4
  107. package/build-module/custom-gradient-picker/gradient-bar/control-points.js.map +1 -1
  108. package/build-module/font-size-picker/utils.js +1 -1
  109. package/build-module/font-size-picker/utils.js.map +1 -1
  110. package/build-module/modal/index.js +47 -18
  111. package/build-module/modal/index.js.map +1 -1
  112. package/build-module/palette-edit/index.js +4 -0
  113. package/build-module/palette-edit/index.js.map +1 -1
  114. package/build-module/popover/index.js +34 -6
  115. package/build-module/popover/index.js.map +1 -1
  116. package/build-module/private-apis.js +9 -1
  117. package/build-module/private-apis.js.map +1 -1
  118. package/build-module/progress-bar/styles.js +5 -5
  119. package/build-module/progress-bar/styles.js.map +1 -1
  120. package/build-module/sandbox/index.js +1 -1
  121. package/build-module/sandbox/index.js.map +1 -1
  122. package/build-module/sandbox/index.native.js +1 -1
  123. package/build-module/sandbox/index.native.js.map +1 -1
  124. package/build-module/tabs/context.js +12 -0
  125. package/build-module/tabs/context.js.map +1 -0
  126. package/build-module/tabs/index.js +142 -0
  127. package/build-module/tabs/index.js.map +1 -0
  128. package/build-module/tabs/styles.js +36 -0
  129. package/build-module/tabs/styles.js.map +1 -0
  130. package/build-module/tabs/tab.js +43 -0
  131. package/build-module/tabs/tab.js.map +1 -0
  132. package/build-module/tabs/tablist.js +41 -0
  133. package/build-module/tabs/tablist.js.map +1 -0
  134. package/build-module/tabs/tabpanel.js +43 -0
  135. package/build-module/tabs/tabpanel.js.map +1 -0
  136. package/build-module/tabs/types.js +2 -0
  137. package/build-module/tabs/types.js.map +1 -0
  138. package/build-module/text/component.js +6 -6
  139. package/build-module/text/component.js.map +1 -1
  140. package/build-module/text/hook.js +11 -19
  141. package/build-module/text/hook.js.map +1 -1
  142. package/build-module/text/index.js.map +1 -1
  143. package/build-module/text/styles.js +7 -7
  144. package/build-module/text/styles.js.map +1 -1
  145. package/build-module/text/types.js.map +1 -1
  146. package/build-module/text/utils.js +17 -10
  147. package/build-module/text/utils.js.map +1 -1
  148. package/build-module/toggle-group-control/toggle-group-control-option-base/component.js +1 -0
  149. package/build-module/toggle-group-control/toggle-group-control-option-base/component.js.map +1 -1
  150. package/build-module/toolbar/toolbar/index.js +18 -11
  151. package/build-module/toolbar/toolbar/index.js.map +1 -1
  152. package/build-module/toolbar/toolbar/types.js.map +1 -1
  153. package/build-module/tools-panel/tools-panel-item/hook.js +2 -2
  154. package/build-module/tools-panel/tools-panel-item/hook.js.map +1 -1
  155. package/build-module/tools-panel/types.js.map +1 -1
  156. package/build-module/unit-control/utils.js +108 -0
  157. package/build-module/unit-control/utils.js.map +1 -1
  158. package/build-module/utils/unit-values.js +1 -1
  159. package/build-module/utils/unit-values.js.map +1 -1
  160. package/build-style/style-rtl.css +16 -4
  161. package/build-style/style.css +16 -4
  162. package/build-types/alignment-matrix-control/cell.d.ts +1 -1
  163. package/build-types/alignment-matrix-control/cell.d.ts.map +1 -1
  164. package/build-types/alignment-matrix-control/index.d.ts.map +1 -1
  165. package/build-types/alignment-matrix-control/stories/index.story.d.ts.map +1 -1
  166. package/build-types/alignment-matrix-control/utils.d.ts +9 -9
  167. package/build-types/alignment-matrix-control/utils.d.ts.map +1 -1
  168. package/build-types/circular-option-picker/circular-option-picker-option.d.ts.map +1 -1
  169. package/build-types/circular-option-picker/circular-option-picker.d.ts.map +1 -1
  170. package/build-types/circular-option-picker/types.d.ts +4 -6
  171. package/build-types/circular-option-picker/types.d.ts.map +1 -1
  172. package/build-types/color-palette/index.d.ts.map +1 -1
  173. package/build-types/color-picker/component.d.ts.map +1 -1
  174. package/build-types/color-picker/picker.d.ts +1 -1
  175. package/build-types/color-picker/picker.d.ts.map +1 -1
  176. package/build-types/color-picker/styles.d.ts.map +1 -1
  177. package/build-types/color-picker/types.d.ts +3 -0
  178. package/build-types/color-picker/types.d.ts.map +1 -1
  179. package/build-types/composite/v2.d.ts +12 -0
  180. package/build-types/composite/v2.d.ts.map +1 -0
  181. package/build-types/confirm-dialog/component.d.ts +70 -29
  182. package/build-types/confirm-dialog/component.d.ts.map +1 -1
  183. package/build-types/confirm-dialog/stories/index.story.d.ts +11 -0
  184. package/build-types/confirm-dialog/stories/index.story.d.ts.map +1 -0
  185. package/build-types/confirm-dialog/test/index.d.ts +2 -0
  186. package/build-types/confirm-dialog/test/index.d.ts.map +1 -0
  187. package/build-types/confirm-dialog/types.d.ts +32 -10
  188. package/build-types/confirm-dialog/types.d.ts.map +1 -1
  189. package/build-types/custom-gradient-picker/gradient-bar/control-points.d.ts.map +1 -1
  190. package/build-types/font-size-picker/utils.d.ts.map +1 -1
  191. package/build-types/heading/stories/index.story.d.ts.map +1 -1
  192. package/build-types/modal/index.d.ts.map +1 -1
  193. package/build-types/palette-edit/index.d.ts.map +1 -1
  194. package/build-types/popover/index.d.ts +1 -1
  195. package/build-types/popover/index.d.ts.map +1 -1
  196. package/build-types/popover/stories/e2e/index.story.d.ts +1 -1
  197. package/build-types/private-apis.d.ts.map +1 -1
  198. package/build-types/progress-bar/styles.d.ts.map +1 -1
  199. package/build-types/sandbox/index.d.ts.map +1 -1
  200. package/build-types/tabs/context.d.ts +8 -0
  201. package/build-types/tabs/context.d.ts.map +1 -0
  202. package/build-types/tabs/index.d.ts +13 -0
  203. package/build-types/tabs/index.d.ts.map +1 -0
  204. package/build-types/tabs/stories/index.story.d.ts +20 -0
  205. package/build-types/tabs/stories/index.story.d.ts.map +1 -0
  206. package/build-types/tabs/styles.d.ts +17 -0
  207. package/build-types/tabs/styles.d.ts.map +1 -0
  208. package/build-types/tabs/tab.d.ts +10 -0
  209. package/build-types/tabs/tab.d.ts.map +1 -0
  210. package/build-types/tabs/tablist.d.ts +7 -0
  211. package/build-types/tabs/tablist.d.ts.map +1 -0
  212. package/build-types/tabs/tabpanel.d.ts +7 -0
  213. package/build-types/tabs/tabpanel.d.ts.map +1 -0
  214. package/build-types/tabs/test/index.d.ts +2 -0
  215. package/build-types/tabs/test/index.d.ts.map +1 -0
  216. package/build-types/tabs/types.d.ts +134 -0
  217. package/build-types/tabs/types.d.ts.map +1 -0
  218. package/build-types/text/component.d.ts +4 -2
  219. package/build-types/text/component.d.ts.map +1 -1
  220. package/build-types/text/hook.d.ts +171 -165
  221. package/build-types/text/hook.d.ts.map +1 -1
  222. package/build-types/text/index.d.ts +2 -2
  223. package/build-types/text/index.d.ts.map +1 -1
  224. package/build-types/text/stories/index.story.d.ts +21 -0
  225. package/build-types/text/stories/index.story.d.ts.map +1 -0
  226. package/build-types/text/styles.d.ts +7 -7
  227. package/build-types/text/styles.d.ts.map +1 -1
  228. package/build-types/text/types.d.ts +1 -1
  229. package/build-types/text/types.d.ts.map +1 -1
  230. package/build-types/text/utils.d.ts +56 -61
  231. package/build-types/text/utils.d.ts.map +1 -1
  232. package/build-types/toggle-group-control/toggle-group-control-option-base/component.d.ts.map +1 -1
  233. package/build-types/toolbar/stories/index.story.d.ts +5 -0
  234. package/build-types/toolbar/stories/index.story.d.ts.map +1 -1
  235. package/build-types/toolbar/toolbar/index.d.ts.map +1 -1
  236. package/build-types/toolbar/toolbar/types.d.ts +10 -0
  237. package/build-types/toolbar/toolbar/types.d.ts.map +1 -1
  238. package/build-types/tools-panel/tools-panel-item/hook.d.ts.map +1 -1
  239. package/build-types/tools-panel/types.d.ts +2 -0
  240. package/build-types/tools-panel/types.d.ts.map +1 -1
  241. package/build-types/unit-control/utils.d.ts.map +1 -1
  242. package/package.json +19 -19
  243. package/src/alignment-matrix-control/cell.tsx +6 -2
  244. package/src/alignment-matrix-control/index.tsx +31 -54
  245. package/src/alignment-matrix-control/stories/index.story.tsx +3 -7
  246. package/src/alignment-matrix-control/test/index.tsx +117 -18
  247. package/src/alignment-matrix-control/utils.tsx +33 -9
  248. package/src/button/style.scss +1 -2
  249. package/src/circular-option-picker/circular-option-picker-option.tsx +24 -38
  250. package/src/circular-option-picker/circular-option-picker.tsx +11 -28
  251. package/src/circular-option-picker/types.ts +6 -5
  252. package/src/color-palette/index.tsx +6 -1
  253. package/src/color-picker/component.tsx +25 -3
  254. package/src/color-picker/picker.tsx +96 -2
  255. package/src/color-picker/styles.ts +0 -1
  256. package/src/color-picker/types.ts +3 -0
  257. package/src/composite/v2.ts +22 -0
  258. package/src/confirm-dialog/README.md +1 -1
  259. package/src/confirm-dialog/component.tsx +79 -13
  260. package/src/confirm-dialog/stories/{index.story.js → index.story.tsx} +26 -24
  261. package/src/confirm-dialog/test/{index.js → index.tsx} +3 -3
  262. package/src/confirm-dialog/types.ts +32 -12
  263. package/src/custom-gradient-picker/gradient-bar/control-points.tsx +32 -25
  264. package/src/font-size-picker/utils.ts +2 -1
  265. package/src/heading/stories/index.story.tsx +2 -4
  266. package/src/modal/index.tsx +58 -22
  267. package/src/modal/test/index.tsx +29 -0
  268. package/src/notice/style.scss +0 -1
  269. package/src/palette-edit/index.tsx +4 -0
  270. package/src/popover/index.tsx +99 -57
  271. package/src/popover/style.scss +9 -0
  272. package/src/private-apis.ts +15 -1
  273. package/src/progress-bar/styles.ts +19 -4
  274. package/src/sandbox/index.native.js +1 -1
  275. package/src/sandbox/index.tsx +3 -1
  276. package/src/tabs/README.md +242 -0
  277. package/src/tabs/context.ts +13 -0
  278. package/src/tabs/index.tsx +167 -0
  279. package/src/tabs/stories/index.story.tsx +352 -0
  280. package/src/tabs/styles.ts +103 -0
  281. package/src/tabs/tab.tsx +39 -0
  282. package/src/tabs/tablist.tsx +40 -0
  283. package/src/tabs/tabpanel.tsx +42 -0
  284. package/src/tabs/test/index.tsx +1124 -0
  285. package/src/tabs/types.ts +142 -0
  286. package/src/text/README.md +2 -2
  287. package/src/text/{component.js → component.tsx} +10 -6
  288. package/src/text/{hook.js → hook.ts} +12 -15
  289. package/src/text/stories/index.story.tsx +80 -0
  290. package/src/text/types.ts +1 -6
  291. package/src/text/{utils.js → utils.ts} +40 -14
  292. package/src/toggle-group-control/test/__snapshots__/index.tsx.snap +8 -0
  293. package/src/toggle-group-control/toggle-group-control-option-base/component.tsx +1 -0
  294. package/src/toolbar/stories/index.story.tsx +15 -0
  295. package/src/toolbar/test/index.tsx +8 -0
  296. package/src/toolbar/toolbar/README.md +9 -0
  297. package/src/toolbar/toolbar/index.tsx +21 -12
  298. package/src/toolbar/toolbar/style.scss +9 -0
  299. package/src/toolbar/toolbar/types.ts +10 -0
  300. package/src/tools-panel/tools-panel/README.md +3 -0
  301. package/src/tools-panel/tools-panel-item/hook.ts +4 -6
  302. package/src/tools-panel/types.ts +2 -0
  303. package/src/unit-control/utils.ts +124 -0
  304. package/src/utils/unit-values.ts +1 -1
  305. package/tsconfig.tsbuildinfo +1 -1
  306. package/src/text/stories/index.story.js +0 -53
  307. /package/src/text/{index.js → index.ts} +0 -0
  308. /package/src/text/{styles.js → styles.ts} +0 -0
@@ -53,6 +53,11 @@ import {
53
53
  placementToMotionAnimationProps,
54
54
  getReferenceElement,
55
55
  } from './utils';
56
+ import {
57
+ contextConnect,
58
+ useContextSystem,
59
+ ContextSystemProvider,
60
+ } from '../context';
56
61
  import type { WordPressComponentProps } from '../context';
57
62
  import type {
58
63
  PopoverProps,
@@ -108,7 +113,7 @@ const getPopoverFallbackContainer = () => {
108
113
  return container;
109
114
  };
110
115
 
111
- const UnforwardedPopover = (
116
+ const UnconnectedPopover = (
112
117
  props: Omit<
113
118
  WordPressComponentProps< PopoverProps, 'div', false >,
114
119
  // To avoid overlaps between the standard HTML attributes and the props
@@ -148,7 +153,7 @@ const UnforwardedPopover = (
148
153
 
149
154
  // Rest
150
155
  ...contentProps
151
- } = props;
156
+ } = useContextSystem( props, 'Popover' );
152
157
 
153
158
  let computedFlipProp = flip;
154
159
  let computedResizeProp = resize;
@@ -383,63 +388,100 @@ const UnforwardedPopover = (
383
388
  const isPositioned =
384
389
  ( ! shouldAnimate || animationFinished ) && x !== null && y !== null;
385
390
 
391
+ // In case a `ColorPicker` component is rendered as a child of `Popover`,
392
+ // the `Popover` component can be notified of when the user is dragging
393
+ // parts of the `ColorPicker` UI (this is possible because the `ColorPicker`
394
+ // component exposes the `onPickerDragStart` and `onPickerDragEnd` props
395
+ // via internal context).
396
+ // While the user is performing a pointer drag, the `Popover` will render
397
+ // a transparent backdrop element that will serve as a "pointer events trap",
398
+ // making sure that no pointer events reach any potential `iframe` element
399
+ // underneath (like, for example, the editor canvas in the WordPress editor).
400
+ const [ showBackdrop, setShowBackdrop ] = useState( false );
401
+ const contextValue = useMemo(
402
+ () => ( {
403
+ ColorPicker: {
404
+ onPickerDragStart() {
405
+ setShowBackdrop( true );
406
+ },
407
+ onPickerDragEnd() {
408
+ setShowBackdrop( false );
409
+ },
410
+ },
411
+ } ),
412
+ []
413
+ );
414
+
386
415
  let content = (
387
- <motion.div
388
- className={ classnames( 'components-popover', className, {
389
- 'is-expanded': isExpanded,
390
- 'is-positioned': isPositioned,
391
- // Use the 'alternate' classname for 'toolbar' variant for back compat.
392
- [ `is-${
393
- computedVariant === 'toolbar'
394
- ? 'alternate'
395
- : computedVariant
396
- }` ]: computedVariant,
397
- } ) }
398
- { ...animationProps }
399
- { ...contentProps }
400
- ref={ mergedFloatingRef }
401
- { ...dialogProps }
402
- tabIndex={ -1 }
403
- >
404
- { /* Prevents scroll on the document */ }
405
- { isExpanded && <ScrollLock /> }
406
- { isExpanded && (
407
- <div className="components-popover__header">
408
- <span className="components-popover__header-title">
409
- { headerTitle }
410
- </span>
411
- <Button
412
- className="components-popover__close"
413
- icon={ close }
414
- onClick={ onClose }
415
- />
416
- </div>
417
- ) }
418
- <div className="components-popover__content">{ children }</div>
419
- { hasArrow && (
416
+ <>
417
+ { showBackdrop && (
420
418
  <div
421
- ref={ arrowCallbackRef }
422
- className={ [
423
- 'components-popover__arrow',
424
- `is-${ computedPlacement.split( '-' )[ 0 ] }`,
425
- ].join( ' ' ) }
426
- style={ {
427
- left:
428
- typeof arrowData?.x !== 'undefined' &&
429
- Number.isFinite( arrowData.x )
430
- ? `${ arrowData.x }px`
431
- : '',
432
- top:
433
- typeof arrowData?.y !== 'undefined' &&
434
- Number.isFinite( arrowData.y )
435
- ? `${ arrowData.y }px`
436
- : '',
437
- } }
438
- >
439
- <ArrowTriangle />
440
- </div>
419
+ className="components-popover-pointer-events-trap"
420
+ aria-hidden="true"
421
+ onClick={ () => setShowBackdrop( false ) }
422
+ />
441
423
  ) }
442
- </motion.div>
424
+ <motion.div
425
+ className={ classnames( 'components-popover', className, {
426
+ 'is-expanded': isExpanded,
427
+ 'is-positioned': isPositioned,
428
+ // Use the 'alternate' classname for 'toolbar' variant for back compat.
429
+ [ `is-${
430
+ computedVariant === 'toolbar'
431
+ ? 'alternate'
432
+ : computedVariant
433
+ }` ]: computedVariant,
434
+ } ) }
435
+ { ...animationProps }
436
+ { ...contentProps }
437
+ ref={ mergedFloatingRef }
438
+ { ...dialogProps }
439
+ tabIndex={ -1 }
440
+ >
441
+ { /* Prevents scroll on the document */ }
442
+ { isExpanded && <ScrollLock /> }
443
+ { isExpanded && (
444
+ <div className="components-popover__header">
445
+ <span className="components-popover__header-title">
446
+ { headerTitle }
447
+ </span>
448
+ <Button
449
+ className="components-popover__close"
450
+ icon={ close }
451
+ onClick={ onClose }
452
+ />
453
+ </div>
454
+ ) }
455
+ <div className="components-popover__content">
456
+ <ContextSystemProvider value={ contextValue }>
457
+ { children }
458
+ </ContextSystemProvider>
459
+ </div>
460
+ { hasArrow && (
461
+ <div
462
+ ref={ arrowCallbackRef }
463
+ className={ [
464
+ 'components-popover__arrow',
465
+ `is-${ computedPlacement.split( '-' )[ 0 ] }`,
466
+ ].join( ' ' ) }
467
+ style={ {
468
+ left:
469
+ typeof arrowData?.x !== 'undefined' &&
470
+ Number.isFinite( arrowData.x )
471
+ ? `${ arrowData.x }px`
472
+ : '',
473
+ top:
474
+ typeof arrowData?.y !== 'undefined' &&
475
+ Number.isFinite( arrowData.y )
476
+ ? `${ arrowData.y }px`
477
+ : '',
478
+ } }
479
+ >
480
+ <ArrowTriangle />
481
+ </div>
482
+ ) }
483
+ </motion.div>
484
+ </>
443
485
  );
444
486
 
445
487
  const shouldRenderWithinSlot = slot.ref && ! inline;
@@ -489,7 +531,7 @@ const UnforwardedPopover = (
489
531
  * ```
490
532
  *
491
533
  */
492
- export const Popover = forwardRef( UnforwardedPopover );
534
+ export const Popover = contextConnect( UnconnectedPopover, 'Popover' );
493
535
 
494
536
  function PopoverSlot(
495
537
  { name = SLOT_NAME }: { name?: string },
@@ -133,3 +133,12 @@ $shadow-popover-border-top-only-alternate: 0 #{-$border-width} 0 $gray-900;
133
133
  stroke: $gray-900;
134
134
  }
135
135
  }
136
+
137
+ .components-popover-pointer-events-trap {
138
+ // Same z-index as popover, but rendered before the popover element
139
+ // in DOM order = it will display just under the popover
140
+ z-index: z-index(".components-popover");
141
+ position: fixed;
142
+ inset: 0;
143
+ background-color: transparent;
144
+ }
@@ -6,6 +6,13 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri
6
6
  /**
7
7
  * Internal dependencies
8
8
  */
9
+ import {
10
+ Composite as CompositeV2,
11
+ CompositeGroup as CompositeGroupV2,
12
+ CompositeItem as CompositeItemV2,
13
+ CompositeRow as CompositeRowV2,
14
+ useCompositeStore as useCompositeStoreV2,
15
+ } from './composite/v2';
9
16
  import { default as CustomSelectControl } from './custom-select-control';
10
17
  import { positionToPlacement as __experimentalPopoverLegacyPositionToPlacement } from './popover/utils';
11
18
  import { default as ProgressBar } from './progress-bar';
@@ -24,15 +31,21 @@ import {
24
31
  } from './dropdown-menu-v2';
25
32
  import { ComponentsContext } from './context/context-system-provider';
26
33
  import Theme from './theme';
34
+ import Tabs from './tabs';
27
35
 
28
36
  export const { lock, unlock } =
29
37
  __dangerousOptInToUnstableAPIsOnlyForCoreModules(
30
- 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.',
38
+ 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.',
31
39
  '@wordpress/components'
32
40
  );
33
41
 
34
42
  export const privateApis = {};
35
43
  lock( privateApis, {
44
+ CompositeV2,
45
+ CompositeGroupV2,
46
+ CompositeItemV2,
47
+ CompositeRowV2,
48
+ useCompositeStoreV2,
36
49
  CustomSelectControl,
37
50
  __experimentalPopoverLegacyPositionToPlacement,
38
51
  createPrivateSlotFill,
@@ -48,5 +61,6 @@ lock( privateApis, {
48
61
  DropdownSubMenuV2,
49
62
  DropdownSubMenuTriggerV2,
50
63
  ProgressBar,
64
+ Tabs,
51
65
  Theme,
52
66
  } );
@@ -27,11 +27,17 @@ export const Track = styled.div`
27
27
  width: 100%;
28
28
  max-width: 160px;
29
29
  height: ${ CONFIG.borderWidthFocus };
30
- background-color: var(
31
- --wp-components-color-gray-300,
32
- ${ COLORS.gray[ 300 ] }
30
+ /* Text color at 10% opacity */
31
+ background-color: color-mix(
32
+ in srgb,
33
+ var( --wp-components-color-foreground, ${ COLORS.gray[ 900 ] } ),
34
+ transparent 90%
33
35
  );
34
36
  border-radius: ${ CONFIG.radiusBlockUi };
37
+
38
+ // Windows high contrast mode.
39
+ outline: 2px solid transparent;
40
+ outline-offset: 2px;
35
41
  `;
36
42
 
37
43
  export const Indicator = styled.div< {
@@ -43,7 +49,16 @@ export const Indicator = styled.div< {
43
49
  top: 0;
44
50
  height: 100%;
45
51
  border-radius: ${ CONFIG.radiusBlockUi };
46
- background-color: ${ COLORS.theme.accent };
52
+ /* Text color at 90% opacity */
53
+ background-color: color-mix(
54
+ in srgb,
55
+ var( --wp-components-color-foreground, ${ COLORS.gray[ 900 ] } ),
56
+ transparent 10%
57
+ );
58
+
59
+ // Windows high contrast mode.
60
+ outline: 2px solid transparent;
61
+ outline-offset: -2px;
47
62
 
48
63
  ${ ( { isIndeterminate, value } ) =>
49
64
  isIndeterminate
@@ -68,7 +68,7 @@ const observeAndResizeJS = `
68
68
  style
69
69
  ) {
70
70
  if (
71
- /^\\d+(vmin|vmax|vh|vw)$/.test( ruleOrNode.style[ style ] )
71
+ /^\\d+(vw|vh|svw|lvw|dvw|svh|lvh|dvh|vi|svi|lvi|dvi|vb|svb|lvb|dvb|vmin|svmin|lvmin|dvmin|vmax|svmax|lvmax|dvmax)$/.test( ruleOrNode.style[ style ] )
72
72
  ) {
73
73
  ruleOrNode.style[ style ] = '';
74
74
  }
@@ -55,7 +55,9 @@ const observeAndResizeJS = function () {
55
55
  [ 'width', 'height', 'minHeight', 'maxHeight' ] as const
56
56
  ).forEach( function ( style ) {
57
57
  if (
58
- /^\\d+(vmin|vmax|vh|vw)$/.test( ruleOrNode.style[ style ] )
58
+ /^\\d+(vw|vh|svw|lvw|dvw|svh|lvh|dvh|vi|svi|lvi|dvi|vb|svb|lvb|dvb|vmin|svmin|lvmin|dvmin|vmax|svmax|lvmax|dvmax)$/.test(
59
+ ruleOrNode.style[ style ]
60
+ )
59
61
  ) {
60
62
  ruleOrNode.style[ style ] = '';
61
63
  }
@@ -0,0 +1,242 @@
1
+ # Tabs
2
+
3
+ <div class="callout callout-alert">
4
+ This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes.
5
+ </div>
6
+
7
+ Tabs is a collection of React components that combine to render an [ARIA-compliant tabs pattern](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/).
8
+
9
+ Tabs organizes content across different screens, data sets, and interactions. It has two sections: a list of tabs, and the view to show when tabs are chosen.
10
+
11
+ ## Development guidelines
12
+
13
+ ### Usage
14
+
15
+ #### Uncontrolled Mode
16
+
17
+ Tabs can be used in an uncontrolled mode, where the component manages its own state. In this mode, the `initialTabId` prop can be used to set the initially selected tab. If this prop is not set, the first tab will be selected by default. In addition, in most cases where the currently active tab becomes disabled or otherwise unavailable, uncontrolled mode will automatically fall back to selecting the first available tab.
18
+
19
+ ```jsx
20
+ import { Tabs } from '@wordpress/components';
21
+
22
+ const onSelect = ( tabName ) => {
23
+ console.log( 'Selecting tab', tabName );
24
+ };
25
+
26
+ const MyUncontrolledTabs = () => (
27
+ <Tabs onSelect={onSelect} initialTab="tab2">
28
+ <Tabs.TabList >
29
+ <Tabs.Tab id={ 'tab1' } title={ 'Tab 1' }>
30
+ Tab 1
31
+ </Tabs.Tab>
32
+ <Tabs.Tab id={ 'tab2' } title={ 'Tab 2' }>
33
+ Tab 2
34
+ </Tabs.Tab>
35
+ <Tabs.Tab id={ 'tab3' } title={ 'Tab 3' }>
36
+ Tab 3
37
+ </Tabs.Tab>
38
+ </Tabs.TabList>
39
+ <Tabs.TabPanel id={ 'tab1' }>
40
+ <p>Selected tab: Tab 1</p>
41
+ </Tabs.TabPanel>
42
+ <Tabs.TabPanel id={ 'tab2' }>
43
+ <p>Selected tab: Tab 2</p>
44
+ </Tabs.TabPanel>
45
+ <Tabs.TabPanel id={ 'tab3' }>
46
+ <p>Selected tab: Tab 3</p>
47
+ </Tabs.TabPanel>
48
+ </Tabs>
49
+ );
50
+ ```
51
+
52
+ #### Controlled Mode
53
+
54
+ Tabs can also be used in a controlled mode, where the parent component specifies the `selectedTabId` and the `onSelect` props to control tab selection. In this mode, the `initialTabId` prop will be ignored if it is provided. If the `selectedTabId` is `null`, no tab is selected. In this mode, if the currently selected tab becomes disabled or otherwise unavailable, the component will _not_ fall back to another available tab, leaving the controlling component in charge of implementing the desired logic.
55
+
56
+ ```jsx
57
+ import { Tabs } from '@wordpress/components';
58
+ const [ selectedTabId, setSelectedTabId ] = useState<
59
+ string | undefined | null
60
+ >();
61
+
62
+ const onSelect = ( tabName ) => {
63
+ console.log( 'Selecting tab', tabName );
64
+ };
65
+
66
+ const MyControlledTabs = () => (
67
+ <Tabs
68
+ selectedTabId={ selectedTabId }
69
+ onSelect={ ( selectedId ) => {
70
+ setSelectedTabId( selectedId );
71
+ onSelect( selectedId );
72
+ } }
73
+ >
74
+ <Tabs.TabList >
75
+ <Tabs.Tab id={ 'tab1' } title={ 'Tab 1' }>
76
+ Tab 1
77
+ </Tabs.Tab>
78
+ <Tabs.Tab id={ 'tab2' } title={ 'Tab 2' }>
79
+ Tab 2
80
+ </Tabs.Tab>
81
+ <Tabs.Tab id={ 'tab3' } title={ 'Tab 3' }>
82
+ Tab 3
83
+ </Tabs.Tab>
84
+ </Tabs.TabList>
85
+ <Tabs.TabPanel id={ 'tab1' }>
86
+ <p>Selected tab: Tab 1</p>
87
+ </Tabs.TabPanel>
88
+ <Tabs.TabPanel id={ 'tab2' }>
89
+ <p>Selected tab: Tab 2</p>
90
+ </Tabs.TabPanel>
91
+ <Tabs.TabPanel id={ 'tab3' }>
92
+ <p>Selected tab: Tab 3</p>
93
+ </Tabs.TabPanel>
94
+ </Tabs>
95
+ );
96
+ ```
97
+
98
+ ### Components and Sub-components
99
+
100
+ Tabs is comprised of four individual components:
101
+ - `Tabs`: a wrapper component and context provider. It is responsible for managing the state of the tabs and rendering the `TabList` and `TabPanels`.
102
+ - `TabList`: a wrapper component for the `Tab` components. It is responsible for rendering the list of tabs.
103
+ - `Tab`: renders a single tab. The currently active tab receives default styling that can be overridden with CSS targeting [aria-selected="true"].
104
+ - `TabPanel`: renders the content to display for a single tab once that tab is selected.
105
+
106
+ #### Tabs
107
+
108
+ ##### Props
109
+
110
+ ###### `children`: `React.ReactNode`
111
+
112
+ The children elements, which should be at least a `Tabs.Tablist` component and a series of `Tabs.TabPanel` components.
113
+
114
+ - Required: Yes
115
+
116
+ ###### `selectOnMove`: `boolean`
117
+
118
+ When `true`, the tab will be selected when receiving focus (automatic tab activation). When `false`, the tab will be selected only when clicked (manual tab activation). See the [official W3C docs](https://www.w3.org/WAI/ARIA/apg/patterns/tabpanel/) for more info.
119
+
120
+ - Required: No
121
+ - Default: `true`
122
+
123
+ ###### `initialTabId`: `string`
124
+
125
+ The id of the tab to be selected upon mounting of component. If this prop is not set, the first tab will be selected by default. The id provided will be internally prefixed with a unique instance ID to avoid collisions.
126
+
127
+ _Note: this prop will be overridden by the `selectedTabId` prop if it is provided. (Controlled Mode)_
128
+
129
+ - Required: No
130
+
131
+ ###### `onSelect`: `( ( selectedId: string | null | undefined ) => void )`
132
+
133
+ The function called when a tab has been selected. It is passed the selected tab's ID as an argument.
134
+
135
+ - Required: No
136
+ - Default: `noop`
137
+
138
+ ###### `orientation`: `horizontal | vertical`
139
+
140
+ The orientation of the `tablist` (`vertical` or `horizontal`)
141
+
142
+ - Required: No
143
+ - Default: `horizontal`
144
+
145
+ ###### `selectedTabId`: `string | null`
146
+
147
+ The ID of the tab to display. This id is prepended with the `Tabs` instanceId internally.
148
+ If left `undefined`, the component assumes it is being used in uncontrolled mode. Consequently, any value different than `undefined` will set the component in `controlled` mode. When in controlled mode, the `null` value will result in no tab being selected.
149
+
150
+ - Required: No
151
+
152
+ #### TabList
153
+
154
+ ##### Props
155
+
156
+ ###### `children`: `React.ReactNode`
157
+
158
+ The children elements, which should be a series of `Tabs.TabPanel` components.
159
+
160
+ - Required: No
161
+
162
+ ###### `className`: `string`
163
+
164
+ The class name to apply to the tablist.
165
+
166
+ - Required: No
167
+ - Default: ''
168
+
169
+ ###### `style`: `React.CSSProperties`
170
+
171
+ Custom CSS styles for the tablist.
172
+
173
+ - Required: No
174
+
175
+ #### Tab
176
+
177
+ ##### Props
178
+
179
+ ###### `id`: `string`
180
+
181
+ The id of the tab, which is prepended with the `Tabs` instance ID.
182
+
183
+ - Required: Yes
184
+
185
+ ###### `style`: `React.CSSProperties`
186
+
187
+ Custom CSS styles for the tab.
188
+
189
+ - Required: No
190
+
191
+ ###### `children`: `React.ReactNode`
192
+
193
+ The children elements, generally the text to display on the tab.
194
+
195
+ - Required: No
196
+
197
+ ###### `className`: `string`
198
+
199
+ The class name to apply to the tab.
200
+
201
+ - Required: No
202
+
203
+ ###### `disabled`: `boolean`
204
+
205
+ Determines if the tab button should be disabled.
206
+
207
+ - Required: No
208
+ - Default: `false`
209
+
210
+ ###### `render`: `React.ReactNode`
211
+
212
+ The type of component to render the tab button as. If this prop is not provided, the tab button will be rendered as a `button` element.
213
+
214
+ - Required: No
215
+
216
+ #### TabPanel
217
+
218
+ ##### Props
219
+
220
+ ###### `children`: `React.ReactNode`
221
+
222
+ The children elements, generally the content to display on the tabpanel.
223
+
224
+ - Required: No
225
+
226
+ ###### `id`: `string`
227
+
228
+ The id of the tabpanel, which is combined with the `Tabs` instance ID and the suffix `-view`
229
+
230
+ - Required: Yes
231
+
232
+ ###### `className`: `string`
233
+
234
+ The class name to apply to the tabpanel.
235
+
236
+ - Required: No
237
+
238
+ ###### `style`: `React.CSSProperties`
239
+
240
+ Custom CSS styles for the tab.
241
+
242
+ - Required: No
@@ -0,0 +1,13 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { createContext, useContext } from '@wordpress/element';
5
+
6
+ /**
7
+ * Internal dependencies
8
+ */
9
+ import type { TabsContextProps } from './types';
10
+
11
+ export const TabsContext = createContext< TabsContextProps >( undefined );
12
+
13
+ export const useTabsContext = () => useContext( TabsContext );