@wordpress/ui 0.9.1-next.v.202603161435.0 → 0.11.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 (655) hide show
  1. package/CHANGELOG.md +76 -1
  2. package/CONTRIBUTING.md +180 -0
  3. package/README.md +34 -6
  4. package/build/alert-dialog/context.cjs +39 -0
  5. package/build/alert-dialog/context.cjs.map +7 -0
  6. package/build/alert-dialog/index.cjs +37 -0
  7. package/build/alert-dialog/index.cjs.map +7 -0
  8. package/build/alert-dialog/popup.cjs +165 -0
  9. package/build/alert-dialog/popup.cjs.map +7 -0
  10. package/build/alert-dialog/root.cjs +152 -0
  11. package/build/alert-dialog/root.cjs.map +7 -0
  12. package/build/alert-dialog/trigger.cjs +38 -0
  13. package/build/alert-dialog/trigger.cjs.map +7 -0
  14. package/build/alert-dialog/types.cjs +19 -0
  15. package/build/alert-dialog/types.cjs.map +7 -0
  16. package/build/badge/badge.cjs +14 -14
  17. package/build/badge/badge.cjs.map +2 -2
  18. package/build/button/button.cjs +18 -8
  19. package/build/button/button.cjs.map +3 -3
  20. package/build/card/content.cjs +4 -4
  21. package/build/card/content.cjs.map +2 -2
  22. package/build/card/full-bleed.cjs +4 -4
  23. package/build/card/full-bleed.cjs.map +2 -2
  24. package/build/card/header.cjs +4 -4
  25. package/build/card/header.cjs.map +2 -2
  26. package/build/card/root.cjs +6 -6
  27. package/build/card/root.cjs.map +2 -2
  28. package/build/card/title.cjs +14 -21
  29. package/build/card/title.cjs.map +3 -3
  30. package/build/collapsible-card/content.cjs +24 -3
  31. package/build/collapsible-card/content.cjs.map +4 -4
  32. package/build/collapsible-card/context.cjs +35 -0
  33. package/build/collapsible-card/context.cjs.map +7 -0
  34. package/build/collapsible-card/header-description.cjs +52 -0
  35. package/build/collapsible-card/header-description.cjs.map +7 -0
  36. package/build/collapsible-card/header.cjs +39 -18
  37. package/build/collapsible-card/header.cjs.map +2 -2
  38. package/build/collapsible-card/index.cjs +3 -0
  39. package/build/collapsible-card/index.cjs.map +2 -2
  40. package/build/collapsible-card/types.cjs.map +1 -1
  41. package/build/dialog/action.cjs +4 -2
  42. package/build/dialog/action.cjs.map +2 -2
  43. package/build/dialog/close-icon.cjs +2 -1
  44. package/build/dialog/close-icon.cjs.map +2 -2
  45. package/build/dialog/footer.cjs +3 -3
  46. package/build/dialog/footer.cjs.map +2 -2
  47. package/build/dialog/header.cjs +3 -3
  48. package/build/dialog/header.cjs.map +2 -2
  49. package/build/dialog/popup.cjs +24 -6
  50. package/build/dialog/popup.cjs.map +2 -2
  51. package/build/dialog/title.cjs +10 -19
  52. package/build/dialog/title.cjs.map +3 -3
  53. package/build/dialog/types.cjs.map +1 -1
  54. package/build/empty-state/actions.cjs +66 -0
  55. package/build/empty-state/actions.cjs.map +7 -0
  56. package/build/empty-state/description.cjs +69 -0
  57. package/build/empty-state/description.cjs.map +7 -0
  58. package/build/empty-state/icon.cjs +69 -0
  59. package/build/empty-state/icon.cjs.map +7 -0
  60. package/build/empty-state/index.cjs +46 -0
  61. package/build/empty-state/index.cjs.map +7 -0
  62. package/build/empty-state/root.cjs +66 -0
  63. package/build/empty-state/root.cjs.map +7 -0
  64. package/build/empty-state/title.cjs +71 -0
  65. package/build/empty-state/title.cjs.map +7 -0
  66. package/build/empty-state/types.cjs +19 -0
  67. package/build/empty-state/types.cjs.map +7 -0
  68. package/build/empty-state/visual.cjs +66 -0
  69. package/build/empty-state/visual.cjs.map +7 -0
  70. package/build/form/index.cjs +27 -0
  71. package/build/form/index.cjs.map +7 -0
  72. package/build/form/input-control/index.cjs +31 -0
  73. package/build/form/input-control/index.cjs.map +7 -0
  74. package/build/form/input-control/input-control.cjs +50 -0
  75. package/build/form/input-control/input-control.cjs.map +7 -0
  76. package/build/form/input-control/types.cjs +19 -0
  77. package/build/form/input-control/types.cjs.map +7 -0
  78. package/build/form/primitives/field/description.cjs +17 -4
  79. package/build/form/primitives/field/description.cjs.map +3 -3
  80. package/build/form/primitives/field/details.cjs +4 -4
  81. package/build/form/primitives/field/details.cjs.map +2 -2
  82. package/build/form/primitives/field/label.cjs +8 -8
  83. package/build/form/primitives/field/label.cjs.map +2 -2
  84. package/build/form/primitives/field/root.cjs +2 -2
  85. package/build/form/primitives/field/root.cjs.map +1 -1
  86. package/build/form/primitives/fieldset/description.cjs +20 -4
  87. package/build/form/primitives/fieldset/description.cjs.map +3 -3
  88. package/build/form/primitives/fieldset/details.cjs +3 -3
  89. package/build/form/primitives/fieldset/details.cjs.map +2 -2
  90. package/build/form/primitives/fieldset/legend.cjs +8 -7
  91. package/build/form/primitives/fieldset/legend.cjs.map +2 -2
  92. package/build/form/primitives/fieldset/root.cjs +2 -2
  93. package/build/form/primitives/fieldset/root.cjs.map +1 -1
  94. package/build/form/primitives/input/input.cjs +23 -7
  95. package/build/form/primitives/input/input.cjs.map +3 -3
  96. package/build/form/primitives/input-layout/input-layout.cjs +15 -5
  97. package/build/form/primitives/input-layout/input-layout.cjs.map +3 -3
  98. package/build/form/primitives/input-layout/slot.cjs +6 -5
  99. package/build/form/primitives/input-layout/slot.cjs.map +2 -2
  100. package/build/form/primitives/select/item.cjs +5 -5
  101. package/build/form/primitives/select/item.cjs.map +2 -2
  102. package/build/form/primitives/select/popup.cjs +9 -9
  103. package/build/form/primitives/select/popup.cjs.map +2 -2
  104. package/build/form/primitives/select/trigger.cjs +6 -6
  105. package/build/form/primitives/select/trigger.cjs.map +2 -2
  106. package/build/form/primitives/select/types.cjs.map +1 -1
  107. package/build/form/primitives/textarea/textarea.cjs +23 -4
  108. package/build/form/primitives/textarea/textarea.cjs.map +3 -3
  109. package/build/form/types.cjs +19 -0
  110. package/build/form/types.cjs.map +7 -0
  111. package/build/icon-button/icon-button.cjs +2 -2
  112. package/build/icon-button/icon-button.cjs.map +1 -1
  113. package/build/index.cjs +11 -2
  114. package/build/index.cjs.map +2 -2
  115. package/build/link/link.cjs +18 -8
  116. package/build/link/link.cjs.map +3 -3
  117. package/build/notice/action-button.cjs +3 -3
  118. package/build/notice/action-button.cjs.map +2 -2
  119. package/build/notice/action-link.cjs +3 -3
  120. package/build/notice/action-link.cjs.map +2 -2
  121. package/build/notice/actions.cjs +3 -3
  122. package/build/notice/actions.cjs.map +2 -2
  123. package/build/notice/close-icon.cjs +3 -3
  124. package/build/notice/close-icon.cjs.map +2 -2
  125. package/build/notice/description.cjs +3 -3
  126. package/build/notice/description.cjs.map +2 -2
  127. package/build/notice/index.cjs.map +1 -1
  128. package/build/notice/root.cjs +5 -5
  129. package/build/notice/root.cjs.map +2 -2
  130. package/build/notice/title.cjs +3 -3
  131. package/build/notice/title.cjs.map +2 -2
  132. package/build/popover/arrow.cjs +94 -0
  133. package/build/popover/arrow.cjs.map +7 -0
  134. package/build/popover/close.cjs +45 -0
  135. package/build/popover/close.cjs.map +7 -0
  136. package/build/popover/context.cjs +76 -0
  137. package/build/popover/context.cjs.map +7 -0
  138. package/build/popover/description.cjs +70 -0
  139. package/build/popover/description.cjs.map +7 -0
  140. package/build/popover/index.cjs +49 -0
  141. package/build/popover/index.cjs.map +7 -0
  142. package/build/popover/popup.cjs +138 -0
  143. package/build/popover/popup.cjs.map +7 -0
  144. package/build/popover/root.cjs +35 -0
  145. package/build/popover/root.cjs.map +7 -0
  146. package/build/popover/title.cjs +56 -0
  147. package/build/popover/title.cjs.map +7 -0
  148. package/build/popover/trigger.cjs +38 -0
  149. package/build/popover/trigger.cjs.map +7 -0
  150. package/build/popover/types.cjs +19 -0
  151. package/build/popover/types.cjs.map +7 -0
  152. package/build/stack/stack.cjs +2 -2
  153. package/build/stack/stack.cjs.map +1 -1
  154. package/build/tabs/context.cjs +121 -0
  155. package/build/tabs/context.cjs.map +7 -0
  156. package/build/tabs/list.cjs +3 -4
  157. package/build/tabs/list.cjs.map +2 -2
  158. package/build/tabs/panel.cjs +5 -3
  159. package/build/tabs/panel.cjs.map +2 -2
  160. package/build/tabs/root.cjs +2 -1
  161. package/build/tabs/root.cjs.map +2 -2
  162. package/build/tabs/tab.cjs +5 -3
  163. package/build/tabs/tab.cjs.map +2 -2
  164. package/build/text/text.cjs +20 -5
  165. package/build/text/text.cjs.map +3 -3
  166. package/build/tooltip/popup.cjs +7 -6
  167. package/build/tooltip/popup.cjs.map +2 -2
  168. package/build/tooltip/root.cjs.map +2 -2
  169. package/build/tooltip/types.cjs.map +1 -1
  170. package/build/utils/types.cjs.map +1 -1
  171. package/build/utils/use-deprioritized-initial-focus.cjs +64 -0
  172. package/build/utils/use-deprioritized-initial-focus.cjs.map +7 -0
  173. package/build/visually-hidden/visually-hidden.cjs +2 -2
  174. package/build/visually-hidden/visually-hidden.cjs.map +2 -2
  175. package/build-module/alert-dialog/context.mjs +14 -0
  176. package/build-module/alert-dialog/context.mjs.map +7 -0
  177. package/build-module/alert-dialog/index.mjs +10 -0
  178. package/build-module/alert-dialog/index.mjs.map +7 -0
  179. package/build-module/alert-dialog/popup.mjs +132 -0
  180. package/build-module/alert-dialog/popup.mjs.map +7 -0
  181. package/build-module/alert-dialog/root.mjs +133 -0
  182. package/build-module/alert-dialog/root.mjs.map +7 -0
  183. package/build-module/alert-dialog/trigger.mjs +13 -0
  184. package/build-module/alert-dialog/trigger.mjs.map +7 -0
  185. package/build-module/alert-dialog/types.mjs +1 -0
  186. package/build-module/alert-dialog/types.mjs.map +7 -0
  187. package/build-module/badge/badge.mjs +14 -14
  188. package/build-module/badge/badge.mjs.map +2 -2
  189. package/build-module/button/button.mjs +18 -8
  190. package/build-module/button/button.mjs.map +3 -3
  191. package/build-module/card/content.mjs +4 -4
  192. package/build-module/card/content.mjs.map +2 -2
  193. package/build-module/card/full-bleed.mjs +4 -4
  194. package/build-module/card/full-bleed.mjs.map +2 -2
  195. package/build-module/card/header.mjs +4 -4
  196. package/build-module/card/header.mjs.map +2 -2
  197. package/build-module/card/root.mjs +6 -6
  198. package/build-module/card/root.mjs.map +2 -2
  199. package/build-module/card/title.mjs +14 -21
  200. package/build-module/card/title.mjs.map +3 -3
  201. package/build-module/collapsible-card/content.mjs +24 -3
  202. package/build-module/collapsible-card/content.mjs.map +3 -3
  203. package/build-module/collapsible-card/context.mjs +10 -0
  204. package/build-module/collapsible-card/context.mjs.map +7 -0
  205. package/build-module/collapsible-card/header-description.mjs +27 -0
  206. package/build-module/collapsible-card/header-description.mjs.map +7 -0
  207. package/build-module/collapsible-card/header.mjs +40 -19
  208. package/build-module/collapsible-card/header.mjs.map +2 -2
  209. package/build-module/collapsible-card/index.mjs +2 -0
  210. package/build-module/collapsible-card/index.mjs.map +2 -2
  211. package/build-module/dialog/action.mjs +4 -2
  212. package/build-module/dialog/action.mjs.map +2 -2
  213. package/build-module/dialog/close-icon.mjs +2 -1
  214. package/build-module/dialog/close-icon.mjs.map +2 -2
  215. package/build-module/dialog/footer.mjs +3 -3
  216. package/build-module/dialog/footer.mjs.map +2 -2
  217. package/build-module/dialog/header.mjs +3 -3
  218. package/build-module/dialog/header.mjs.map +2 -2
  219. package/build-module/dialog/popup.mjs +24 -6
  220. package/build-module/dialog/popup.mjs.map +2 -2
  221. package/build-module/dialog/title.mjs +10 -9
  222. package/build-module/dialog/title.mjs.map +2 -2
  223. package/build-module/empty-state/actions.mjs +31 -0
  224. package/build-module/empty-state/actions.mjs.map +7 -0
  225. package/build-module/empty-state/description.mjs +34 -0
  226. package/build-module/empty-state/description.mjs.map +7 -0
  227. package/build-module/empty-state/icon.mjs +34 -0
  228. package/build-module/empty-state/icon.mjs.map +7 -0
  229. package/build-module/empty-state/index.mjs +16 -0
  230. package/build-module/empty-state/index.mjs.map +7 -0
  231. package/build-module/empty-state/root.mjs +31 -0
  232. package/build-module/empty-state/root.mjs.map +7 -0
  233. package/build-module/empty-state/title.mjs +36 -0
  234. package/build-module/empty-state/title.mjs.map +7 -0
  235. package/build-module/empty-state/types.mjs +1 -0
  236. package/build-module/empty-state/types.mjs.map +7 -0
  237. package/build-module/empty-state/visual.mjs +31 -0
  238. package/build-module/empty-state/visual.mjs.map +7 -0
  239. package/build-module/form/index.mjs +4 -0
  240. package/build-module/form/index.mjs.map +7 -0
  241. package/build-module/form/input-control/index.mjs +6 -0
  242. package/build-module/form/input-control/index.mjs.map +7 -0
  243. package/build-module/form/input-control/input-control.mjs +25 -0
  244. package/build-module/form/input-control/input-control.mjs.map +7 -0
  245. package/build-module/form/input-control/types.mjs +1 -0
  246. package/build-module/form/input-control/types.mjs.map +7 -0
  247. package/build-module/form/primitives/field/description.mjs +17 -4
  248. package/build-module/form/primitives/field/description.mjs.map +3 -3
  249. package/build-module/form/primitives/field/details.mjs +4 -4
  250. package/build-module/form/primitives/field/details.mjs.map +2 -2
  251. package/build-module/form/primitives/field/label.mjs +8 -8
  252. package/build-module/form/primitives/field/label.mjs.map +2 -2
  253. package/build-module/form/primitives/field/root.mjs +2 -2
  254. package/build-module/form/primitives/field/root.mjs.map +1 -1
  255. package/build-module/form/primitives/fieldset/description.mjs +20 -4
  256. package/build-module/form/primitives/fieldset/description.mjs.map +3 -3
  257. package/build-module/form/primitives/fieldset/details.mjs +3 -3
  258. package/build-module/form/primitives/fieldset/details.mjs.map +2 -2
  259. package/build-module/form/primitives/fieldset/legend.mjs +8 -7
  260. package/build-module/form/primitives/fieldset/legend.mjs.map +2 -2
  261. package/build-module/form/primitives/fieldset/root.mjs +2 -2
  262. package/build-module/form/primitives/fieldset/root.mjs.map +1 -1
  263. package/build-module/form/primitives/input/input.mjs +23 -7
  264. package/build-module/form/primitives/input/input.mjs.map +3 -3
  265. package/build-module/form/primitives/input-layout/input-layout.mjs +15 -5
  266. package/build-module/form/primitives/input-layout/input-layout.mjs.map +3 -3
  267. package/build-module/form/primitives/input-layout/slot.mjs +6 -5
  268. package/build-module/form/primitives/input-layout/slot.mjs.map +2 -2
  269. package/build-module/form/primitives/select/item.mjs +5 -5
  270. package/build-module/form/primitives/select/item.mjs.map +2 -2
  271. package/build-module/form/primitives/select/popup.mjs +9 -9
  272. package/build-module/form/primitives/select/popup.mjs.map +2 -2
  273. package/build-module/form/primitives/select/trigger.mjs +6 -6
  274. package/build-module/form/primitives/select/trigger.mjs.map +2 -2
  275. package/build-module/form/primitives/textarea/textarea.mjs +23 -4
  276. package/build-module/form/primitives/textarea/textarea.mjs.map +3 -3
  277. package/build-module/form/types.mjs +1 -0
  278. package/build-module/form/types.mjs.map +7 -0
  279. package/build-module/icon-button/icon-button.mjs +2 -2
  280. package/build-module/icon-button/icon-button.mjs.map +1 -1
  281. package/build-module/index.mjs +7 -1
  282. package/build-module/index.mjs.map +2 -2
  283. package/build-module/link/link.mjs +18 -8
  284. package/build-module/link/link.mjs.map +3 -3
  285. package/build-module/notice/action-button.mjs +3 -3
  286. package/build-module/notice/action-button.mjs.map +2 -2
  287. package/build-module/notice/action-link.mjs +3 -3
  288. package/build-module/notice/action-link.mjs.map +2 -2
  289. package/build-module/notice/actions.mjs +3 -3
  290. package/build-module/notice/actions.mjs.map +2 -2
  291. package/build-module/notice/close-icon.mjs +3 -3
  292. package/build-module/notice/close-icon.mjs.map +2 -2
  293. package/build-module/notice/description.mjs +3 -3
  294. package/build-module/notice/description.mjs.map +2 -2
  295. package/build-module/notice/index.mjs.map +1 -1
  296. package/build-module/notice/root.mjs +5 -5
  297. package/build-module/notice/root.mjs.map +2 -2
  298. package/build-module/notice/title.mjs +3 -3
  299. package/build-module/notice/title.mjs.map +2 -2
  300. package/build-module/popover/arrow.mjs +59 -0
  301. package/build-module/popover/arrow.mjs.map +7 -0
  302. package/build-module/popover/close.mjs +20 -0
  303. package/build-module/popover/close.mjs.map +7 -0
  304. package/build-module/popover/context.mjs +57 -0
  305. package/build-module/popover/context.mjs.map +7 -0
  306. package/build-module/popover/description.mjs +35 -0
  307. package/build-module/popover/description.mjs.map +7 -0
  308. package/build-module/popover/index.mjs +18 -0
  309. package/build-module/popover/index.mjs.map +7 -0
  310. package/build-module/popover/popup.mjs +105 -0
  311. package/build-module/popover/popup.mjs.map +7 -0
  312. package/build-module/popover/root.mjs +10 -0
  313. package/build-module/popover/root.mjs.map +7 -0
  314. package/build-module/popover/title.mjs +31 -0
  315. package/build-module/popover/title.mjs.map +7 -0
  316. package/build-module/popover/trigger.mjs +13 -0
  317. package/build-module/popover/trigger.mjs.map +7 -0
  318. package/build-module/popover/types.mjs +1 -0
  319. package/build-module/popover/types.mjs.map +7 -0
  320. package/build-module/stack/stack.mjs +2 -2
  321. package/build-module/stack/stack.mjs.map +1 -1
  322. package/build-module/tabs/context.mjs +101 -0
  323. package/build-module/tabs/context.mjs.map +7 -0
  324. package/build-module/tabs/list.mjs +3 -4
  325. package/build-module/tabs/list.mjs.map +2 -2
  326. package/build-module/tabs/panel.mjs +5 -3
  327. package/build-module/tabs/panel.mjs.map +2 -2
  328. package/build-module/tabs/root.mjs +2 -1
  329. package/build-module/tabs/root.mjs.map +2 -2
  330. package/build-module/tabs/tab.mjs +5 -3
  331. package/build-module/tabs/tab.mjs.map +2 -2
  332. package/build-module/text/text.mjs +20 -5
  333. package/build-module/text/text.mjs.map +3 -3
  334. package/build-module/tooltip/popup.mjs +7 -6
  335. package/build-module/tooltip/popup.mjs.map +2 -2
  336. package/build-module/tooltip/root.mjs.map +2 -2
  337. package/build-module/utils/use-deprioritized-initial-focus.mjs +39 -0
  338. package/build-module/utils/use-deprioritized-initial-focus.mjs.map +7 -0
  339. package/build-module/visually-hidden/visually-hidden.mjs +2 -2
  340. package/build-module/visually-hidden/visually-hidden.mjs.map +2 -2
  341. package/build-types/alert-dialog/context.d.ts +11 -0
  342. package/build-types/alert-dialog/context.d.ts.map +1 -0
  343. package/build-types/alert-dialog/index.d.ts +4 -0
  344. package/build-types/alert-dialog/index.d.ts.map +1 -0
  345. package/build-types/alert-dialog/popup.d.ts +4 -0
  346. package/build-types/alert-dialog/popup.d.ts.map +1 -0
  347. package/build-types/alert-dialog/root.d.ts +18 -0
  348. package/build-types/alert-dialog/root.d.ts.map +1 -0
  349. package/build-types/alert-dialog/stories/index.story.d.ts +56 -0
  350. package/build-types/alert-dialog/stories/index.story.d.ts.map +1 -0
  351. package/build-types/alert-dialog/test/index.test.d.ts +2 -0
  352. package/build-types/alert-dialog/test/index.test.d.ts.map +1 -0
  353. package/build-types/alert-dialog/trigger.d.ts +7 -0
  354. package/build-types/alert-dialog/trigger.d.ts.map +1 -0
  355. package/build-types/alert-dialog/types.d.ts +105 -0
  356. package/build-types/alert-dialog/types.d.ts.map +1 -0
  357. package/build-types/badge/badge.d.ts.map +1 -1
  358. package/build-types/button/button.d.ts.map +1 -1
  359. package/build-types/card/stories/index.story.d.ts.map +1 -1
  360. package/build-types/card/title.d.ts.map +1 -1
  361. package/build-types/collapsible/panel.d.ts +2 -1
  362. package/build-types/collapsible/panel.d.ts.map +1 -1
  363. package/build-types/collapsible/root.d.ts +2 -1
  364. package/build-types/collapsible/root.d.ts.map +1 -1
  365. package/build-types/collapsible/trigger.d.ts +2 -1
  366. package/build-types/collapsible/trigger.d.ts.map +1 -1
  367. package/build-types/collapsible-card/content.d.ts.map +1 -1
  368. package/build-types/collapsible-card/context.d.ts +4 -0
  369. package/build-types/collapsible-card/context.d.ts.map +1 -0
  370. package/build-types/collapsible-card/header-description.d.ts +15 -0
  371. package/build-types/collapsible-card/header-description.d.ts.map +1 -0
  372. package/build-types/collapsible-card/header.d.ts.map +1 -1
  373. package/build-types/collapsible-card/index.d.ts +2 -1
  374. package/build-types/collapsible-card/index.d.ts.map +1 -1
  375. package/build-types/collapsible-card/stories/index.story.d.ts +10 -0
  376. package/build-types/collapsible-card/stories/index.story.d.ts.map +1 -1
  377. package/build-types/collapsible-card/types.d.ts +21 -0
  378. package/build-types/collapsible-card/types.d.ts.map +1 -1
  379. package/build-types/dialog/action.d.ts.map +1 -1
  380. package/build-types/dialog/close-icon.d.ts.map +1 -1
  381. package/build-types/dialog/popup.d.ts.map +1 -1
  382. package/build-types/dialog/stories/index.story.d.ts +8 -6
  383. package/build-types/dialog/stories/index.story.d.ts.map +1 -1
  384. package/build-types/dialog/title.d.ts +12 -2
  385. package/build-types/dialog/title.d.ts.map +1 -1
  386. package/build-types/dialog/types.d.ts +13 -6
  387. package/build-types/dialog/types.d.ts.map +1 -1
  388. package/build-types/empty-state/actions.d.ts +7 -0
  389. package/build-types/empty-state/actions.d.ts.map +1 -0
  390. package/build-types/empty-state/description.d.ts +7 -0
  391. package/build-types/empty-state/description.d.ts.map +1 -0
  392. package/build-types/empty-state/icon.d.ts +7 -0
  393. package/build-types/empty-state/icon.d.ts.map +1 -0
  394. package/build-types/empty-state/index.d.ts +8 -0
  395. package/build-types/empty-state/index.d.ts.map +1 -0
  396. package/build-types/empty-state/root.d.ts +6 -0
  397. package/build-types/empty-state/root.d.ts.map +1 -0
  398. package/build-types/empty-state/stories/index.story.d.ts +8 -0
  399. package/build-types/empty-state/stories/index.story.d.ts.map +1 -0
  400. package/build-types/empty-state/test/actions.test.d.ts +2 -0
  401. package/build-types/empty-state/test/actions.test.d.ts.map +1 -0
  402. package/build-types/empty-state/test/description.test.d.ts +2 -0
  403. package/build-types/empty-state/test/description.test.d.ts.map +1 -0
  404. package/build-types/empty-state/test/icon.test.d.ts +2 -0
  405. package/build-types/empty-state/test/icon.test.d.ts.map +1 -0
  406. package/build-types/empty-state/test/root.test.d.ts +2 -0
  407. package/build-types/empty-state/test/root.test.d.ts.map +1 -0
  408. package/build-types/empty-state/test/title.test.d.ts +2 -0
  409. package/build-types/empty-state/test/title.test.d.ts.map +1 -0
  410. package/build-types/empty-state/test/visual.test.d.ts +2 -0
  411. package/build-types/empty-state/test/visual.test.d.ts.map +1 -0
  412. package/build-types/empty-state/title.d.ts +6 -0
  413. package/build-types/empty-state/title.d.ts.map +1 -0
  414. package/build-types/empty-state/types.d.ts +40 -0
  415. package/build-types/empty-state/types.d.ts.map +1 -0
  416. package/build-types/empty-state/visual.d.ts +7 -0
  417. package/build-types/empty-state/visual.d.ts.map +1 -0
  418. package/build-types/form/index.d.ts +3 -0
  419. package/build-types/form/index.d.ts.map +1 -0
  420. package/build-types/form/input-control/index.d.ts +2 -0
  421. package/build-types/form/input-control/index.d.ts.map +1 -0
  422. package/build-types/form/input-control/input-control.d.ts +6 -0
  423. package/build-types/form/input-control/input-control.d.ts.map +1 -0
  424. package/build-types/form/input-control/stories/index.story.d.ts +16 -0
  425. package/build-types/form/input-control/stories/index.story.d.ts.map +1 -0
  426. package/build-types/form/input-control/test/index.test.d.ts +2 -0
  427. package/build-types/form/input-control/test/index.test.d.ts.map +1 -0
  428. package/build-types/form/input-control/types.d.ts +4 -0
  429. package/build-types/form/input-control/types.d.ts.map +1 -0
  430. package/build-types/form/primitives/field/description.d.ts +2 -1
  431. package/build-types/form/primitives/field/description.d.ts.map +1 -1
  432. package/build-types/form/primitives/field/details.d.ts +2 -1
  433. package/build-types/form/primitives/field/details.d.ts.map +1 -1
  434. package/build-types/form/primitives/field/label.d.ts +2 -1
  435. package/build-types/form/primitives/field/label.d.ts.map +1 -1
  436. package/build-types/form/primitives/field/stories/index.story.d.ts.map +1 -1
  437. package/build-types/form/primitives/fieldset/description.d.ts +2 -1
  438. package/build-types/form/primitives/fieldset/description.d.ts.map +1 -1
  439. package/build-types/form/primitives/fieldset/details.d.ts +2 -1
  440. package/build-types/form/primitives/fieldset/details.d.ts.map +1 -1
  441. package/build-types/form/primitives/fieldset/legend.d.ts +2 -1
  442. package/build-types/form/primitives/fieldset/legend.d.ts.map +1 -1
  443. package/build-types/form/primitives/fieldset/root.d.ts +2 -1
  444. package/build-types/form/primitives/fieldset/root.d.ts.map +1 -1
  445. package/build-types/form/primitives/fieldset/stories/index.story.d.ts.map +1 -1
  446. package/build-types/form/primitives/input/input.d.ts.map +1 -1
  447. package/build-types/form/primitives/input/stories/index.story.d.ts +2 -0
  448. package/build-types/form/primitives/input/stories/index.story.d.ts.map +1 -1
  449. package/build-types/form/primitives/input-layout/input-layout.d.ts.map +1 -1
  450. package/build-types/form/primitives/input-layout/slot.d.ts.map +1 -1
  451. package/build-types/form/primitives/input-layout/stories/index.story.d.ts +5 -0
  452. package/build-types/form/primitives/input-layout/stories/index.story.d.ts.map +1 -1
  453. package/build-types/form/primitives/select/item.d.ts +6 -2
  454. package/build-types/form/primitives/select/item.d.ts.map +1 -1
  455. package/build-types/form/primitives/select/popup.d.ts +11 -1
  456. package/build-types/form/primitives/select/popup.d.ts.map +1 -1
  457. package/build-types/form/primitives/select/trigger.d.ts +12 -2
  458. package/build-types/form/primitives/select/trigger.d.ts.map +1 -1
  459. package/build-types/form/primitives/select/types.d.ts +13 -3
  460. package/build-types/form/primitives/select/types.d.ts.map +1 -1
  461. package/build-types/form/primitives/textarea/textarea.d.ts.map +1 -1
  462. package/build-types/form/stories/shared.d.ts +3 -0
  463. package/build-types/form/stories/shared.d.ts.map +1 -0
  464. package/build-types/form/types.d.ts +30 -0
  465. package/build-types/form/types.d.ts.map +1 -0
  466. package/build-types/index.d.ts +4 -1
  467. package/build-types/index.d.ts.map +1 -1
  468. package/build-types/link/link.d.ts.map +1 -1
  469. package/build-types/notice/index.d.ts +0 -1
  470. package/build-types/notice/index.d.ts.map +1 -1
  471. package/build-types/popover/arrow.d.ts +10 -0
  472. package/build-types/popover/arrow.d.ts.map +1 -0
  473. package/build-types/popover/close.d.ts +11 -0
  474. package/build-types/popover/close.d.ts.map +1 -0
  475. package/build-types/popover/context.d.ts +22 -0
  476. package/build-types/popover/context.d.ts.map +1 -0
  477. package/build-types/popover/description.d.ts +10 -0
  478. package/build-types/popover/description.d.ts.map +1 -0
  479. package/build-types/popover/index.d.ts +9 -0
  480. package/build-types/popover/index.d.ts.map +1 -0
  481. package/build-types/popover/popup.d.ts +11 -0
  482. package/build-types/popover/popup.d.ts.map +1 -0
  483. package/build-types/popover/root.d.ts +37 -0
  484. package/build-types/popover/root.d.ts.map +1 -0
  485. package/build-types/popover/stories/index.story.d.ts +211 -0
  486. package/build-types/popover/stories/index.story.d.ts.map +1 -0
  487. package/build-types/popover/stories/utils.d.ts +25 -0
  488. package/build-types/popover/stories/utils.d.ts.map +1 -0
  489. package/build-types/popover/test/index.test.d.ts +2 -0
  490. package/build-types/popover/test/index.test.d.ts.map +1 -0
  491. package/build-types/popover/title.d.ts +20 -0
  492. package/build-types/popover/title.d.ts.map +1 -0
  493. package/build-types/popover/trigger.d.ts +10 -0
  494. package/build-types/popover/trigger.d.ts.map +1 -0
  495. package/build-types/popover/types.d.ts +83 -0
  496. package/build-types/popover/types.d.ts.map +1 -0
  497. package/build-types/tabs/context.d.ts +26 -0
  498. package/build-types/tabs/context.d.ts.map +1 -0
  499. package/build-types/tabs/list.d.ts +2 -1
  500. package/build-types/tabs/list.d.ts.map +1 -1
  501. package/build-types/tabs/panel.d.ts +2 -1
  502. package/build-types/tabs/panel.d.ts.map +1 -1
  503. package/build-types/tabs/root.d.ts +2 -1
  504. package/build-types/tabs/root.d.ts.map +1 -1
  505. package/build-types/tabs/tab.d.ts +2 -1
  506. package/build-types/tabs/tab.d.ts.map +1 -1
  507. package/build-types/text/stories/index.story.d.ts +4 -0
  508. package/build-types/text/stories/index.story.d.ts.map +1 -1
  509. package/build-types/text/text.d.ts.map +1 -1
  510. package/build-types/tooltip/popup.d.ts.map +1 -1
  511. package/build-types/tooltip/root.d.ts +13 -0
  512. package/build-types/tooltip/root.d.ts.map +1 -1
  513. package/build-types/tooltip/stories/index.story.d.ts.map +1 -1
  514. package/build-types/tooltip/stories/usage-guidelines.story.d.ts +21 -0
  515. package/build-types/tooltip/stories/usage-guidelines.story.d.ts.map +1 -0
  516. package/build-types/tooltip/types.d.ts +4 -0
  517. package/build-types/tooltip/types.d.ts.map +1 -1
  518. package/build-types/utils/test/use-deprioritized-initial-focus.test.d.ts +2 -0
  519. package/build-types/utils/test/use-deprioritized-initial-focus.test.d.ts.map +1 -0
  520. package/build-types/utils/types.d.ts +6 -2
  521. package/build-types/utils/types.d.ts.map +1 -1
  522. package/build-types/utils/use-deprioritized-initial-focus.d.ts +36 -0
  523. package/build-types/utils/use-deprioritized-initial-focus.d.ts.map +1 -0
  524. package/build-types/visually-hidden/stories/index.story.d.ts +7 -0
  525. package/build-types/visually-hidden/stories/index.story.d.ts.map +1 -1
  526. package/build-types/visually-hidden/visually-hidden.d.ts +34 -0
  527. package/build-types/visually-hidden/visually-hidden.d.ts.map +1 -1
  528. package/package.json +17 -16
  529. package/src/alert-dialog/context.tsx +22 -0
  530. package/src/alert-dialog/index.ts +3 -0
  531. package/src/alert-dialog/popup.tsx +116 -0
  532. package/src/alert-dialog/root.tsx +226 -0
  533. package/src/alert-dialog/stories/index.story.tsx +305 -0
  534. package/src/alert-dialog/style.module.css +21 -0
  535. package/src/alert-dialog/test/index.test.tsx +1509 -0
  536. package/src/alert-dialog/trigger.tsx +15 -0
  537. package/src/alert-dialog/types.ts +119 -0
  538. package/src/badge/badge.tsx +11 -14
  539. package/src/badge/style.module.css +0 -4
  540. package/src/button/button.tsx +2 -0
  541. package/src/button/style.module.css +9 -3
  542. package/src/card/stories/index.story.tsx +4 -5
  543. package/src/card/style.module.css +4 -10
  544. package/src/card/test/index.test.tsx +17 -1
  545. package/src/card/title.tsx +14 -12
  546. package/src/collapsible-card/content.tsx +16 -3
  547. package/src/collapsible-card/context.ts +7 -0
  548. package/src/collapsible-card/header-description.tsx +43 -0
  549. package/src/collapsible-card/header.tsx +47 -24
  550. package/src/collapsible-card/index.ts +2 -1
  551. package/src/collapsible-card/stories/index.story.tsx +102 -4
  552. package/src/collapsible-card/style.module.css +34 -2
  553. package/src/collapsible-card/test/index.test.tsx +96 -9
  554. package/src/collapsible-card/types.ts +22 -0
  555. package/src/dialog/action.tsx +8 -2
  556. package/src/dialog/close-icon.tsx +1 -0
  557. package/src/dialog/popup.tsx +23 -3
  558. package/src/dialog/stories/index.story.tsx +33 -28
  559. package/src/dialog/style.module.css +18 -14
  560. package/src/dialog/test/index.test.tsx +180 -4
  561. package/src/dialog/title.tsx +21 -9
  562. package/src/dialog/types.ts +20 -6
  563. package/src/empty-state/actions.tsx +24 -0
  564. package/src/empty-state/description.tsx +31 -0
  565. package/src/empty-state/icon.tsx +24 -0
  566. package/src/empty-state/index.ts +8 -0
  567. package/src/empty-state/root.tsx +23 -0
  568. package/src/empty-state/stories/index.story.tsx +64 -0
  569. package/src/empty-state/style.module.css +53 -0
  570. package/src/empty-state/test/actions.test.tsx +18 -0
  571. package/src/empty-state/test/description.test.tsx +26 -0
  572. package/src/empty-state/test/icon.test.tsx +13 -0
  573. package/src/empty-state/test/root.test.tsx +13 -0
  574. package/src/empty-state/test/title.test.tsx +26 -0
  575. package/src/empty-state/test/visual.test.tsx +17 -0
  576. package/src/empty-state/title.tsx +29 -0
  577. package/src/empty-state/types.ts +45 -0
  578. package/src/empty-state/visual.tsx +24 -0
  579. package/src/form/index.ts +3 -0
  580. package/src/form/input-control/index.ts +1 -0
  581. package/src/form/input-control/input-control.tsx +33 -0
  582. package/src/form/input-control/stories/index.story.tsx +163 -0
  583. package/src/form/input-control/test/index.test.tsx +53 -0
  584. package/src/form/input-control/types.ts +5 -0
  585. package/src/form/primitives/field/description.tsx +6 -1
  586. package/src/form/primitives/field/details.tsx +4 -2
  587. package/src/form/primitives/field/label.tsx +9 -5
  588. package/src/form/primitives/field/stories/index.story.tsx +2 -7
  589. package/src/form/primitives/field/test/index.test.tsx +11 -0
  590. package/src/form/primitives/fieldset/description.tsx +9 -1
  591. package/src/form/primitives/fieldset/legend.tsx +9 -4
  592. package/src/form/primitives/fieldset/stories/index.story.tsx +2 -7
  593. package/src/form/primitives/fieldset/test/index.test.tsx +22 -0
  594. package/src/form/primitives/input/input.tsx +6 -1
  595. package/src/form/primitives/input/stories/index.story.tsx +7 -0
  596. package/src/form/primitives/input/style.module.css +4 -0
  597. package/src/form/primitives/input-layout/input-layout.tsx +2 -0
  598. package/src/form/primitives/input-layout/slot.tsx +6 -2
  599. package/src/form/primitives/input-layout/stories/index.story.tsx +22 -1
  600. package/src/form/primitives/input-layout/style.module.css +3 -3
  601. package/src/form/primitives/select/popup.tsx +5 -2
  602. package/src/form/primitives/select/test/index.test.tsx +60 -1
  603. package/src/form/primitives/select/types.ts +14 -4
  604. package/src/form/primitives/stories/overview.mdx +15 -0
  605. package/src/form/primitives/textarea/textarea.tsx +11 -2
  606. package/src/form/stories/shared.tsx +21 -0
  607. package/src/form/types.ts +34 -0
  608. package/src/index.ts +4 -1
  609. package/src/link/link.tsx +2 -0
  610. package/src/link/style.module.css +11 -1
  611. package/src/notice/index.ts +0 -2
  612. package/src/notice/style.module.css +6 -6
  613. package/src/popover/arrow.tsx +49 -0
  614. package/src/popover/close.tsx +24 -0
  615. package/src/popover/context.tsx +100 -0
  616. package/src/popover/description.tsx +29 -0
  617. package/src/popover/index.ts +9 -0
  618. package/src/popover/popup.tsx +106 -0
  619. package/src/popover/root.tsx +41 -0
  620. package/src/popover/stories/index.story.tsx +1315 -0
  621. package/src/popover/stories/utils.tsx +91 -0
  622. package/src/popover/style.module.css +64 -0
  623. package/src/popover/test/index.test.tsx +727 -0
  624. package/src/popover/title.tsx +47 -0
  625. package/src/popover/trigger.tsx +17 -0
  626. package/src/popover/types.ts +113 -0
  627. package/src/tabs/context.tsx +170 -0
  628. package/src/tabs/list.tsx +0 -1
  629. package/src/tabs/panel.tsx +3 -0
  630. package/src/tabs/root.tsx +6 -1
  631. package/src/tabs/style.module.css +3 -3
  632. package/src/tabs/tab.tsx +3 -0
  633. package/src/tabs/test/index.test.tsx +162 -0
  634. package/src/text/stories/index.story.tsx +4 -2
  635. package/src/text/style.module.css +62 -36
  636. package/src/text/test/index.test.tsx +1 -4
  637. package/src/text/text.tsx +8 -1
  638. package/src/tooltip/popup.tsx +2 -1
  639. package/src/tooltip/root.tsx +13 -0
  640. package/src/tooltip/stories/index.story.tsx +20 -15
  641. package/src/tooltip/stories/usage-guidelines.mdx +91 -0
  642. package/src/tooltip/stories/usage-guidelines.story.tsx +119 -0
  643. package/src/tooltip/style.module.css +2 -2
  644. package/src/tooltip/test/index.test.tsx +61 -0
  645. package/src/tooltip/types.ts +5 -0
  646. package/src/utils/css/field.module.css +12 -9
  647. package/src/utils/css/focus.module.css +7 -5
  648. package/src/utils/css/global-css-defense.module.css +117 -0
  649. package/src/utils/css/item-popup.module.css +3 -2
  650. package/src/utils/css/select-trigger.module.css +1 -0
  651. package/src/utils/test/use-deprioritized-initial-focus.test.tsx +230 -0
  652. package/src/utils/types.ts +7 -2
  653. package/src/utils/use-deprioritized-initial-focus.ts +84 -0
  654. package/src/visually-hidden/stories/index.story.tsx +25 -0
  655. package/src/visually-hidden/visually-hidden.tsx +34 -0
@@ -0,0 +1,116 @@
1
+ import { AlertDialog as _AlertDialog } from '@base-ui/react/alert-dialog';
2
+ import clsx from 'clsx';
3
+ import { forwardRef, useContext } from '@wordpress/element';
4
+ import { __ } from '@wordpress/i18n';
5
+ import {
6
+ type ThemeProvider as ThemeProviderType,
7
+ privateApis as themePrivateApis,
8
+ } from '@wordpress/theme';
9
+
10
+ import { Button } from '../button';
11
+ import dialogStyles from '../dialog/style.module.css';
12
+ import { unlock } from '../lock-unlock';
13
+ import { Stack } from '../stack';
14
+ import { Text } from '../text';
15
+ import { AlertDialogContext } from './context';
16
+ import alertDialogStyles from './style.module.css';
17
+ import type { PopupProps } from './types';
18
+
19
+ const ThemeProvider: typeof ThemeProviderType =
20
+ unlock( themePrivateApis ).ThemeProvider;
21
+
22
+ const Popup = forwardRef< HTMLDivElement, PopupProps >(
23
+ function AlertDialogPopup(
24
+ {
25
+ className,
26
+ container,
27
+ intent = 'default',
28
+ title,
29
+ description,
30
+ children,
31
+ confirmButtonText = __( 'OK' ),
32
+ cancelButtonText = __( 'Cancel' ),
33
+ ...props
34
+ },
35
+ ref
36
+ ) {
37
+ const { phase, showSpinner, errorMessage, confirm } =
38
+ useContext( AlertDialogContext );
39
+
40
+ const confirmClassName =
41
+ intent === 'irreversible'
42
+ ? alertDialogStyles[ 'irreversible-action' ]
43
+ : undefined;
44
+
45
+ const buttonsDisabled = phase !== 'idle' || undefined;
46
+
47
+ return (
48
+ <_AlertDialog.Portal container={ container }>
49
+ <_AlertDialog.Backdrop className={ dialogStyles.backdrop } />
50
+ <ThemeProvider>
51
+ <_AlertDialog.Popup
52
+ ref={ ref }
53
+ className={ clsx(
54
+ dialogStyles.popup,
55
+ className,
56
+ dialogStyles[ 'is-medium' ]
57
+ ) }
58
+ { ...props }
59
+ >
60
+ <Stack
61
+ direction="column"
62
+ gap="sm"
63
+ className={ alertDialogStyles.header }
64
+ >
65
+ <Text
66
+ variant="heading-xl"
67
+ render={ <_AlertDialog.Title /> }
68
+ >
69
+ { title }
70
+ </Text>
71
+ { description && (
72
+ <Text
73
+ variant="body-md"
74
+ render={ <_AlertDialog.Description /> }
75
+ >
76
+ { description }
77
+ </Text>
78
+ ) }
79
+ </Stack>
80
+ { children }
81
+ <Stack direction="column" gap="md">
82
+ <div className={ dialogStyles.footer }>
83
+ <_AlertDialog.Close
84
+ render={ <Button variant="minimal" /> }
85
+ disabled={ buttonsDisabled }
86
+ >
87
+ { cancelButtonText }
88
+ </_AlertDialog.Close>
89
+ <Button
90
+ className={ confirmClassName }
91
+ onClick={ confirm }
92
+ loading={ showSpinner || undefined }
93
+ disabled={ buttonsDisabled }
94
+ >
95
+ { confirmButtonText }
96
+ </Button>
97
+ </div>
98
+ { errorMessage && (
99
+ <Text
100
+ variant="body-sm"
101
+ className={
102
+ alertDialogStyles[ 'error-message' ]
103
+ }
104
+ >
105
+ { errorMessage }
106
+ </Text>
107
+ ) }
108
+ </Stack>
109
+ </_AlertDialog.Popup>
110
+ </ThemeProvider>
111
+ </_AlertDialog.Portal>
112
+ );
113
+ }
114
+ );
115
+
116
+ export { Popup };
@@ -0,0 +1,226 @@
1
+ import { AlertDialog as _AlertDialog } from '@base-ui/react/alert-dialog';
2
+ import { speak } from '@wordpress/a11y';
3
+ import {
4
+ useCallback,
5
+ useEffect,
6
+ useMemo,
7
+ useRef,
8
+ useState,
9
+ } from '@wordpress/element';
10
+
11
+ import { AlertDialogContext } from './context';
12
+ import type { Phase } from './context';
13
+ import type { RootProps } from './types';
14
+
15
+ function isThenable( value: unknown ): value is PromiseLike< unknown > {
16
+ return (
17
+ value !== null &&
18
+ value !== undefined &&
19
+ typeof ( value as PromiseLike< unknown > ).then === 'function'
20
+ );
21
+ }
22
+
23
+ /**
24
+ * A dialog that requires a user response to proceed.
25
+ *
26
+ * Use `AlertDialog.Trigger` to render a button that opens the dialog.
27
+ * Use `AlertDialog.Popup` to render the dialog content.
28
+ * The `AlertDialog.Trigger` is optional — the dialog can also be controlled
29
+ * via `open` / `onOpenChange` props.
30
+ *
31
+ * For use cases outside the standard confirm/cancel pattern, use the lower-level
32
+ * `Dialog` component directly.
33
+ *
34
+ * See the [Destructive Actions guidelines](https://wordpress.github.io/gutenberg/?path=/docs/design-system-patterns-destructive-actions--docs)
35
+ * for more details on when to use each pattern.
36
+ */
37
+ function Root( {
38
+ children,
39
+ open: openProp,
40
+ onOpenChange,
41
+ defaultOpen,
42
+ onConfirm,
43
+ }: RootProps ) {
44
+ const [ internalOpen, setInternalOpen ] = useState( defaultOpen ?? false );
45
+
46
+ // Internal state machine for the confirm-and-close lifecycle.
47
+ //
48
+ // Phase transitions:
49
+ //
50
+ // idle ──> pending ──> closing ──> idle
51
+ // (confirm (success, (animation
52
+ // clicked) close) complete)
53
+ //
54
+ // idle ──> pending ──> idle
55
+ // (confirm (error, or
56
+ // clicked) {close:false})
57
+ //
58
+ // idle ──> closing ──> idle
59
+ // (cancel/ (animation
60
+ // escape) complete)
61
+ //
62
+ // `showSpinner` tracks whether the confirm button shows a loading
63
+ // indicator. It is orthogonal to `phase`:
64
+ //
65
+ // Scenario | pending | closing
66
+ // --------------------------+---------+---------
67
+ // Sync onConfirm | false | false
68
+ // Async onConfirm (success) | true | true
69
+ // Async onConfirm (error) | true | n/a (-> idle)
70
+ // Cancel / Escape | n/a | false
71
+ //
72
+ // Buttons are disabled whenever phase !== 'idle'.
73
+ // Dismiss (Escape / Cancel) is blocked during 'pending'.
74
+ const [ phase, setPhase ] = useState< Phase >( 'idle' );
75
+ const [ showSpinner, setShowSpinner ] = useState( false );
76
+ const [ errorMessage, setErrorMessage ] = useState< string >();
77
+
78
+ const actionsRef = useRef< _AlertDialog.Root.Actions | null >( null );
79
+
80
+ const onConfirmRef = useRef( onConfirm );
81
+ onConfirmRef.current = onConfirm;
82
+
83
+ // Ref keeps phase accessible synchronously from callbacks that may
84
+ // run between a setState call and the subsequent React re-render.
85
+ const phaseRef = useRef( phase );
86
+ phaseRef.current = phase;
87
+
88
+ // Generation counter — safety net for the edge case where the component
89
+ // unmounts while an async confirm is in flight. Also incremented when
90
+ // the dialog finishes closing, so a stale promise settling after a
91
+ // dismiss+reopen cycle is silently discarded.
92
+ const confirmIdRef = useRef( 0 );
93
+
94
+ const effectiveOpen = openProp ?? internalOpen;
95
+
96
+ // Safety net: if the consumer keeps `open={true}` after a confirm
97
+ // (i.e. does not react to `onOpenChange`), the phase would be stuck
98
+ // at 'closing'. Detect the contradiction and reset to idle.
99
+ useEffect( () => {
100
+ if ( effectiveOpen && phase === 'closing' ) {
101
+ phaseRef.current = 'idle';
102
+ setPhase( 'idle' );
103
+ setShowSpinner( false );
104
+ }
105
+ }, [ effectiveOpen, phase ] );
106
+
107
+ const handleOpenChange = useCallback(
108
+ (
109
+ nextOpen: boolean,
110
+ eventDetails: _AlertDialog.Root.ChangeEventDetails
111
+ ) => {
112
+ // Block dismiss while a confirm action is pending.
113
+ if ( ! nextOpen && phaseRef.current === 'pending' ) {
114
+ return;
115
+ }
116
+
117
+ if ( ! nextOpen && phaseRef.current === 'idle' ) {
118
+ phaseRef.current = 'closing';
119
+ setPhase( 'closing' );
120
+ }
121
+
122
+ setInternalOpen( nextOpen );
123
+ onOpenChange?.( nextOpen, eventDetails );
124
+ },
125
+ [ onOpenChange ]
126
+ );
127
+
128
+ const confirm = useCallback( async () => {
129
+ if ( phaseRef.current !== 'idle' ) {
130
+ return;
131
+ }
132
+
133
+ phaseRef.current = 'pending';
134
+ setPhase( 'pending' );
135
+ setErrorMessage( undefined );
136
+
137
+ const id = ++confirmIdRef.current;
138
+
139
+ try {
140
+ const rawResult = onConfirmRef.current?.();
141
+
142
+ // Show spinner only for async handlers (Promises).
143
+ // Sync handlers resolve in the same tick — no spinner needed.
144
+ if ( isThenable( rawResult ) ) {
145
+ setShowSpinner( true );
146
+ }
147
+
148
+ const result = await Promise.resolve( rawResult );
149
+
150
+ // Discard if the component unmounted or the dialog was
151
+ // dismissed and reopened while the promise was in flight.
152
+ if ( confirmIdRef.current !== id ) {
153
+ return;
154
+ }
155
+
156
+ // An error message implies the dialog should stay open.
157
+ if ( result?.error ) {
158
+ phaseRef.current = 'idle';
159
+ setPhase( 'idle' );
160
+ setShowSpinner( false );
161
+ setErrorMessage( result.error );
162
+ speak( result.error, 'assertive' );
163
+ return;
164
+ }
165
+
166
+ const shouldClose = result?.close !== false;
167
+
168
+ if ( shouldClose ) {
169
+ phaseRef.current = 'closing';
170
+ setPhase( 'closing' );
171
+ actionsRef.current?.close();
172
+ } else {
173
+ phaseRef.current = 'idle';
174
+ setPhase( 'idle' );
175
+ setShowSpinner( false );
176
+ }
177
+ } catch ( error ) {
178
+ if ( confirmIdRef.current !== id ) {
179
+ return;
180
+ }
181
+ phaseRef.current = 'idle';
182
+ setPhase( 'idle' );
183
+ setShowSpinner( false );
184
+ // eslint-disable-next-line no-console
185
+ console.error( error );
186
+ }
187
+ }, [] );
188
+
189
+ const handleOpenChangeComplete = useCallback( ( open: boolean ) => {
190
+ if ( ! open ) {
191
+ // Invalidate any in-flight async so a stale promise settling
192
+ // after dismiss+reopen doesn't close the new session.
193
+ confirmIdRef.current++;
194
+ phaseRef.current = 'idle';
195
+ setPhase( 'idle' );
196
+ setShowSpinner( false );
197
+ setErrorMessage( undefined );
198
+ }
199
+ }, [] );
200
+
201
+ const contextValue = useMemo(
202
+ () => ( {
203
+ phase,
204
+ showSpinner,
205
+ errorMessage,
206
+ confirm,
207
+ } ),
208
+ [ phase, showSpinner, errorMessage, confirm ]
209
+ );
210
+
211
+ return (
212
+ <_AlertDialog.Root
213
+ open={ effectiveOpen }
214
+ defaultOpen={ defaultOpen }
215
+ onOpenChange={ handleOpenChange }
216
+ onOpenChangeComplete={ handleOpenChangeComplete }
217
+ actionsRef={ actionsRef }
218
+ >
219
+ <AlertDialogContext.Provider value={ contextValue }>
220
+ { children }
221
+ </AlertDialogContext.Provider>
222
+ </_AlertDialog.Root>
223
+ );
224
+ }
225
+
226
+ export { Root };
@@ -0,0 +1,305 @@
1
+ import { Menu } from '@base-ui/react/menu';
2
+ import { useId, useState } from '@wordpress/element';
3
+ import type { Meta, StoryObj } from '@storybook/react-vite';
4
+ import { action } from 'storybook/actions';
5
+ import { fn } from 'storybook/test';
6
+
7
+ import { AlertDialog, Text } from '../..';
8
+
9
+ const meta: Meta< typeof AlertDialog.Root > = {
10
+ title: 'Design System/Components/AlertDialog',
11
+ component: AlertDialog.Root,
12
+ subcomponents: {
13
+ 'AlertDialog.Trigger': AlertDialog.Trigger,
14
+ 'AlertDialog.Popup': AlertDialog.Popup,
15
+ },
16
+ argTypes: {
17
+ onConfirm: { action: fn() },
18
+ onOpenChange: { action: fn() },
19
+ },
20
+ };
21
+ export default meta;
22
+
23
+ type Story = StoryObj< typeof AlertDialog.Root >;
24
+
25
+ /**
26
+ * Standard confirmation dialog for reversible actions. The dialog can be
27
+ * dismissed via Escape key or the cancel/confirm buttons. Backdrop click
28
+ * is blocked.
29
+ */
30
+ export const Default: Story = {
31
+ args: {
32
+ children: (
33
+ <>
34
+ <AlertDialog.Trigger>Move to trash</AlertDialog.Trigger>
35
+ <AlertDialog.Popup
36
+ title="Move to trash?"
37
+ description="This post will be moved to trash. You can restore it later."
38
+ />
39
+ </>
40
+ ),
41
+ },
42
+ };
43
+
44
+ /**
45
+ * Confirmation dialog for irreversible actions that cannot be undone.
46
+ * The confirm button uses error/danger coloring.
47
+ */
48
+ export const Irreversible: Story = {
49
+ args: {
50
+ children: (
51
+ <>
52
+ <AlertDialog.Trigger>Delete permanently</AlertDialog.Trigger>
53
+ <AlertDialog.Popup
54
+ intent="irreversible"
55
+ title="Delete permanently?"
56
+ description="This action cannot be undone. All data will be lost."
57
+ confirmButtonText="Delete permanently"
58
+ />
59
+ </>
60
+ ),
61
+ },
62
+ };
63
+
64
+ /**
65
+ * Example with custom button labels for both confirm and cancel buttons.
66
+ */
67
+ export const CustomLabels: Story = {
68
+ args: {
69
+ children: (
70
+ <>
71
+ <AlertDialog.Trigger>Send feedback</AlertDialog.Trigger>
72
+ <AlertDialog.Popup
73
+ title="Send feedback?"
74
+ description="Your feedback helps us improve. Would you like to send it now?"
75
+ confirmButtonText="Send feedback"
76
+ cancelButtonText="Not now"
77
+ />
78
+ </>
79
+ ),
80
+ },
81
+ };
82
+
83
+ /**
84
+ * Use `children` to render custom content between the description and the
85
+ * action buttons. The `description` should be self-contained for
86
+ * accessibility (`aria-describedby`); `children` adds supplementary detail.
87
+ */
88
+ export const WithCustomContent: Story = {
89
+ args: {
90
+ children: (
91
+ <>
92
+ <AlertDialog.Trigger>Remove pages</AlertDialog.Trigger>
93
+ <AlertDialog.Popup
94
+ title="Remove 3 pages?"
95
+ description="These pages will be moved to trash."
96
+ confirmButtonText="Delete pages"
97
+ >
98
+ <ul
99
+ style={ {
100
+ margin: 0,
101
+ paddingInlineStart: 'var(--wpds-dimension-gap-lg)',
102
+ } }
103
+ >
104
+ <Text render={ <li /> }>About us</Text>
105
+ <Text render={ <li /> }>Contact</Text>
106
+ <Text render={ <li /> }>Privacy policy</Text>
107
+ </ul>
108
+ </AlertDialog.Popup>
109
+ </>
110
+ ),
111
+ },
112
+ };
113
+
114
+ const menuPopupStyles: React.CSSProperties = {
115
+ background: 'var(--wpds-color-bg-surface-neutral-strong)',
116
+ border: '1px solid var(--wpds-color-stroke-surface-neutral)',
117
+ borderRadius: '8px',
118
+ padding: '4px',
119
+ minWidth: '160px',
120
+ boxShadow: '0 4px 12px rgba(0, 0, 0, 0.1)',
121
+ };
122
+
123
+ const menuItemStyles: React.CSSProperties = {
124
+ display: 'block',
125
+ width: '100%',
126
+ padding: '8px 12px',
127
+ borderRadius: '4px',
128
+ border: 'none',
129
+ background: 'none',
130
+ textAlign: 'start',
131
+ fontSize: 'inherit',
132
+ userSelect: 'none',
133
+ };
134
+
135
+ /**
136
+ * Example showing composition with a menu. The `AlertDialog.Trigger` is
137
+ * composed with Base UI's `Menu.Item` using the `render` prop, allowing the
138
+ * menu item to directly trigger the alert dialog.
139
+ *
140
+ * Note: the example currently uses the `Menu` component from BaseUI, although
141
+ * consumers should not use BaseUI directly and instead use the DS `Menu`
142
+ * component (not ready yet).
143
+ */
144
+ export const MenuTrigger: Story = {
145
+ render: () => {
146
+ const [ menuOpen, setMenuOpen ] = useState( false );
147
+ return (
148
+ <>
149
+ <Menu.Root onOpenChange={ setMenuOpen } open={ menuOpen }>
150
+ <Menu.Trigger>Actions ▾</Menu.Trigger>
151
+ <Menu.Portal>
152
+ <Menu.Positioner>
153
+ <Menu.Popup style={ menuPopupStyles }>
154
+ <Menu.Item style={ menuItemStyles }>
155
+ Edit
156
+ </Menu.Item>
157
+ <AlertDialog.Root
158
+ onConfirm={ () => {
159
+ setMenuOpen( false );
160
+ action( 'onConfirm' )();
161
+ } }
162
+ >
163
+ <Menu.Item
164
+ render={
165
+ <AlertDialog.Trigger
166
+ // Quick fix to remove `button`-specific styles.
167
+ // This shouldn't be an issue once we use the DS `Menu`
168
+ // component, which will come with item styles.
169
+ render={ <div /> }
170
+ />
171
+ }
172
+ style={ menuItemStyles }
173
+ closeOnClick={ false }
174
+ >
175
+ Delete...
176
+ <AlertDialog.Popup
177
+ intent="irreversible"
178
+ title="Delete permanently?"
179
+ description="This action cannot be undone. All data will be lost."
180
+ confirmButtonText="Delete permanently"
181
+ />
182
+ </Menu.Item>
183
+ </AlertDialog.Root>
184
+ </Menu.Popup>
185
+ </Menu.Positioner>
186
+ </Menu.Portal>
187
+ </Menu.Root>
188
+ </>
189
+ );
190
+ },
191
+ };
192
+
193
+ function sleep( ms: number ) {
194
+ return new Promise< void >( ( resolve ) => setTimeout( resolve, ms ) );
195
+ }
196
+
197
+ /**
198
+ * Async confirm flow. The consumer returns a promise from `onConfirm`.
199
+ * The dialog automatically manages the pending state: buttons are disabled
200
+ * and a spinner appears on the confirm button. Toggle between success and
201
+ * failure to test both outcomes.
202
+ *
203
+ * On failure, the consumer catches the error and returns
204
+ * `{ close: false, error: '...' }`. The component displays the message
205
+ * below the action buttons and announces it to screen readers. The error
206
+ * is automatically cleared on the next confirm attempt or when the dialog
207
+ * reopens.
208
+ */
209
+ export const AsyncConfirm: Story = {
210
+ render: function AsyncConfirm( args ) {
211
+ const [ shouldFail, setShouldFail ] = useState( false );
212
+ const successId = useId();
213
+ const failureId = useId();
214
+
215
+ return (
216
+ <>
217
+ <fieldset>
218
+ <legend>Async task outcome</legend>
219
+ <label htmlFor={ successId }>
220
+ <input
221
+ id={ successId }
222
+ type="radio"
223
+ name="async-outcome"
224
+ checked={ ! shouldFail }
225
+ onChange={ () => setShouldFail( false ) }
226
+ />
227
+ Success (closes dialog)
228
+ </label>
229
+ <label
230
+ htmlFor={ failureId }
231
+ style={ { marginInlineStart: 12 } }
232
+ >
233
+ <input
234
+ id={ failureId }
235
+ type="radio"
236
+ name="async-outcome"
237
+ checked={ shouldFail }
238
+ onChange={ () => setShouldFail( true ) }
239
+ />
240
+ Failure (dialog stays open, shows error)
241
+ </label>
242
+ </fieldset>
243
+ <br />
244
+ <AlertDialog.Root
245
+ { ...args }
246
+ onConfirm={ async () => {
247
+ action( 'onConfirm' )();
248
+ try {
249
+ await sleep( 2000 );
250
+ if ( shouldFail ) {
251
+ throw new Error( 'Task failed' );
252
+ }
253
+ } catch {
254
+ return {
255
+ close: false,
256
+ error: 'Something went wrong. Please try again.',
257
+ };
258
+ }
259
+ return undefined;
260
+ } }
261
+ >
262
+ <AlertDialog.Trigger>
263
+ Delete permanently
264
+ </AlertDialog.Trigger>
265
+ <AlertDialog.Popup
266
+ intent="irreversible"
267
+ title="Delete permanently?"
268
+ description="This action cannot be undone. All data will be lost."
269
+ confirmButtonText="Delete permanently"
270
+ />
271
+ </AlertDialog.Root>
272
+ </>
273
+ );
274
+ },
275
+ };
276
+
277
+ /**
278
+ * The `AlertDialog.Trigger` element is not necessary when the open state is
279
+ * controlled externally. This is useful when the dialog needs to be opened
280
+ * from code or from a non-standard trigger element.
281
+ */
282
+ export const Controlled: Story = {
283
+ render: function Controlled( args ) {
284
+ const [ isOpen, setIsOpen ] = useState( false );
285
+
286
+ return (
287
+ <>
288
+ <button onClick={ () => setIsOpen( true ) }>Open Dialog</button>
289
+ <AlertDialog.Root
290
+ { ...args }
291
+ open={ isOpen }
292
+ onOpenChange={ ( open, eventDetails ) => {
293
+ setIsOpen( open );
294
+ args.onOpenChange?.( open, eventDetails );
295
+ } }
296
+ >
297
+ <AlertDialog.Popup
298
+ title="Move to trash?"
299
+ description="This post will be moved to trash. You can restore it later."
300
+ />
301
+ </AlertDialog.Root>
302
+ </>
303
+ );
304
+ },
305
+ };
@@ -0,0 +1,21 @@
1
+ @layer wp-ui-utilities, wp-ui-components, wp-ui-compositions, wp-ui-overrides;
2
+
3
+ @layer wp-ui-components {
4
+ .header {
5
+ margin-bottom: var(--wpds-dimension-gap-lg);
6
+ }
7
+
8
+ .error-message {
9
+ align-self: flex-end;
10
+ color: var(--wpds-color-fg-content-error);
11
+ }
12
+ }
13
+
14
+ @layer wp-ui-compositions {
15
+ .irreversible-action {
16
+ --wp-ui-button-background-color: var(--wpds-color-bg-interactive-error-strong);
17
+ --wp-ui-button-background-color-active: var(--wpds-color-bg-interactive-error-strong-active);
18
+ --wp-ui-button-foreground-color: var(--wpds-color-fg-interactive-error-strong);
19
+ --wp-ui-button-foreground-color-active: var(--wpds-color-fg-interactive-error-strong-active);
20
+ }
21
+ }