@wordpress/widget-dashboard 0.2.0 → 0.3.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 (283) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +29 -16
  3. package/build/components/actions/actions.cjs +6 -23
  4. package/build/components/actions/actions.cjs.map +3 -3
  5. package/build/components/commands/commands.cjs +1 -60
  6. package/build/components/commands/commands.cjs.map +2 -2
  7. package/build/{utils/grid-model-change → components/widget-attribute-controls}/index.cjs +7 -9
  8. package/build/components/widget-attribute-controls/index.cjs.map +7 -0
  9. package/build/components/widget-attribute-controls/widget-attribute-controls.cjs +93 -0
  10. package/build/components/widget-attribute-controls/widget-attribute-controls.cjs.map +7 -0
  11. package/build/components/widget-chrome/widget-chrome.cjs +28 -69
  12. package/build/components/widget-chrome/widget-chrome.cjs.map +2 -2
  13. package/build/components/{layout-settings → widget-frame}/index.cjs +9 -7
  14. package/build/components/widget-frame/index.cjs.map +7 -0
  15. package/build/components/widget-frame/widget-frame.cjs +193 -0
  16. package/build/components/widget-frame/widget-frame.cjs.map +7 -0
  17. package/build/{utils/migrate-layout → components/widget-header}/index.cjs +7 -7
  18. package/build/components/widget-header/index.cjs.map +7 -0
  19. package/build/components/widget-header/widget-header-infotip.cjs +166 -0
  20. package/build/components/widget-header/widget-header-infotip.cjs.map +7 -0
  21. package/build/components/widget-header/widget-header.cjs +176 -0
  22. package/build/components/widget-header/widget-header.cjs.map +7 -0
  23. package/build/components/{widget-settings/utils/get-admin-menu-inset.cjs → widget-layout-controls/index.cjs} +8 -18
  24. package/build/components/widget-layout-controls/index.cjs.map +7 -0
  25. package/build/components/{widgets/widget-layout-toolbar.cjs → widget-layout-controls/widget-layout-controls.cjs} +9 -100
  26. package/build/components/widget-layout-controls/widget-layout-controls.cjs.map +7 -0
  27. package/build/components/widget-picker/widget-picker.cjs +5 -93
  28. package/build/components/widget-picker/widget-picker.cjs.map +3 -3
  29. package/build/components/widget-preview-chrome/index.cjs +31 -0
  30. package/build/components/widget-preview-chrome/index.cjs.map +7 -0
  31. package/build/components/{widget-settings/widget-settings-toolbar.cjs → widget-preview-chrome/widget-preview-chrome.cjs} +41 -23
  32. package/build/components/widget-preview-chrome/widget-preview-chrome.cjs.map +7 -0
  33. package/build/components/widget-settings/index.cjs +3 -3
  34. package/build/components/widget-settings/index.cjs.map +1 -1
  35. package/build/components/widget-settings/utils/index.cjs +0 -3
  36. package/build/components/widget-settings/utils/index.cjs.map +2 -2
  37. package/build/components/widget-settings/widget-settings-trigger.cjs +22 -28
  38. package/build/components/widget-settings/widget-settings-trigger.cjs.map +2 -2
  39. package/build/components/widget-settings/widget-settings.cjs +40 -57
  40. package/build/components/widget-settings/widget-settings.cjs.map +2 -2
  41. package/build/components/widget-toolbar/widget-toolbar.cjs +7 -4
  42. package/build/components/widget-toolbar/widget-toolbar.cjs.map +2 -2
  43. package/build/components/widgets/widget-resize-handle.cjs +4 -4
  44. package/build/components/widgets/widget-resize-handle.cjs.map +2 -2
  45. package/build/components/widgets/widgets.cjs +18 -11
  46. package/build/components/widgets/widgets.cjs.map +2 -2
  47. package/build/context/dashboard-context.cjs +31 -80
  48. package/build/context/dashboard-context.cjs.map +2 -2
  49. package/build/context/ui-context.cjs +2 -18
  50. package/build/context/ui-context.cjs.map +2 -2
  51. package/build/types.cjs.map +1 -1
  52. package/build/utils/index.cjs +2 -5
  53. package/build/utils/index.cjs.map +2 -2
  54. package/build/widget-dashboard.cjs +0 -4
  55. package/build/widget-dashboard.cjs.map +2 -2
  56. package/build-module/components/actions/actions.mjs +7 -24
  57. package/build-module/components/actions/actions.mjs.map +2 -2
  58. package/build-module/components/commands/commands.mjs +2 -67
  59. package/build-module/components/commands/commands.mjs.map +2 -2
  60. package/build-module/components/widget-attribute-controls/index.mjs +6 -0
  61. package/build-module/components/widget-attribute-controls/index.mjs.map +7 -0
  62. package/build-module/components/widget-attribute-controls/widget-attribute-controls.mjs +68 -0
  63. package/build-module/components/widget-attribute-controls/widget-attribute-controls.mjs.map +7 -0
  64. package/build-module/components/widget-chrome/widget-chrome.mjs +29 -76
  65. package/build-module/components/widget-chrome/widget-chrome.mjs.map +2 -2
  66. package/build-module/components/widget-frame/index.mjs +7 -0
  67. package/build-module/components/widget-frame/index.mjs.map +7 -0
  68. package/build-module/components/widget-frame/widget-frame.mjs +157 -0
  69. package/build-module/components/widget-frame/widget-frame.mjs.map +7 -0
  70. package/build-module/components/widget-header/index.mjs +6 -0
  71. package/build-module/components/widget-header/index.mjs.map +7 -0
  72. package/build-module/components/widget-header/widget-header-infotip.mjs +141 -0
  73. package/build-module/components/widget-header/widget-header-infotip.mjs.map +7 -0
  74. package/build-module/components/widget-header/widget-header.mjs +141 -0
  75. package/build-module/components/widget-header/widget-header.mjs.map +7 -0
  76. package/build-module/components/widget-layout-controls/index.mjs +6 -0
  77. package/build-module/components/widget-layout-controls/index.mjs.map +7 -0
  78. package/build-module/components/widget-layout-controls/widget-layout-controls.mjs +90 -0
  79. package/build-module/components/widget-layout-controls/widget-layout-controls.mjs.map +7 -0
  80. package/build-module/components/widget-picker/widget-picker.mjs +6 -94
  81. package/build-module/components/widget-picker/widget-picker.mjs.map +3 -3
  82. package/build-module/components/widget-preview-chrome/index.mjs +6 -0
  83. package/build-module/components/widget-preview-chrome/index.mjs.map +7 -0
  84. package/build-module/components/{widget-settings/widget-settings-toolbar.mjs → widget-preview-chrome/widget-preview-chrome.mjs} +37 -19
  85. package/build-module/components/widget-preview-chrome/widget-preview-chrome.mjs.map +7 -0
  86. package/build-module/components/widget-settings/index.mjs +2 -2
  87. package/build-module/components/widget-settings/index.mjs.map +1 -1
  88. package/build-module/components/widget-settings/utils/index.mjs +0 -2
  89. package/build-module/components/widget-settings/utils/index.mjs.map +2 -2
  90. package/build-module/components/widget-settings/widget-settings-trigger.mjs +23 -29
  91. package/build-module/components/widget-settings/widget-settings-trigger.mjs.map +2 -2
  92. package/build-module/components/widget-settings/widget-settings.mjs +40 -57
  93. package/build-module/components/widget-settings/widget-settings.mjs.map +2 -2
  94. package/build-module/components/widget-toolbar/widget-toolbar.mjs +7 -4
  95. package/build-module/components/widget-toolbar/widget-toolbar.mjs.map +2 -2
  96. package/build-module/components/widgets/widget-resize-handle.mjs +4 -4
  97. package/build-module/components/widgets/widget-resize-handle.mjs.map +2 -2
  98. package/build-module/components/widgets/widgets.mjs +18 -11
  99. package/build-module/components/widgets/widgets.mjs.map +2 -2
  100. package/build-module/context/dashboard-context.mjs +31 -80
  101. package/build-module/context/dashboard-context.mjs.map +2 -2
  102. package/build-module/context/ui-context.mjs +2 -18
  103. package/build-module/context/ui-context.mjs.map +2 -2
  104. package/build-module/types.mjs.map +1 -1
  105. package/build-module/utils/index.mjs +1 -3
  106. package/build-module/utils/index.mjs.map +2 -2
  107. package/build-module/widget-dashboard.mjs +0 -4
  108. package/build-module/widget-dashboard.mjs.map +2 -2
  109. package/build-types/components/actions/actions.d.ts.map +1 -1
  110. package/build-types/components/commands/commands.d.ts.map +1 -1
  111. package/build-types/components/commands/use-pending-when-edit-mode.d.ts +1 -1
  112. package/build-types/components/commands/use-pending-when-edit-mode.d.ts.map +1 -1
  113. package/build-types/components/no-widgets-state/no-widgets-state.d.ts +1 -1
  114. package/build-types/components/no-widgets-state/no-widgets-state.d.ts.map +1 -1
  115. package/build-types/components/widget-attribute-controls/index.d.ts +2 -0
  116. package/build-types/components/widget-attribute-controls/index.d.ts.map +1 -0
  117. package/build-types/components/widget-attribute-controls/widget-attribute-controls.d.ts +23 -0
  118. package/build-types/components/widget-attribute-controls/widget-attribute-controls.d.ts.map +1 -0
  119. package/build-types/components/widget-chrome/widget-chrome.d.ts +8 -8
  120. package/build-types/components/widget-chrome/widget-chrome.d.ts.map +1 -1
  121. package/build-types/components/widget-frame/index.d.ts +3 -0
  122. package/build-types/components/widget-frame/index.d.ts.map +1 -0
  123. package/build-types/components/widget-frame/widget-frame.d.ts +25 -0
  124. package/build-types/components/widget-frame/widget-frame.d.ts.map +1 -0
  125. package/build-types/components/widget-header/index.d.ts +3 -0
  126. package/build-types/components/widget-header/index.d.ts.map +1 -0
  127. package/build-types/components/widget-header/widget-header-infotip.d.ts +20 -0
  128. package/build-types/components/widget-header/widget-header-infotip.d.ts.map +1 -0
  129. package/build-types/components/widget-header/widget-header.d.ts +38 -0
  130. package/build-types/components/widget-header/widget-header.d.ts.map +1 -0
  131. package/build-types/components/widget-layout-controls/index.d.ts +3 -0
  132. package/build-types/components/widget-layout-controls/index.d.ts.map +1 -0
  133. package/build-types/components/widget-layout-controls/widget-layout-controls.d.ts +14 -0
  134. package/build-types/components/widget-layout-controls/widget-layout-controls.d.ts.map +1 -0
  135. package/build-types/components/widget-picker/widget-picker.d.ts +1 -1
  136. package/build-types/components/widget-picker/widget-picker.d.ts.map +1 -1
  137. package/build-types/components/widget-preview-chrome/index.d.ts +3 -0
  138. package/build-types/components/widget-preview-chrome/index.d.ts.map +1 -0
  139. package/build-types/components/widget-preview-chrome/widget-preview-chrome.d.ts +15 -0
  140. package/build-types/components/widget-preview-chrome/widget-preview-chrome.d.ts.map +1 -0
  141. package/build-types/components/widget-settings/index.d.ts +2 -2
  142. package/build-types/components/widget-settings/utils/index.d.ts +0 -1
  143. package/build-types/components/widget-settings/utils/index.d.ts.map +1 -1
  144. package/build-types/components/widget-settings/widget-settings-trigger.d.ts +7 -5
  145. package/build-types/components/widget-settings/widget-settings-trigger.d.ts.map +1 -1
  146. package/build-types/components/widget-settings/widget-settings.d.ts +5 -4
  147. package/build-types/components/widget-settings/widget-settings.d.ts.map +1 -1
  148. package/build-types/components/widget-toolbar/widget-toolbar.d.ts +10 -7
  149. package/build-types/components/widget-toolbar/widget-toolbar.d.ts.map +1 -1
  150. package/build-types/components/widgets/widgets.d.ts.map +1 -1
  151. package/build-types/context/dashboard-context.d.ts +23 -40
  152. package/build-types/context/dashboard-context.d.ts.map +1 -1
  153. package/build-types/context/ui-context.d.ts +0 -18
  154. package/build-types/context/ui-context.d.ts.map +1 -1
  155. package/build-types/context/widget-context.d.ts +1 -1
  156. package/build-types/context/widget-context.d.ts.map +1 -1
  157. package/build-types/types.d.ts +9 -15
  158. package/build-types/types.d.ts.map +1 -1
  159. package/build-types/utils/index.d.ts +0 -1
  160. package/build-types/utils/index.d.ts.map +1 -1
  161. package/build-types/widget-dashboard.d.ts +5 -5
  162. package/build-types/widget-dashboard.d.ts.map +1 -1
  163. package/package.json +20 -20
  164. package/src/components/actions/actions.module.css +7 -7
  165. package/src/components/actions/actions.tsx +5 -25
  166. package/src/components/commands/commands.tsx +3 -70
  167. package/src/components/widget-attribute-controls/index.ts +1 -0
  168. package/src/components/widget-attribute-controls/widget-attribute-controls.tsx +108 -0
  169. package/src/components/widget-chrome/widget-chrome.module.css +6 -71
  170. package/src/components/widget-chrome/widget-chrome.tsx +31 -136
  171. package/src/components/widget-frame/index.ts +2 -0
  172. package/src/components/widget-frame/widget-frame.module.css +17 -0
  173. package/src/components/widget-frame/widget-frame.tsx +138 -0
  174. package/src/components/widget-header/index.ts +2 -0
  175. package/src/components/widget-header/widget-header-infotip.tsx +82 -0
  176. package/src/components/widget-header/widget-header.module.css +59 -0
  177. package/src/components/widget-header/widget-header.tsx +104 -0
  178. package/src/components/widget-layout-controls/index.ts +2 -0
  179. package/src/components/{widgets/widget-layout-toolbar.tsx → widget-layout-controls/widget-layout-controls.tsx} +12 -13
  180. package/src/components/widget-picker/widget-picker.tsx +5 -10
  181. package/src/components/widget-preview-chrome/index.ts +2 -0
  182. package/src/components/widget-preview-chrome/widget-preview-chrome.module.css +22 -0
  183. package/src/components/widget-preview-chrome/widget-preview-chrome.tsx +65 -0
  184. package/src/components/widget-settings/index.ts +2 -2
  185. package/src/components/widget-settings/utils/index.ts +0 -1
  186. package/src/components/widget-settings/widget-settings-trigger.tsx +39 -44
  187. package/src/components/widget-settings/widget-settings.tsx +10 -28
  188. package/src/components/widget-toolbar/widget-toolbar.module.css +13 -10
  189. package/src/components/widget-toolbar/widget-toolbar.tsx +14 -8
  190. package/src/components/widgets/widget-resize-handle.module.css +21 -21
  191. package/src/components/widgets/widget-resize-handle.tsx +2 -2
  192. package/src/components/widgets/widgets.module.css +20 -11
  193. package/src/components/widgets/widgets.tsx +33 -10
  194. package/src/context/dashboard-context.tsx +70 -133
  195. package/src/context/ui-context.tsx +1 -39
  196. package/src/test/actions.test.tsx +7 -77
  197. package/src/test/commands.test.tsx +6 -45
  198. package/src/test/staging.test.tsx +82 -144
  199. package/src/test/widget-dashboard.test.tsx +24 -0
  200. package/src/types.ts +9 -16
  201. package/src/utils/index.ts +0 -1
  202. package/src/widget-dashboard.tsx +4 -8
  203. package/build/components/layout-settings/index.cjs.map +0 -7
  204. package/build/components/layout-settings/layout-model-edit-field/index.cjs +0 -186
  205. package/build/components/layout-settings/layout-model-edit-field/index.cjs.map +0 -7
  206. package/build/components/layout-settings/layout-model-edit-field/thumbnail-grid.cjs +0 -53
  207. package/build/components/layout-settings/layout-model-edit-field/thumbnail-grid.cjs.map +0 -7
  208. package/build/components/layout-settings/layout-model-edit-field/thumbnail-masonry.cjs +0 -53
  209. package/build/components/layout-settings/layout-model-edit-field/thumbnail-masonry.cjs.map +0 -7
  210. package/build/components/layout-settings/layout-settings.cjs +0 -207
  211. package/build/components/layout-settings/layout-settings.cjs.map +0 -7
  212. package/build/components/widget-settings/utils/get-admin-menu-inset.cjs.map +0 -7
  213. package/build/components/widget-settings/widget-settings-toolbar.cjs.map +0 -7
  214. package/build/components/widgets/widget-layout-toolbar.cjs.map +0 -7
  215. package/build/utils/grid-model-change/grid-model-change.cjs +0 -56
  216. package/build/utils/grid-model-change/grid-model-change.cjs.map +0 -7
  217. package/build/utils/grid-model-change/index.cjs.map +0 -7
  218. package/build/utils/migrate-layout/index.cjs.map +0 -7
  219. package/build/utils/migrate-layout/migrate-layout.cjs +0 -94
  220. package/build/utils/migrate-layout/migrate-layout.cjs.map +0 -7
  221. package/build-module/components/layout-settings/index.mjs +0 -6
  222. package/build-module/components/layout-settings/index.mjs.map +0 -7
  223. package/build-module/components/layout-settings/layout-model-edit-field/index.mjs +0 -151
  224. package/build-module/components/layout-settings/layout-model-edit-field/index.mjs.map +0 -7
  225. package/build-module/components/layout-settings/layout-model-edit-field/thumbnail-grid.mjs +0 -28
  226. package/build-module/components/layout-settings/layout-model-edit-field/thumbnail-grid.mjs.map +0 -7
  227. package/build-module/components/layout-settings/layout-model-edit-field/thumbnail-masonry.mjs +0 -28
  228. package/build-module/components/layout-settings/layout-model-edit-field/thumbnail-masonry.mjs.map +0 -7
  229. package/build-module/components/layout-settings/layout-settings.mjs +0 -187
  230. package/build-module/components/layout-settings/layout-settings.mjs.map +0 -7
  231. package/build-module/components/widget-settings/utils/get-admin-menu-inset.mjs +0 -16
  232. package/build-module/components/widget-settings/utils/get-admin-menu-inset.mjs.map +0 -7
  233. package/build-module/components/widget-settings/widget-settings-toolbar.mjs.map +0 -7
  234. package/build-module/components/widgets/widget-layout-toolbar.mjs +0 -181
  235. package/build-module/components/widgets/widget-layout-toolbar.mjs.map +0 -7
  236. package/build-module/utils/grid-model-change/grid-model-change.mjs +0 -30
  237. package/build-module/utils/grid-model-change/grid-model-change.mjs.map +0 -7
  238. package/build-module/utils/grid-model-change/index.mjs +0 -7
  239. package/build-module/utils/grid-model-change/index.mjs.map +0 -7
  240. package/build-module/utils/migrate-layout/index.mjs +0 -6
  241. package/build-module/utils/migrate-layout/index.mjs.map +0 -7
  242. package/build-module/utils/migrate-layout/migrate-layout.mjs +0 -69
  243. package/build-module/utils/migrate-layout/migrate-layout.mjs.map +0 -7
  244. package/build-types/components/layout-settings/index.d.ts +0 -2
  245. package/build-types/components/layout-settings/index.d.ts.map +0 -1
  246. package/build-types/components/layout-settings/layout-model-edit-field/index.d.ts +0 -17
  247. package/build-types/components/layout-settings/layout-model-edit-field/index.d.ts.map +0 -1
  248. package/build-types/components/layout-settings/layout-model-edit-field/thumbnail-grid.d.ts +0 -6
  249. package/build-types/components/layout-settings/layout-model-edit-field/thumbnail-grid.d.ts.map +0 -1
  250. package/build-types/components/layout-settings/layout-model-edit-field/thumbnail-masonry.d.ts +0 -6
  251. package/build-types/components/layout-settings/layout-model-edit-field/thumbnail-masonry.d.ts.map +0 -1
  252. package/build-types/components/layout-settings/layout-settings.d.ts +0 -14
  253. package/build-types/components/layout-settings/layout-settings.d.ts.map +0 -1
  254. package/build-types/components/widget-settings/utils/get-admin-menu-inset.d.ts +0 -17
  255. package/build-types/components/widget-settings/utils/get-admin-menu-inset.d.ts.map +0 -1
  256. package/build-types/components/widget-settings/widget-settings-toolbar.d.ts +0 -20
  257. package/build-types/components/widget-settings/widget-settings-toolbar.d.ts.map +0 -1
  258. package/build-types/components/widgets/widget-layout-toolbar.d.ts +0 -14
  259. package/build-types/components/widgets/widget-layout-toolbar.d.ts.map +0 -1
  260. package/build-types/utils/grid-model-change/grid-model-change.d.ts +0 -20
  261. package/build-types/utils/grid-model-change/grid-model-change.d.ts.map +0 -1
  262. package/build-types/utils/grid-model-change/index.d.ts +0 -2
  263. package/build-types/utils/grid-model-change/index.d.ts.map +0 -1
  264. package/build-types/utils/migrate-layout/index.d.ts +0 -2
  265. package/build-types/utils/migrate-layout/index.d.ts.map +0 -1
  266. package/build-types/utils/migrate-layout/migrate-layout.d.ts +0 -36
  267. package/build-types/utils/migrate-layout/migrate-layout.d.ts.map +0 -1
  268. package/src/components/layout-settings/index.ts +0 -1
  269. package/src/components/layout-settings/layout-model-edit-field/index.tsx +0 -98
  270. package/src/components/layout-settings/layout-model-edit-field/style.module.css +0 -34
  271. package/src/components/layout-settings/layout-model-edit-field/thumbnail-grid.tsx +0 -28
  272. package/src/components/layout-settings/layout-model-edit-field/thumbnail-masonry.tsx +0 -28
  273. package/src/components/layout-settings/layout-settings.tsx +0 -217
  274. package/src/components/widget-picker/widget-picker.module.css +0 -11
  275. package/src/components/widget-settings/utils/get-admin-menu-inset.ts +0 -30
  276. package/src/components/widget-settings/widget-settings-toolbar.module.css +0 -25
  277. package/src/components/widget-settings/widget-settings-toolbar.tsx +0 -45
  278. package/src/components/widgets/widget-layout-toolbar.module.css +0 -6
  279. package/src/utils/grid-model-change/grid-model-change.ts +0 -53
  280. package/src/utils/grid-model-change/index.ts +0 -1
  281. package/src/utils/migrate-layout/index.ts +0 -1
  282. package/src/utils/migrate-layout/migrate-layout.ts +0 -156
  283. package/src/utils/migrate-layout/test/migrate-layout.test.ts +0 -114
@@ -3,7 +3,7 @@
3
3
  */
4
4
  import { useCallback } from '@wordpress/element';
5
5
  import { __ } from '@wordpress/i18n';
6
- import { cog } from '@wordpress/icons';
6
+ import { moreVertical } from '@wordpress/icons';
7
7
  // Dashboard is still experimental.
8
8
  // eslint-disable-next-line @wordpress/use-recommended-components
9
9
  import { IconButton } from '@wordpress/ui';
@@ -12,13 +12,13 @@ import type { WidgetType } from '@wordpress/widget-primitives';
12
12
  /**
13
13
  * Internal dependencies
14
14
  */
15
+ import { useDashboardInternalContext } from '../../context/dashboard-context';
15
16
  import { useDashboardUIContext } from '../../context/ui-context';
16
- import { getAdminMenuInset } from './utils';
17
17
  import type { DashboardWidget } from '../../types';
18
18
 
19
19
  export interface WidgetSettingsTriggerProps {
20
20
  /**
21
- * The instance whose settings drawer this gear opens.
21
+ * The instance whose settings surface this control opens.
22
22
  */
23
23
  widget: DashboardWidget< unknown >;
24
24
 
@@ -30,10 +30,12 @@ export interface WidgetSettingsTriggerProps {
30
30
  }
31
31
 
32
32
  /**
33
- * Per-instance gear that opens the shared settings drawer by writing the
33
+ * Per-instance control that toggles the shared settings surface by writing the
34
34
  * instance `uuid` to the UI context; the single `WidgetSettings` at the root
35
- * reacts to it. Returns `null` when the type declares no attributes, so chrome
36
- * can mount it unconditionally.
35
+ * reacts to it. Clicking the control of the instance whose settings surface is
36
+ * already open closes it. Returns `null` when no attribute needs that surface
37
+ * (none, or all already promoted to the prominent one), so chrome can mount it
38
+ * unconditionally.
37
39
  *
38
40
  * @param {WidgetSettingsTriggerProps} props Component props.
39
41
  */
@@ -41,56 +43,49 @@ export function WidgetSettingsTrigger( {
41
43
  widget,
42
44
  widgetType,
43
45
  }: WidgetSettingsTriggerProps ): React.ReactNode {
44
- const {
45
- setSettingsWidgetUuid,
46
- setSettingsDrawerSide,
47
- setSettingsDrawerInset,
48
- } = useDashboardUIContext();
46
+ const { settingsWidgetUuid, setSettingsWidgetUuid } =
47
+ useDashboardUIContext();
48
+ const { cancel, flushAutoSave } = useDashboardInternalContext();
49
49
 
50
- const open = useCallback(
51
- ( event: React.MouseEvent< HTMLElement > ) => {
52
- // Open the drawer on the side away from the widget: compare the
53
- // tile's center against the midpoint of the usable content area
54
- // (which starts after the admin menu). Past it opens left.
55
- const adminMenuInset = getAdminMenuInset();
56
- // The gear sits in the grid slot, outside the card, so reach the
57
- // tile via the grid item's data hook.
58
- const tile = event.currentTarget.closest(
59
- '[data-wp-grid-item-key]'
60
- );
61
- const rect = (
62
- tile ?? event.currentTarget
63
- ).getBoundingClientRect();
64
- const widgetCenter = rect.left + rect.width / 2;
65
- const contentCenter = ( adminMenuInset + window.innerWidth ) / 2;
66
- const side = widgetCenter > contentCenter ? 'left' : 'right';
50
+ const toggle = useCallback( () => {
51
+ // Re-clicking the open instance's control closes the settings surface,
52
+ // discarding staged edits like any other non-Save exit.
53
+ if ( settingsWidgetUuid === widget.uuid ) {
54
+ cancel();
55
+ setSettingsWidgetUuid( null );
56
+ return;
57
+ }
58
+ // Persist any pending prominent-surface edit before opening, so the
59
+ // settings surface's edits stay isolated and its Cancel discards only
60
+ // its own changes.
61
+ flushAutoSave();
62
+ setSettingsWidgetUuid( widget.uuid );
63
+ }, [
64
+ cancel,
65
+ flushAutoSave,
66
+ settingsWidgetUuid,
67
+ setSettingsWidgetUuid,
68
+ widget.uuid,
69
+ ] );
67
70
 
68
- setSettingsDrawerSide( side );
69
- // A left drawer would otherwise slide over the fixed admin menu;
70
- // offset it by the menu width so it lands clear of it.
71
- setSettingsDrawerInset( side === 'left' ? adminMenuInset : 0 );
72
- setSettingsWidgetUuid( widget.uuid );
73
- },
74
- [
75
- setSettingsDrawerSide,
76
- setSettingsDrawerInset,
77
- setSettingsWidgetUuid,
78
- widget.uuid,
79
- ]
71
+ // Surface the settings UI only when there are attributes not already
72
+ // promoted inline; if every attribute is high-relevance, a second
73
+ // surface would just repeat the prominent one.
74
+ const hasNonPromotedAttributes = widgetType.attributes?.some(
75
+ ( attribute ) => attribute.relevance !== 'high'
80
76
  );
81
-
82
- if ( ! widgetType.attributes?.length ) {
77
+ if ( ! hasNonPromotedAttributes ) {
83
78
  return null;
84
79
  }
85
80
 
86
81
  return (
87
82
  <IconButton
88
- icon={ cog }
83
+ icon={ moreVertical }
89
84
  label={ __( 'Widget settings' ) }
90
85
  variant="minimal"
91
86
  tone="neutral"
92
87
  size="compact"
93
- onClick={ open }
88
+ onClick={ toggle }
94
89
  />
95
90
  );
96
91
  }
@@ -22,13 +22,14 @@ type WidgetAttributes = Record< string, unknown >;
22
22
  /**
23
23
  * Side drawer that edits one instance's attributes, mounted once at the
24
24
  * dashboard root. It resolves the active instance from `settingsWidgetUuid`
25
- * in the UI context (set by the per-instance gear), renders the type's
26
- * declarative `attributes` through `DataForm`, and enters from the edge away
27
- * from the widget.
25
+ * in the UI context (set by the per-instance settings trigger), renders the
26
+ * type's declarative `attributes` through `DataForm`, and enters from the
27
+ * inline-end edge.
28
28
  *
29
29
  * Edits write to the staging layer, so they preview live behind the drawer
30
30
  * and are published on Save or reverted on any other exit. Available in
31
- * normal mode only; the gear is hidden while the layout is being edited.
31
+ * normal mode only; the settings entry point is hidden while the layout is
32
+ * being edited.
32
33
  */
33
34
  export function WidgetSettings(): React.ReactNode {
34
35
  const {
@@ -39,12 +40,8 @@ export function WidgetSettings(): React.ReactNode {
39
40
  cancel: cancelStaging,
40
41
  hasUncommittedChanges,
41
42
  } = useDashboardInternalContext();
42
- const {
43
- settingsWidgetUuid,
44
- setSettingsWidgetUuid,
45
- settingsDrawerSide,
46
- settingsDrawerInset,
47
- } = useDashboardUIContext();
43
+ const { settingsWidgetUuid, setSettingsWidgetUuid } =
44
+ useDashboardUIContext();
48
45
 
49
46
  const open = settingsWidgetUuid !== null;
50
47
 
@@ -117,7 +114,7 @@ export function WidgetSettings(): React.ReactNode {
117
114
  const handleOpenChange = useCallback(
118
115
  ( nextOpen: boolean ) => {
119
116
  // Any path out of the drawer other than Save discards the
120
- // staged edits, matching the layout-settings drawer.
117
+ // staged edits.
121
118
  if ( ! nextOpen ) {
122
119
  cancelStaging();
123
120
  close();
@@ -126,17 +123,6 @@ export function WidgetSettings(): React.ReactNode {
126
123
  [ cancelStaging, close ]
127
124
  );
128
125
 
129
- // For a left drawer, clear the fixed admin menu on the inline-start
130
- // edge so the drawer lands beside it. The admin bar at the top is
131
- // cleared in the CSS module.
132
- const popupStyle = useMemo< React.CSSProperties >(
133
- () =>
134
- settingsDrawerSide === 'left' && settingsDrawerInset > 0
135
- ? { marginLeft: settingsDrawerInset }
136
- : {},
137
- [ settingsDrawerSide, settingsDrawerInset ]
138
- );
139
-
140
126
  const hasForm = !! widget && !! widgetType && fields.length > 0;
141
127
 
142
128
  if ( ! hasForm ) {
@@ -152,15 +138,11 @@ export function WidgetSettings(): React.ReactNode {
152
138
  <Drawer.Root
153
139
  open={ open }
154
140
  onOpenChange={ handleOpenChange }
155
- swipeDirection={ settingsDrawerSide }
141
+ swipeDirection="right"
156
142
  modal={ false }
157
143
  disablePointerDismissal
158
144
  >
159
- <Drawer.Popup
160
- size="medium"
161
- className={ styles.popup }
162
- style={ popupStyle }
163
- >
145
+ <Drawer.Popup size="medium" className={ styles.popup }>
164
146
  <Drawer.Header>
165
147
  <Drawer.Title>{ title }</Drawer.Title>
166
148
  <Drawer.CloseIcon />
@@ -1,12 +1,15 @@
1
- /*
2
- * Per-tile toolbar shell: anchored top-right (the grid item is the positioned
3
- * ancestor) with the shared padding and radius. Variants add the background.
4
- */
5
- .widgetToolbar {
6
- position: absolute;
7
- inset-block-start: var(--wpds-dimension-padding-sm);
8
- inset-inline-end: var(--wpds-dimension-padding-sm);
9
- z-index: 1;
1
+ .widget-toolbar {
10
2
  padding: var(--wpds-dimension-padding-xs);
11
- border-radius: var(--wpds-border-radius-md);
3
+ background: var(--wpds-color-background-surface-neutral-strong);
4
+ }
5
+
6
+ .elevated {
7
+ --_wp-widget-dashboard-elevation-xs:
8
+ 0 1px 1px rgba(0, 0, 0, 0.03),
9
+ 0 1px 2px rgba(0, 0, 0, 0.02),
10
+ 0 3px 3px rgba(0, 0, 0, 0.02),
11
+ 0 4px 4px rgba(0, 0, 0, 0.01);
12
+
13
+ border: 1px solid var(--wpds-color-stroke-surface-neutral-weak);
14
+ box-shadow: var(--_wp-widget-dashboard-elevation-xs);
12
15
  }
@@ -15,30 +15,36 @@ import { Stack } from '@wordpress/ui';
15
15
  import styles from './widget-toolbar.module.css';
16
16
 
17
17
  export interface WidgetToolbarProps {
18
- /** Toolbar controls, laid out in one row. */
18
+ /**
19
+ * The active mode's controls.
20
+ */
19
21
  children: ReactNode;
20
22
 
21
- /** Variant surface class (background, reveal). */
22
- className?: string;
23
+ /**
24
+ * Lift the toolbar with a shadow while customizing.
25
+ */
26
+ editMode?: boolean;
23
27
  }
24
28
 
25
29
  /**
26
- * Shared shell for the per-tile action toolbars. Anchors to the tile's
27
- * top-right corner and lays controls out in the row the header also uses, so
28
- * a toolbar lines up with the title when they overlap.
30
+ * The per-tile toolbar chip holding the active mode's controls.
31
+ * Always visible; lifted with a shadow only while customizing.
29
32
  *
30
33
  * @param {WidgetToolbarProps} props Component props.
31
34
  */
32
35
  export function WidgetToolbar( {
33
36
  children,
34
- className,
37
+ editMode = false,
35
38
  }: WidgetToolbarProps ): React.ReactNode {
36
39
  return (
37
40
  <Stack
38
41
  direction="row"
39
42
  align="center"
40
43
  gap="xs"
41
- className={ clsx( styles.widgetToolbar, className ) }
44
+ className={ clsx(
45
+ styles[ 'widget-toolbar' ],
46
+ editMode && styles.elevated
47
+ ) }
42
48
  >
43
49
  { children }
44
50
  </Stack>
@@ -26,13 +26,13 @@
26
26
  * Larger box = hit target; small `::after` = visual only (still uses
27
27
  * logical borders so RTL needs no mirroring).
28
28
  */
29
- .handleCorner {
29
+ .handle-corner {
30
30
  width: var(--wpds-dimension-size-sm);
31
31
  height: var(--wpds-dimension-size-sm);
32
32
  cursor: nwse-resize;
33
33
  }
34
34
 
35
- .handleCorner::after {
35
+ .handle-corner::after {
36
36
  content: "";
37
37
  position: absolute;
38
38
  bottom: var(--widget-resize-handle-visual-inset);
@@ -54,13 +54,13 @@
54
54
  transform-origin: 100% 100%;
55
55
  }
56
56
 
57
- [dir="rtl"] .handleCorner::after {
57
+ [dir="rtl"] .handle-corner::after {
58
58
  transform-origin: 0% 100%;
59
59
  }
60
60
 
61
- .handleCorner.resizing::after,
62
- .handleCorner:hover::after,
63
- .handleCorner:focus-visible::after {
61
+ .handle-corner.resizing::after,
62
+ .handle-corner:hover::after,
63
+ .handle-corner:focus-visible::after {
64
64
  transform: scale(var(--widget-resize-handle-hover-scale));
65
65
  border-block-end:
66
66
  var(--wpds-border-width-sm) solid
@@ -70,7 +70,7 @@
70
70
  var(--wpds-color-foreground-interactive-brand-active);
71
71
  }
72
72
 
73
- .handleHorizontal {
73
+ .handle-horizontal {
74
74
  display: flex;
75
75
  align-items: center;
76
76
  justify-content: center;
@@ -82,7 +82,7 @@
82
82
  }
83
83
 
84
84
  @media not ( prefers-reduced-motion ) {
85
- .handleCorner::after {
85
+ .handle-corner::after {
86
86
  transition:
87
87
  transform var(--wpds-motion-duration-xs)
88
88
  var(--wpds-motion-easing-balanced),
@@ -92,7 +92,7 @@
92
92
  var(--wpds-motion-easing-balanced);
93
93
  }
94
94
 
95
- .handleHorizontal::after {
95
+ .handle-horizontal::after {
96
96
  transition:
97
97
  transform var(--wpds-motion-duration-xs)
98
98
  var(--wpds-motion-easing-balanced),
@@ -101,7 +101,7 @@
101
101
  }
102
102
  }
103
103
 
104
- .handleHorizontal::after {
104
+ .handle-horizontal::after {
105
105
  content: "";
106
106
  width: var(--wpds-border-width-sm);
107
107
  height: var(--wpds-dimension-size-3xs);
@@ -110,26 +110,26 @@
110
110
  transform-origin: 50% 100%;
111
111
  }
112
112
 
113
- .handleHorizontal.resizing::after,
114
- .handleHorizontal:hover::after,
115
- .handleHorizontal:focus-visible::after {
113
+ .handle-horizontal.resizing::after,
114
+ .handle-horizontal:hover::after,
115
+ .handle-horizontal:focus-visible::after {
116
116
  transform: scale(var(--widget-resize-handle-hover-scale));
117
117
  background-color: var(--wpds-color-foreground-interactive-brand-active);
118
118
  }
119
119
 
120
120
  @media (forced-colors: active) {
121
- .handleCorner::after,
122
- .handleCorner.resizing::after,
123
- .handleCorner:hover::after,
124
- .handleCorner:focus-visible::after {
121
+ .handle-corner::after,
122
+ .handle-corner.resizing::after,
123
+ .handle-corner:hover::after,
124
+ .handle-corner:focus-visible::after {
125
125
  border-block-end-color: Highlight;
126
126
  border-inline-end-color: Highlight;
127
127
  }
128
128
 
129
- .handleHorizontal::after,
130
- .handleHorizontal.resizing::after,
131
- .handleHorizontal:hover::after,
132
- .handleHorizontal:focus-visible::after {
129
+ .handle-horizontal::after,
130
+ .handle-horizontal.resizing::after,
131
+ .handle-horizontal:hover::after,
132
+ .handle-horizontal:focus-visible::after {
133
133
  background-color: Highlight;
134
134
  }
135
135
  }
@@ -36,7 +36,7 @@ export const WidgetResizeHandle = forwardRef<
36
36
  ref={ ref }
37
37
  className={ clsx(
38
38
  styles.handle,
39
- styles.handleHorizontal,
39
+ styles[ 'handle-horizontal' ],
40
40
  isResizing && styles.resizing
41
41
  ) }
42
42
  { ...listeners }
@@ -50,7 +50,7 @@ export const WidgetResizeHandle = forwardRef<
50
50
  ref={ ref }
51
51
  className={ clsx(
52
52
  styles.handle,
53
- styles.handleCorner,
53
+ styles[ 'handle-corner' ],
54
54
  isResizing && styles.resizing
55
55
  ) }
56
56
  { ...listeners }
@@ -1,11 +1,14 @@
1
1
  .grid {
2
- /* stylelint-disable-next-line property-no-unknown -- container queries for the dashboard grid surface */
3
2
  container-type: inline-size;
4
3
  container-name: widget-dashboard;
5
4
  width: 100%;
6
5
  /* Placeholder and drag-preview radii: match `.tile` and `@wordpress/ui` Card (`--wpds-border-radius-lg`). */
7
6
  --wp-grid-placeholder-radius: var(--wpds-border-radius-lg);
8
7
  --wp-grid-drag-preview-radius: var(--wpds-border-radius-lg);
8
+ /* Reserve top paint space so scroll containers do not clip tile focus rings. */
9
+ --wp-widget-dashboard-tile-focus-offset: 2px;
10
+ --wp-widget-dashboard-focus-ring-reserve: calc(var(--wpds-border-width-focus) + var(--wp-widget-dashboard-tile-focus-offset));
11
+ padding-block-start: var(--wp-widget-dashboard-focus-ring-reserve);
9
12
  }
10
13
 
11
14
  .tile {
@@ -14,16 +17,22 @@
14
17
  }
15
18
 
16
19
  /*
17
- * Edit-mode tiles stay at resting elevation (`xs`) on hover; only the
18
- * drag preview (`.drag-preview-frame` on `@wordpress/grid`) lifts to `md`.
20
+ * Edit-mode tiles keep their resting shadow on hover; only the drag preview
21
+ * (`.drag-preview-frame` on `@wordpress/grid`) uses a stronger shadow.
19
22
  */
20
- .tileEditMode {
21
- box-shadow: var(--wpds-elevation-xs);
23
+ .tile-edit-mode {
24
+ --_wp-widget-dashboard-elevation-xs:
25
+ 0 1px 1px rgba(0, 0, 0, 0.03),
26
+ 0 1px 2px rgba(0, 0, 0, 0.02),
27
+ 0 3px 3px rgba(0, 0, 0, 0.02),
28
+ 0 4px 4px rgba(0, 0, 0, 0.01);
29
+
30
+ box-shadow: var(--_wp-widget-dashboard-elevation-xs);
22
31
  }
23
32
 
24
- .tileEditMode:focus-visible {
33
+ .tile-edit-mode:focus-visible {
25
34
  outline: var(--wpds-border-width-focus) solid var(--wpds-color-stroke-focus);
26
- outline-offset: 2px;
35
+ outline-offset: var(--wp-widget-dashboard-tile-focus-offset, 2px);
27
36
  }
28
37
 
29
38
  /*
@@ -31,13 +40,13 @@
31
40
  * `height: 100%` keeps the inner `.tile` height: 100% chain alive
32
41
  * (without it, the wrapper auto-sizes and the cloned tile collapses
33
42
  * to content height). Drag elevation is owned by the grid
34
- * `.drag-preview-frame` (`md` while dragging); strip the cloned tile shadow so it
35
- * does not stack on the frame.
43
+ * `.drag-preview-frame`; strip the cloned tile shadow so it does not stack on
44
+ * the frame.
36
45
  */
37
- .dragPreview {
46
+ .drag-preview {
38
47
  height: 100%;
39
48
  }
40
49
 
41
- .dragPreview .tile {
50
+ .drag-preview .tile {
42
51
  box-shadow: none;
43
52
  }
@@ -21,9 +21,11 @@ import type { WidgetName } from '@wordpress/widget-primitives';
21
21
  */
22
22
  import { useDashboardInternalContext } from '../../context/dashboard-context';
23
23
  import { useDashboardContainerColumnCount } from '../../hooks/use-dashboard-container-column-count';
24
+ import { WidgetAttributeControls } from '../widget-attribute-controls';
24
25
  import { WidgetChrome } from '../widget-chrome';
25
- import { WidgetSettingsToolbar } from '../widget-settings';
26
- import { WidgetLayoutToolbar } from './widget-layout-toolbar';
26
+ import { WidgetHeader } from '../widget-header';
27
+ import { WidgetLayoutControls } from '../widget-layout-controls';
28
+ import { WidgetToolbar } from '../widget-toolbar';
27
29
  import { WidgetResizeHandle } from './widget-resize-handle';
28
30
  import styles from './widgets.module.css';
29
31
  import type {
@@ -132,37 +134,58 @@ export const Widgets = forwardRef< HTMLDivElement, WidgetsProps >(
132
134
  ( type ) => type.name === widget.type
133
135
  );
134
136
  const hasSettings = !! widgetType?.attributes?.length;
137
+ const isFullBleed = widgetType?.presentation === 'full-bleed';
135
138
 
136
- // One slot, chosen by mode: layout toolbar while customizing,
137
- // settings toolbar otherwise (undefined when nothing to configure).
138
- let actionableArea: React.ReactNode;
139
+ // The active mode's controls: layout while customizing, the
140
+ // attribute controls (high-relevance fields on the prominent
141
+ // surface, plus a settings entry point when needed)
142
+ // otherwise.
143
+ let controls: React.ReactNode;
139
144
  if ( editMode ) {
140
- actionableArea = <WidgetLayoutToolbar widget={ widget } />;
145
+ controls = <WidgetLayoutControls widget={ widget } />;
141
146
  } else if ( hasSettings && widgetType ) {
142
- actionableArea = (
143
- <WidgetSettingsToolbar
147
+ controls = (
148
+ <WidgetAttributeControls
144
149
  widget={ widget }
145
150
  widgetType={ widgetType }
146
151
  />
147
152
  );
148
153
  }
149
154
 
155
+ const toolbar = controls ? (
156
+ <WidgetToolbar editMode={ editMode }>
157
+ { controls }
158
+ </WidgetToolbar>
159
+ ) : undefined;
160
+
161
+ // Normal mode hosts the toolbar in the in-card header, beside the
162
+ // identity. Customize controls and full-bleed widgets need it in
163
+ // the grid's actionable-area slot instead: the slot sits outside
164
+ // the draggable card, so the controls stay clickable (in-card they
165
+ // would be captured by the drag listeners).
166
+ const inSlot = editMode || isFullBleed;
167
+ const actionableArea =
168
+ inSlot && toolbar ? (
169
+ <WidgetHeader overlay>{ toolbar }</WidgetHeader>
170
+ ) : undefined;
171
+
150
172
  return (
151
173
  <WidgetChrome
152
174
  key={ widget.uuid }
153
175
  widget={ widget }
154
176
  index={ index }
155
177
  className={ clsx( styles.tile, {
156
- [ styles.tileEditMode ]: editMode,
178
+ [ styles[ 'tile-edit-mode' ] ]: editMode,
157
179
  } ) }
158
180
  actionableArea={ actionableArea }
181
+ headerToolbar={ ! inSlot ? toolbar : undefined }
159
182
  />
160
183
  );
161
184
  } );
162
185
 
163
186
  const renderDragPreview = useCallback(
164
187
  ( { children: clone }: DragPreviewRenderProps ) => (
165
- <div className={ styles.dragPreview }>{ clone }</div>
188
+ <div className={ styles[ 'drag-preview' ] }>{ clone }</div>
166
189
  ),
167
190
  []
168
191
  );