newspack-components 4.7.0 → 4.8.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 (251) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/DEVELOPMENT.md +42 -21
  3. package/dist/cjs/_mixins.scss +13 -0
  4. package/dist/cjs/_variables.scss +12 -0
  5. package/dist/cjs/action-card/index.js +18 -10
  6. package/dist/cjs/action-card/index.test.js +91 -0
  7. package/dist/cjs/action-card/style.scss +2 -40
  8. package/dist/cjs/button/index.js +8 -3
  9. package/dist/cjs/button/index.test.js +61 -5
  10. package/dist/cjs/card/core-card.js +0 -2
  11. package/dist/cjs/card/style-core.scss +7 -5
  12. package/dist/cjs/card-feature/index.js +75 -61
  13. package/dist/cjs/card-feature/index.test.js +396 -54
  14. package/dist/cjs/card-feature/style.scss +20 -31
  15. package/dist/cjs/card-form/index.js +5 -5
  16. package/dist/cjs/card-sortable-list/index.js +5 -3
  17. package/dist/cjs/card-sortable-list/index.test.js +50 -0
  18. package/dist/cjs/collapsible-group/context.js +19 -0
  19. package/dist/cjs/collapsible-group/index.js +24 -0
  20. package/dist/cjs/collapsible-group/index.test.js +215 -0
  21. package/dist/cjs/collapsible-group/item.js +61 -0
  22. package/dist/cjs/collapsible-group/root.js +62 -0
  23. package/dist/cjs/collapsible-group/style.scss +47 -0
  24. package/dist/cjs/collapsible-group/types.js +5 -0
  25. package/dist/cjs/empty-state/actions.js +45 -0
  26. package/dist/cjs/empty-state/context.js +41 -0
  27. package/dist/cjs/empty-state/header.js +66 -0
  28. package/dist/cjs/empty-state/index.js +31 -0
  29. package/dist/cjs/empty-state/index.test.js +303 -0
  30. package/dist/cjs/empty-state/root.js +56 -0
  31. package/dist/cjs/empty-state/style.scss +51 -0
  32. package/dist/cjs/empty-state/types.js +5 -0
  33. package/dist/cjs/index.js +34 -20
  34. package/dist/cjs/info-button/index.js +59 -43
  35. package/dist/cjs/info-button/index.test.js +199 -0
  36. package/dist/cjs/info-button/style.scss +41 -9
  37. package/dist/cjs/modal/style.scss +12 -12
  38. package/dist/cjs/newspack-icon/style.scss +4 -4
  39. package/dist/cjs/notice/style.scss +3 -3
  40. package/dist/cjs/page/style.scss +16 -16
  41. package/dist/cjs/plugin-installer/index.js +5 -9
  42. package/dist/cjs/plugin-installer/style.scss +3 -14
  43. package/dist/cjs/section-header/index.js +31 -18
  44. package/dist/cjs/section-header/index.test.js +40 -0
  45. package/dist/cjs/section-header/style.scss +22 -6
  46. package/dist/cjs/settings/DateRangeSetting.js +309 -0
  47. package/dist/cjs/settings/SettingsSection.js +19 -5
  48. package/dist/cjs/settings/SettingsSection.test.js +49 -0
  49. package/dist/cjs/settings/index.js +3 -1
  50. package/dist/cjs/settings/style.scss +40 -7
  51. package/dist/cjs/stat-card/body.js +41 -0
  52. package/dist/cjs/stat-card/constants.js +11 -0
  53. package/dist/cjs/stat-card/context.js +54 -0
  54. package/dist/cjs/stat-card/delta.js +91 -0
  55. package/dist/cjs/stat-card/footer.js +72 -0
  56. package/dist/cjs/stat-card/index.js +47 -0
  57. package/dist/cjs/stat-card/index.test.js +938 -0
  58. package/dist/cjs/stat-card/label.js +66 -0
  59. package/dist/cjs/stat-card/root.js +69 -0
  60. package/dist/cjs/stat-card/secondary.js +38 -0
  61. package/dist/cjs/stat-card/style.scss +89 -0
  62. package/dist/cjs/stat-card/types.js +5 -0
  63. package/dist/cjs/stat-card/value.js +78 -0
  64. package/dist/cjs/status-indicator/index.js +66 -0
  65. package/dist/cjs/status-indicator/index.test.js +101 -0
  66. package/dist/cjs/status-indicator/statuses.js +39 -0
  67. package/dist/cjs/status-indicator/style.scss +9 -0
  68. package/dist/cjs/status-indicator/types.js +5 -0
  69. package/dist/cjs/style.scss +9 -9
  70. package/dist/cjs/tabbed-navigation/style.scss +6 -4
  71. package/dist/cjs/types.js +5 -0
  72. package/dist/cjs/web-preview/style.scss +11 -11
  73. package/dist/cjs/with-wizard/style.scss +10 -10
  74. package/dist/cjs/with-wizard-screen/style.scss +9 -9
  75. package/dist/cjs/wizard/index.js +33 -4
  76. package/dist/cjs/wizard/store/index.js +23 -1
  77. package/dist/esm/_mixins.scss +13 -0
  78. package/dist/esm/_variables.scss +12 -0
  79. package/dist/esm/action-card/index.js +18 -10
  80. package/dist/esm/action-card/index.test.js +89 -0
  81. package/dist/esm/action-card/style.scss +2 -40
  82. package/dist/esm/button/index.js +9 -4
  83. package/dist/esm/button/index.test.js +63 -5
  84. package/dist/esm/card/core-card.js +0 -2
  85. package/dist/esm/card/style-core.scss +7 -5
  86. package/dist/esm/card-feature/index.js +78 -62
  87. package/dist/esm/card-feature/index.test.js +397 -55
  88. package/dist/esm/card-feature/style.scss +20 -31
  89. package/dist/esm/card-form/index.js +5 -5
  90. package/dist/esm/card-sortable-list/index.js +6 -4
  91. package/dist/esm/card-sortable-list/index.test.js +46 -0
  92. package/dist/esm/collapsible-group/context.js +13 -0
  93. package/dist/esm/collapsible-group/index.js +17 -0
  94. package/dist/esm/collapsible-group/index.test.js +215 -0
  95. package/dist/esm/collapsible-group/item.js +53 -0
  96. package/dist/esm/collapsible-group/root.js +54 -0
  97. package/dist/esm/collapsible-group/style.scss +47 -0
  98. package/dist/esm/collapsible-group/types.js +1 -0
  99. package/dist/esm/empty-state/actions.js +37 -0
  100. package/dist/esm/empty-state/context.js +35 -0
  101. package/dist/esm/empty-state/header.js +58 -0
  102. package/dist/esm/empty-state/index.js +23 -0
  103. package/dist/esm/empty-state/index.test.js +299 -0
  104. package/dist/esm/empty-state/root.js +56 -0
  105. package/dist/esm/empty-state/style.scss +51 -0
  106. package/dist/esm/empty-state/types.js +1 -0
  107. package/dist/esm/index.js +4 -2
  108. package/dist/esm/info-button/index.js +54 -43
  109. package/dist/esm/info-button/index.test.js +195 -0
  110. package/dist/esm/info-button/style.scss +41 -9
  111. package/dist/esm/modal/style.scss +12 -12
  112. package/dist/esm/newspack-icon/style.scss +4 -4
  113. package/dist/esm/notice/style.scss +3 -3
  114. package/dist/esm/page/style.scss +16 -16
  115. package/dist/esm/plugin-installer/index.js +5 -9
  116. package/dist/esm/plugin-installer/style.scss +3 -14
  117. package/dist/esm/section-header/index.js +27 -14
  118. package/dist/esm/section-header/index.test.js +36 -0
  119. package/dist/esm/section-header/style.scss +22 -6
  120. package/dist/esm/settings/DateRangeSetting.js +304 -0
  121. package/dist/esm/settings/SettingsSection.js +16 -3
  122. package/dist/esm/settings/SettingsSection.test.js +45 -0
  123. package/dist/esm/settings/index.js +3 -1
  124. package/dist/esm/settings/style.scss +40 -7
  125. package/dist/esm/stat-card/body.js +36 -0
  126. package/dist/esm/stat-card/constants.js +5 -0
  127. package/dist/esm/stat-card/context.js +48 -0
  128. package/dist/esm/stat-card/delta.js +86 -0
  129. package/dist/esm/stat-card/footer.js +67 -0
  130. package/dist/esm/stat-card/index.js +33 -0
  131. package/dist/esm/stat-card/index.test.js +939 -0
  132. package/dist/esm/stat-card/label.js +61 -0
  133. package/dist/esm/stat-card/root.js +64 -0
  134. package/dist/esm/stat-card/secondary.js +33 -0
  135. package/dist/esm/stat-card/style.scss +89 -0
  136. package/dist/esm/stat-card/types.js +1 -0
  137. package/dist/esm/stat-card/value.js +73 -0
  138. package/dist/esm/status-indicator/index.js +52 -0
  139. package/dist/esm/status-indicator/index.test.js +96 -0
  140. package/dist/esm/status-indicator/statuses.js +33 -0
  141. package/dist/esm/status-indicator/style.scss +9 -0
  142. package/dist/esm/status-indicator/types.js +1 -0
  143. package/dist/esm/style.scss +9 -9
  144. package/dist/esm/tabbed-navigation/style.scss +6 -4
  145. package/dist/esm/types.js +1 -0
  146. package/dist/esm/web-preview/style.scss +11 -11
  147. package/dist/esm/with-wizard/style.scss +10 -10
  148. package/dist/esm/with-wizard-screen/style.scss +9 -9
  149. package/dist/esm/wizard/index.js +38 -7
  150. package/dist/esm/wizard/store/index.js +23 -1
  151. package/package.json +1 -1
  152. package/src/_mixins.scss +13 -0
  153. package/src/_variables.scss +12 -0
  154. package/src/action-card/action-card.d.ts +3 -2
  155. package/src/action-card/index.js +12 -12
  156. package/src/action-card/index.test.js +56 -0
  157. package/src/action-card/style.scss +2 -40
  158. package/src/button/index.test.js +52 -5
  159. package/src/button/index.tsx +9 -4
  160. package/src/card/core-card.js +0 -2
  161. package/src/card/style-core.scss +7 -5
  162. package/src/card-feature/README.md +68 -27
  163. package/src/card-feature/index.test.js +242 -27
  164. package/src/card-feature/index.tsx +77 -67
  165. package/src/card-feature/style.scss +20 -31
  166. package/src/card-form/README.md +10 -10
  167. package/src/card-form/index.tsx +4 -8
  168. package/src/card-sortable-list/README.md +4 -5
  169. package/src/card-sortable-list/index.test.js +29 -0
  170. package/src/card-sortable-list/index.tsx +7 -4
  171. package/src/collapsible-group/README.md +50 -0
  172. package/src/collapsible-group/context.ts +13 -0
  173. package/src/collapsible-group/index.test.js +168 -0
  174. package/src/collapsible-group/index.tsx +17 -0
  175. package/src/collapsible-group/item.tsx +42 -0
  176. package/src/collapsible-group/root.tsx +42 -0
  177. package/src/collapsible-group/style.scss +47 -0
  178. package/src/collapsible-group/types.ts +22 -0
  179. package/src/drawer/README.md +2 -2
  180. package/src/empty-state/README.md +165 -0
  181. package/src/empty-state/actions.tsx +37 -0
  182. package/src/empty-state/context.ts +40 -0
  183. package/src/empty-state/header.tsx +48 -0
  184. package/src/empty-state/index.test.js +247 -0
  185. package/src/empty-state/index.tsx +22 -0
  186. package/src/empty-state/root.tsx +39 -0
  187. package/src/empty-state/style.scss +51 -0
  188. package/src/empty-state/types.ts +33 -0
  189. package/src/index.js +4 -2
  190. package/src/info-button/README.md +115 -0
  191. package/src/info-button/index.test.js +163 -0
  192. package/src/info-button/index.tsx +64 -0
  193. package/src/info-button/style.scss +41 -9
  194. package/src/modal/style.scss +12 -12
  195. package/src/newspack-icon/style.scss +4 -4
  196. package/src/notice/style.scss +3 -3
  197. package/src/page/style.scss +16 -16
  198. package/src/plugin-installer/index.js +3 -9
  199. package/src/plugin-installer/style.scss +3 -14
  200. package/src/section-header/index.js +27 -14
  201. package/src/section-header/index.test.js +28 -0
  202. package/src/section-header/style.scss +22 -6
  203. package/src/settings/DateRangeSetting.js +266 -0
  204. package/src/settings/SettingsSection.js +24 -4
  205. package/src/settings/SettingsSection.test.js +45 -0
  206. package/src/settings/index.js +2 -0
  207. package/src/settings/style.scss +40 -7
  208. package/src/stat-card/README.md +434 -0
  209. package/src/stat-card/body.tsx +28 -0
  210. package/src/stat-card/constants.ts +5 -0
  211. package/src/stat-card/context.ts +53 -0
  212. package/src/stat-card/delta.tsx +88 -0
  213. package/src/stat-card/footer.tsx +68 -0
  214. package/src/stat-card/index.test.js +818 -0
  215. package/src/stat-card/index.tsx +48 -0
  216. package/src/stat-card/label.tsx +61 -0
  217. package/src/stat-card/root.tsx +40 -0
  218. package/src/stat-card/secondary.tsx +27 -0
  219. package/src/stat-card/style.scss +89 -0
  220. package/src/stat-card/types.ts +84 -0
  221. package/src/stat-card/value.tsx +72 -0
  222. package/src/status-indicator/README.md +123 -0
  223. package/src/status-indicator/index.test.js +70 -0
  224. package/src/status-indicator/index.tsx +39 -0
  225. package/src/status-indicator/statuses.ts +35 -0
  226. package/src/status-indicator/style.scss +9 -0
  227. package/src/status-indicator/types.ts +28 -0
  228. package/src/style.scss +9 -9
  229. package/src/tabbed-navigation/style.scss +6 -4
  230. package/src/types.ts +25 -0
  231. package/src/web-preview/style.scss +11 -11
  232. package/src/with-wizard/style.scss +10 -10
  233. package/src/with-wizard-screen/style.scss +9 -9
  234. package/src/wizard/index.js +49 -7
  235. package/src/wizard/store/index.js +26 -1
  236. package/dist/cjs/accordion/index.js +0 -72
  237. package/dist/cjs/accordion/index.test.js +0 -80
  238. package/dist/cjs/accordion/style.scss +0 -35
  239. package/dist/cjs/badge/index.js +0 -32
  240. package/dist/cjs/badge/style.scss +0 -36
  241. package/dist/esm/accordion/index.js +0 -63
  242. package/dist/esm/accordion/index.test.js +0 -79
  243. package/dist/esm/accordion/style.scss +0 -35
  244. package/dist/esm/badge/index.js +0 -24
  245. package/dist/esm/badge/style.scss +0 -36
  246. package/src/accordion/index.js +0 -46
  247. package/src/accordion/index.test.js +0 -62
  248. package/src/accordion/style.scss +0 -35
  249. package/src/badge/index.tsx +0 -26
  250. package/src/badge/style.scss +0 -36
  251. package/src/info-button/index.js +0 -38
@@ -0,0 +1,195 @@
1
+ /**
2
+ * External dependencies.
3
+ */
4
+ import { act, fireEvent, render, screen } from '@testing-library/react';
5
+
6
+ /**
7
+ * WordPress dependencies.
8
+ */
9
+ import { createRef } from '@wordpress/element';
10
+
11
+ /**
12
+ * Internal dependencies.
13
+ */
14
+ import InfoButton from './';
15
+ import { jsx as _jsx } from "react/jsx-runtime";
16
+ var DESCRIPTION = 'Number of articles read in the last 30 day period.';
17
+ var getTrigger = function getTrigger() {
18
+ var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'More information';
19
+ return screen.getByRole('button', {
20
+ name: name
21
+ });
22
+ };
23
+ describe('InfoButton', function () {
24
+ afterEach(function () {
25
+ jest.useRealTimers();
26
+ });
27
+ it('names the trigger briefly rather than with the whole description', function () {
28
+ render(/*#__PURE__*/_jsx(InfoButton, {
29
+ description: DESCRIPTION
30
+ }));
31
+ expect(getTrigger()).toBeInTheDocument();
32
+ expect(screen.queryByRole('button', {
33
+ name: DESCRIPTION
34
+ })).not.toBeInTheDocument();
35
+ });
36
+ it('renders nothing at all without a description', function () {
37
+ var _render = render(/*#__PURE__*/_jsx(InfoButton, {})),
38
+ container = _render.container;
39
+ expect(screen.queryByRole('button')).not.toBeInTheDocument();
40
+ expect(container.firstChild).toBeNull();
41
+ });
42
+ it('treats an empty description as nothing to explain', function () {
43
+ var _render2 = render(/*#__PURE__*/_jsx(InfoButton, {
44
+ description: ""
45
+ })),
46
+ container = _render2.container;
47
+ expect(screen.queryByRole('button')).not.toBeInTheDocument();
48
+ expect(container.firstChild).toBeNull();
49
+ });
50
+ it('lets a consumer name the trigger for its own context', function () {
51
+ render(/*#__PURE__*/_jsx(InfoButton, {
52
+ description: DESCRIPTION,
53
+ triggerLabel: "More information about Articles read"
54
+ }));
55
+ expect(getTrigger('More information about Articles read')).toBeInTheDocument();
56
+ });
57
+ it('leaves the trigger in the tab order', function () {
58
+ render(/*#__PURE__*/_jsx(InfoButton, {
59
+ description: DESCRIPTION
60
+ }));
61
+ expect(getTrigger().tabIndex).toBeGreaterThanOrEqual(0);
62
+ });
63
+ it('keeps the description hidden until the trigger is activated', function () {
64
+ render(/*#__PURE__*/_jsx(InfoButton, {
65
+ description: DESCRIPTION
66
+ }));
67
+ expect(screen.queryByText(DESCRIPTION)).not.toBeInTheDocument();
68
+ expect(getTrigger()).toHaveAttribute('aria-expanded', 'false');
69
+ });
70
+ it('reveals the description on click, so touch users can reach it', function () {
71
+ render(/*#__PURE__*/_jsx(InfoButton, {
72
+ description: DESCRIPTION
73
+ }));
74
+ fireEvent.click(getTrigger());
75
+ expect(screen.getByText(DESCRIPTION)).toBeInTheDocument();
76
+ expect(getTrigger()).toHaveAttribute('aria-expanded', 'true');
77
+ });
78
+ it('reveals the description on hover, once the pointer has rested', function () {
79
+ jest.useFakeTimers();
80
+ render(/*#__PURE__*/_jsx(InfoButton, {
81
+ description: DESCRIPTION
82
+ }));
83
+ var trigger = getTrigger();
84
+ fireEvent.mouseEnter(trigger);
85
+ fireEvent.mouseMove(trigger);
86
+ expect(screen.queryByText(DESCRIPTION)).not.toBeInTheDocument();
87
+ act(function () {
88
+ return jest.advanceTimersByTime(200);
89
+ });
90
+ expect(screen.getByText(DESCRIPTION)).toBeInTheDocument();
91
+ });
92
+ it('holds the description open long enough to overshoot the trigger', function () {
93
+ jest.useFakeTimers();
94
+ render(/*#__PURE__*/_jsx(InfoButton, {
95
+ description: DESCRIPTION
96
+ }));
97
+ var trigger = getTrigger();
98
+ fireEvent.mouseEnter(trigger);
99
+ fireEvent.mouseMove(trigger);
100
+ act(function () {
101
+ return jest.advanceTimersByTime(200);
102
+ });
103
+ expect(screen.getByText(DESCRIPTION)).toBeInTheDocument();
104
+ fireEvent.mouseLeave(trigger);
105
+ expect(screen.getByText(DESCRIPTION)).toBeInTheDocument();
106
+ act(function () {
107
+ return jest.advanceTimersByTime(200);
108
+ });
109
+ expect(screen.queryByText(DESCRIPTION)).not.toBeInTheDocument();
110
+ });
111
+ it('uses a native button, so Enter and Space activate it', function () {
112
+ render(/*#__PURE__*/_jsx(InfoButton, {
113
+ description: DESCRIPTION
114
+ }));
115
+ var trigger = getTrigger();
116
+ expect(trigger.tagName).toBe('BUTTON');
117
+ expect(trigger).toHaveAttribute('type', 'button');
118
+ });
119
+ it('closes on Escape and hands focus back to the trigger', function () {
120
+ render(/*#__PURE__*/_jsx(InfoButton, {
121
+ description: DESCRIPTION
122
+ }));
123
+ var trigger = getTrigger();
124
+ trigger.focus();
125
+ fireEvent.click(trigger);
126
+ expect(screen.getByText(DESCRIPTION)).toBeInTheDocument();
127
+ fireEvent.keyDown(document.activeElement, {
128
+ key: 'Escape'
129
+ });
130
+ expect(screen.queryByText(DESCRIPTION)).not.toBeInTheDocument();
131
+ expect(trigger).toHaveFocus();
132
+ });
133
+ it('gives the popup an accessible name of its own', function () {
134
+ render(/*#__PURE__*/_jsx(InfoButton, {
135
+ description: DESCRIPTION
136
+ }));
137
+ fireEvent.click(getTrigger());
138
+ expect(screen.getByRole('dialog', {
139
+ name: 'More information'
140
+ })).toBeInTheDocument();
141
+ });
142
+ it('describes the popup with the description rather than naming it', function () {
143
+ render(/*#__PURE__*/_jsx(InfoButton, {
144
+ description: DESCRIPTION
145
+ }));
146
+ fireEvent.click(getTrigger());
147
+ var paragraph = screen.getByText(DESCRIPTION);
148
+ expect(paragraph.id).toBeTruthy();
149
+ expect(document.querySelector("[aria-describedby=\"".concat(paragraph.id, "\"]"))).toBeInTheDocument();
150
+ });
151
+ it('renders through its own portal and positioner', function () {
152
+ render(/*#__PURE__*/_jsx(InfoButton, {
153
+ description: DESCRIPTION
154
+ }));
155
+ fireEvent.click(getTrigger());
156
+ var paragraph = screen.getByText(DESCRIPTION);
157
+ expect(paragraph.closest('.newspack-info-button__positioner')).toBeInTheDocument();
158
+ expect(paragraph.closest('.newspack-info-button__portal')).toBeInTheDocument();
159
+ });
160
+ it('forwards unknown props to the trigger', function () {
161
+ render(/*#__PURE__*/_jsx(InfoButton, {
162
+ description: DESCRIPTION,
163
+ id: "articles-read-info",
164
+ "data-testid": "info"
165
+ }));
166
+ var trigger = getTrigger();
167
+ expect(trigger).toHaveAttribute('id', 'articles-read-info');
168
+ expect(trigger).toHaveAttribute('data-testid', 'info');
169
+ });
170
+ it('keeps its own class alongside a consumer className', function () {
171
+ render(/*#__PURE__*/_jsx(InfoButton, {
172
+ description: DESCRIPTION,
173
+ className: "custom-class"
174
+ }));
175
+ expect(getTrigger()).toHaveClass('newspack-info-button', 'custom-class');
176
+ });
177
+ it('hands a consumer ref the trigger itself', function () {
178
+ var ref = createRef();
179
+ render(/*#__PURE__*/_jsx(InfoButton, {
180
+ description: DESCRIPTION,
181
+ ref: ref
182
+ }));
183
+ expect(ref.current).toBe(getTrigger());
184
+ });
185
+ it('names the trigger and the popup alike when given an aria-label', function () {
186
+ render(/*#__PURE__*/_jsx(InfoButton, {
187
+ description: DESCRIPTION,
188
+ "aria-label": "More information about Articles read"
189
+ }));
190
+ fireEvent.click(getTrigger('More information about Articles read'));
191
+ expect(screen.getByRole('dialog', {
192
+ name: 'More information about Articles read'
193
+ })).toBeInTheDocument();
194
+ });
195
+ });
@@ -1,18 +1,50 @@
1
- /**
2
- * Info Button
3
- */
1
+ @use "~@wordpress/base-styles/colors" as wp-colors;
2
+ @use "~@wordpress/base-styles/variables" as wp-vars;
3
+ @use "~@wordpress/base-styles/z-index" as wp-z;
4
4
 
5
5
  .newspack-info-button {
6
- display: inline-block;
7
- flex: 0 0 24px;
8
- height: 24px;
9
- margin: 0;
10
- margin-left: 4px;
11
- width: 24px;
6
+ align-items: center;
7
+ background: none;
8
+ border: none;
9
+ border-radius: var(--wpds-border-radius-sm, #{wp-vars.$radius-small});
10
+ color: inherit;
11
+ cursor: var(--wpds-cursor-control, pointer);
12
+ display: inline-flex;
13
+ flex: 0 0 auto;
14
+ height: wp-vars.$button-size-small;
15
+ justify-content: center;
16
+ padding: 0;
12
17
  vertical-align: middle;
18
+ width: wp-vars.$button-size-small;
13
19
 
14
20
  svg {
15
21
  display: block;
16
22
  fill: currentcolor;
17
23
  }
24
+
25
+ &:focus-visible {
26
+ outline: var(--wp-admin-border-width-focus, #{wp-vars.$border-width-focus-fallback}) solid var(--wp-admin-theme-color, #{wp-colors.$gray-900});
27
+ outline-offset: 0;
28
+ }
29
+ }
30
+
31
+ .newspack-info-button__portal {
32
+ --wp-ui-popover-z-index: #{wp-z.z-index(".components-popover")};
33
+ }
34
+
35
+ .newspack-info-button__positioner {
36
+ max-width: var(--wpds-dimension-surface-width-sm, calc(#{wp-vars.$grid-unit} * 40));
37
+ }
38
+
39
+ .newspack-info-button__popup {
40
+ background-color: wp-colors.$gray-900;
41
+ border-radius: var(--wpds-border-radius-md, #{wp-vars.$radius-medium});
42
+ box-shadow: var(--wpds-elevation-sm, #{wp-vars.$elevation-small});
43
+ color: wp-colors.$white;
44
+ outline: 0;
45
+ padding: var(--wpds-dimension-padding-xs, #{wp-vars.$grid-unit-05}) var(--wpds-dimension-padding-sm, #{wp-vars.$grid-unit-10});
46
+
47
+ @media (forced-colors: active) {
48
+ border: var(--wpds-border-width-xs, #{wp-vars.$border-width}) solid CanvasText;
49
+ }
18
50
  }
@@ -2,18 +2,18 @@
2
2
  * Modal
3
3
  */
4
4
 
5
- @use "../../../colors/colors.module" as colors;
5
+ @use "../../../colors/colors.module" as np-colors;
6
6
 
7
7
  .newspack-modal {
8
8
  // Color
9
- --wp-admin-theme-color: #{colors.$primary-600};
10
- --wp-admin-theme-color--rgb: #{colors.$primary-600--rgb};
11
- --wp-admin-theme-color-darker-10: #{colors.$primary-700};
12
- --wp-admin-theme-color-darker-10--rgb: #{colors.$primary-700--rgb};
13
- --wp-admin-theme-color-darker-20: #{colors.$primary-800};
14
- --wp-admin-theme-color-darker-20--rgb: #{colors.$primary-800--rgb};
15
- --wp-admin-theme-color-lighter-10: #{colors.$primary-000};
16
- --wp-admin-theme-color-lighter-10--rgb: #{colors.$primary-000--rgb};
9
+ --wp-admin-theme-color: #{np-colors.$primary-600};
10
+ --wp-admin-theme-color--rgb: #{np-colors.$primary-600--rgb};
11
+ --wp-admin-theme-color-darker-10: #{np-colors.$primary-700};
12
+ --wp-admin-theme-color-darker-10--rgb: #{np-colors.$primary-700--rgb};
13
+ --wp-admin-theme-color-darker-20: #{np-colors.$primary-800};
14
+ --wp-admin-theme-color-darker-20--rgb: #{np-colors.$primary-800--rgb};
15
+ --wp-admin-theme-color-lighter-10: #{np-colors.$primary-000};
16
+ --wp-admin-theme-color-lighter-10--rgb: #{np-colors.$primary-000--rgb};
17
17
 
18
18
  border-radius: 8px;
19
19
  margin: auto;
@@ -58,11 +58,11 @@
58
58
 
59
59
  &--destructive {
60
60
  .components-button.is-primary {
61
- background-color: colors.$error-500;
62
- color: colors.$neutral-000;
61
+ background-color: np-colors.$error-500;
62
+ color: np-colors.$neutral-000;
63
63
  &:hover,
64
64
  &:focus {
65
- background-color: colors.$error-600;
65
+ background-color: np-colors.$error-600;
66
66
  }
67
67
  }
68
68
  }
@@ -1,22 +1,22 @@
1
- @use '../../../colors/colors.module.scss' as colors;
1
+ @use "../../../colors/colors.module" as np-colors;
2
2
 
3
3
  /**
4
4
  * Newspack Icon
5
5
  */
6
6
 
7
7
  .newspack-icon {
8
- background: colors.$primary-600;
8
+ background: np-colors.$primary-600;
9
9
  fill: white;
10
10
  padding: 12px;
11
11
 
12
12
  &--white {
13
13
  background: white;
14
- fill: colors.$primary-600;
14
+ fill: np-colors.$primary-600;
15
15
  }
16
16
 
17
17
  &--simple {
18
18
  background: none;
19
- fill: colors.$primary-600;
19
+ fill: np-colors.$primary-600;
20
20
  padding: 0;
21
21
  }
22
22
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  @use "sass:color";
6
6
  @use "~@wordpress/base-styles/colors" as wp-colors;
7
- @use "../../../colors/colors.module" as colors;
7
+ @use "../../../colors/colors.module" as np-colors;
8
8
 
9
9
  .newspack-notice {
10
10
  align-items: center;
@@ -23,7 +23,7 @@
23
23
  }
24
24
 
25
25
  &__is-debug {
26
- background: colors.$primary-600;
26
+ background: np-colors.$primary-600;
27
27
  border-radius: 50%;
28
28
  bottom: 16px;
29
29
  box-shadow: 0 0 8px 4px rgba(black, 0.08);
@@ -63,7 +63,7 @@
63
63
  }
64
64
 
65
65
  &__is-help {
66
- background: colors.$primary-050;
66
+ background: np-colors.$primary-050;
67
67
 
68
68
  > svg {
69
69
  fill: var(--wp-admin-theme-color);
@@ -1,4 +1,4 @@
1
- @use "../../../colors/colors.module" as colors;
1
+ @use "../../../colors/colors.module" as np-colors;
2
2
  @use "~@wordpress/base-styles/colors" as wp-colors;
3
3
  @use "~@wordpress/base-styles/mixins" as wp-mixins;
4
4
  @use "~@wordpress/base-styles/variables" as wp-vars;
@@ -20,21 +20,21 @@
20
20
  // without per-component overrides.
21
21
  /* stylelint-disable plugin-wpds/no-setting-wpds-custom-properties -- deliberate Newspack brand override of the wpds brand tokens. */
22
22
  :root {
23
- --wpds-color-background-interactive-brand-strong: #{colors.$primary-600};
24
- --wpds-color-background-interactive-brand-strong-active: #{colors.$primary-800};
25
- --wpds-color-background-interactive-brand-weak-active: #{colors.$primary-000};
26
- --wpds-color-background-surface-brand: #{colors.$primary-000};
27
- --wpds-color-background-thumb-brand: #{colors.$primary-600};
28
- --wpds-color-background-thumb-brand-active: #{colors.$primary-600};
29
- --wpds-color-foreground-interactive-brand: #{colors.$primary-600};
30
- --wpds-color-foreground-interactive-brand-active: #{colors.$primary-800};
31
- --wpds-color-foreground-interactive-brand-disabled: #{colors.$primary-400};
32
- --wpds-color-stroke-focus: #{colors.$primary-600};
33
- --wpds-color-stroke-interactive-brand: #{colors.$primary-600};
34
- --wpds-color-stroke-interactive-brand-active: #{colors.$primary-800};
35
- --wpds-color-stroke-interactive-brand-disabled: #{colors.$primary-100};
36
- --wpds-color-stroke-surface-brand: #{colors.$primary-000};
37
- --wpds-color-stroke-surface-brand-strong: #{colors.$primary-600};
23
+ --wpds-color-background-interactive-brand-strong: #{np-colors.$primary-600};
24
+ --wpds-color-background-interactive-brand-strong-active: #{np-colors.$primary-800};
25
+ --wpds-color-background-interactive-brand-weak-active: #{np-colors.$primary-000};
26
+ --wpds-color-background-surface-brand: #{np-colors.$primary-000};
27
+ --wpds-color-background-thumb-brand: #{np-colors.$primary-600};
28
+ --wpds-color-background-thumb-brand-active: #{np-colors.$primary-600};
29
+ --wpds-color-foreground-interactive-brand: #{np-colors.$primary-600};
30
+ --wpds-color-foreground-interactive-brand-active: #{np-colors.$primary-800};
31
+ --wpds-color-foreground-interactive-brand-disabled: #{np-colors.$primary-400};
32
+ --wpds-color-stroke-focus: #{np-colors.$primary-600};
33
+ --wpds-color-stroke-interactive-brand: #{np-colors.$primary-600};
34
+ --wpds-color-stroke-interactive-brand-active: #{np-colors.$primary-800};
35
+ --wpds-color-stroke-interactive-brand-disabled: #{np-colors.$primary-100};
36
+ --wpds-color-stroke-surface-brand: #{np-colors.$primary-000};
37
+ --wpds-color-stroke-surface-brand-strong: #{np-colors.$primary-600};
38
38
  }
39
39
  /* stylelint-enable plugin-wpds/no-setting-wpds-custom-properties */
40
40
 
@@ -18,7 +18,7 @@ function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.
18
18
  import apiFetch from '@wordpress/api-fetch';
19
19
  import { Component } from '@wordpress/element';
20
20
  import { __ } from '@wordpress/i18n';
21
- import { Icon, check } from '@wordpress/icons';
21
+ import { Badge } from '@wordpress/ui';
22
22
 
23
23
  /**
24
24
  * Internal dependencies.
@@ -254,14 +254,10 @@ var PluginInstaller = /*#__PURE__*/function (_Component) {
254
254
  })]
255
255
  });
256
256
  } else if (Status === 'active') {
257
- actionText = /*#__PURE__*/_jsxs("span", {
258
- className: "newspack-plugin-installer__status",
259
- children: [__('Installed', 'newspack-plugin'), /*#__PURE__*/_jsx("span", {
260
- className: "newspack-checkbox-icon newspack-checkbox-icon--checked",
261
- children: /*#__PURE__*/_jsx(Icon, {
262
- icon: check
263
- })
264
- })]
257
+ // Installed is a state, not an action, so the slot takes a badge.
258
+ actionText = /*#__PURE__*/_jsx(Badge, {
259
+ intent: "stable",
260
+ children: __('Installed', 'newspack-plugin')
265
261
  });
266
262
  }
267
263
  var classes = classnames('newspack-action-card__plugin-installer', _this2.classForInstallationStatus(installationStatus));
@@ -2,8 +2,6 @@
2
2
  * Plugin Installer
3
3
  */
4
4
 
5
- @use "~@wordpress/base-styles/colors" as wp-colors;
6
-
7
5
  .newspack-card {
8
6
  .newspack-plugin-installer__status {
9
7
  align-items: center;
@@ -35,25 +33,16 @@
35
33
  }
36
34
 
37
35
  &.newspack-plugin-installer__status-active {
38
- box-shadow: inset 4px 0 0 wp-colors.$alert-green;
39
-
40
- .newspack-plugin-installer__checkbox {
41
- background: wp-colors.$alert-green;
42
- box-shadow: none;
43
- }
44
-
45
- svg {
46
- fill: white;
47
- }
36
+ box-shadow: inset 4px 0 0 var( --wpds-color-stroke-surface-success-strong, #008030 );
48
37
  }
49
38
 
50
39
  &.newspack-plugin-installer__status-error {
51
- box-shadow: inset 4px 0 0 wp-colors.$alert-red;
40
+ box-shadow: inset 4px 0 0 var( --wpds-color-stroke-surface-error-strong, #cc1818 );
52
41
  }
53
42
 
54
43
  &.newspack-plugin-installer__status-installing,
55
44
  &.newspack-plugin-installer__status-none {
56
- box-shadow: inset 4px 0 0 wp-colors.$gray-100;
45
+ box-shadow: inset 4px 0 0 var( --wpds-color-stroke-surface-neutral-weak, #f0f0f0 );
57
46
  }
58
47
 
59
48
  // Is Small
@@ -9,11 +9,13 @@ import { __ } from '@wordpress/i18n';
9
9
  import { useEffect, useRef } from '@wordpress/element';
10
10
  import { DropdownMenu, MenuItem, Tooltip, __experimentalHStack as HStack } from '@wordpress/components'; // eslint-disable-line @wordpress/no-unsafe-wp-apis
11
11
  import { Icon, chevronLeft, moreVertical } from '@wordpress/icons';
12
+ import { Badge } from '@wordpress/ui';
12
13
 
13
14
  /**
14
15
  * Internal dependencies
15
16
  */
16
- import { Badge, Button, Grid } from '..';
17
+ import Button from '../button';
18
+ import Grid from '../grid';
17
19
  import './style.scss';
18
20
 
19
21
  /**
@@ -26,17 +28,19 @@ import classnames from 'classnames';
26
28
  *
27
29
  * @typedef {Object} SectionHeaderProps
28
30
  * @property {string} [backNav=''] - URL to navigate back to.
29
- * @property {string|string[]} [badge] - Badge to display in the header.
30
- * @property {string} [badgeLevel] - Badge level, e.g., 'success', 'info', 'warning', 'error'.
31
+ * @property {Object[]} [badges] - Badges to display beside the title, each `{ label, intent }`.
31
32
  * @property {boolean} [centered=false] - Indicates if the header is centered.
32
- * @property {?string} [className=null] - Additional CSS class name.
33
+ * @property {?string} [className=null] - Additional CSS class name, applied to the outer container.
33
34
  * @property {string|Function|*} [description] - Description of the section.
34
35
  * @property {number} [heading=2] - HTML heading level, e.g., 1 for h1, 2 for h2, etc.
35
36
  * @property {string|Function|*} [icon] - Icon to display in the header.
36
37
  * @property {boolean} [isWhite=false] - Indicates if the header should use a white theme.
38
+ * @property {Object[]} [menu] - Overflow menu items.
37
39
  * @property {boolean} [noMargin=false] - Indicates if the header should have no margin.
38
40
  * @property {boolean} [pageHeader=false] - Indicates if the header is used as a page header.
39
- * @property {string} [size='default'] - Size variant, either 'default' or 'small'. Scales the title, and the icon with it, independently of `pageHeader`.
41
+ * @property {Object} [primaryAction] - Primary button, `{ label, href, action }`.
42
+ * @property {Object} [secondaryAction] - Secondary link, `{ label, href, action }`.
43
+ * @property {string} [size='default'] - Size variant: 'small', 'default', or 'hidden' to drop the title and description while the back nav stays visible.
40
44
  * @property {string} title - The title of the section.
41
45
  * @property {?string} [id=null] - Optional ID for the header element.
42
46
  * @property {?string|Function|*} [children=null] - Optional children to display in the header.
@@ -96,25 +100,31 @@ var SectionHeader = function SectionHeader(_ref) {
96
100
  }, 250);
97
101
  }
98
102
  }, []);
99
- var classes = classnames('newspack-section-header', centered && 'newspack-section-header--is-centered', isWhite && 'newspack-section-header--is-white', noMargin && 'newspack-section-header--no-margin', pageHeader && 'newspack-section-header--page-header', size === 'small' && 'newspack-section-header--small');
103
+ var classes = classnames('newspack-section-header', centered && 'newspack-section-header--is-centered', isWhite && 'newspack-section-header--is-white', noMargin && 'newspack-section-header--no-margin', pageHeader && 'newspack-section-header--page-header', size === 'small' && 'newspack-section-header--small', size === 'hidden' && 'newspack-section-header--hidden');
100
104
 
101
105
  // The breadcrumb `Page` owns the single page `<h1>`, so a `pageHeader` section
102
106
  // is a secondary heading: its level follows `heading` (default 2). `pageHeader`
103
107
  // controls only the enlarged, centered styling — not the tag. Pass `heading={ 1 }`
104
108
  // on a headerless screen that needs the section header to be the page's h1.
105
109
  var HeadingTag = "h".concat(heading);
110
+ // `hidden` drops the title rather than announcing a level no reader can see.
111
+ var hiddenText = size === 'hidden' ? 'newspack-section-header__hidden-text' : undefined;
106
112
  var titleContent = null;
113
+ var renderBadge = function renderBadge(badge, i) {
114
+ return /*#__PURE__*/_jsx(Badge, {
115
+ className: "newspack-section-header__badge",
116
+ intent: badge.intent || 'none',
117
+ children: badge.label
118
+ }, i);
119
+ };
107
120
  if (typeof title === 'string') {
108
121
  titleContent = /*#__PURE__*/_jsxs("div", {
109
122
  className: "newspack-section-header__title-container",
110
123
  children: [/*#__PURE__*/_jsxs(HeadingTag, {
111
- className: "newspack-section-header__title",
112
- children: [title, badges !== null && badges !== void 0 && badges.length ? badges.map(function (badge, i) {
113
- return /*#__PURE__*/_jsx(Badge, {
114
- text: badge.label,
115
- level: badge.level || 'default'
116
- }, i);
117
- }) : null]
124
+ className: classnames('newspack-section-header__title', hiddenText),
125
+ children: [title, (badges || []).filter(function (badge) {
126
+ return badge === null || badge === void 0 ? void 0 : badge.label;
127
+ }).map(renderBadge)]
118
128
  }), secondaryAction && /*#__PURE__*/_jsx("div", {
119
129
  className: "newspack-section-header__secondary-action",
120
130
  children: /*#__PURE__*/_jsx(Button, {
@@ -143,7 +153,7 @@ var SectionHeader = function SectionHeader(_ref) {
143
153
  });
144
154
  } else if (typeof title === 'function') {
145
155
  titleContent = /*#__PURE__*/_jsx(HeadingTag, {
146
- className: "newspack-section-header__title",
156
+ className: classnames('newspack-section-header__title', hiddenText),
147
157
  children: title()
148
158
  });
149
159
  }
@@ -178,10 +188,13 @@ var SectionHeader = function SectionHeader(_ref) {
178
188
  })
179
189
  }), titleContent]
180
190
  }) : titleContent, description && typeof description === 'string' && /*#__PURE__*/_jsx("p", {
191
+ className: hiddenText,
181
192
  children: description
182
193
  }), typeof description === 'function' && /*#__PURE__*/_jsx("p", {
194
+ className: hiddenText,
183
195
  children: description()
184
196
  }), description && typeof description !== 'string' && typeof description !== 'function' && /*#__PURE__*/_jsx("p", {
197
+ className: hiddenText,
185
198
  children: description
186
199
  }), children && /*#__PURE__*/_jsx("div", {
187
200
  className: "newspack-section-header__children",
@@ -0,0 +1,36 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { envelope } from '@wordpress/icons';
5
+
6
+ /**
7
+ * External dependencies
8
+ */
9
+ import { render } from '@testing-library/react';
10
+
11
+ /**
12
+ * Internal dependencies
13
+ */
14
+ import SectionHeader from '.';
15
+ import { jsx as _jsx } from "react/jsx-runtime";
16
+ describe('SectionHeader size', function () {
17
+ it('renders a 48px icon and no small modifier by default', function () {
18
+ var _render = render(/*#__PURE__*/_jsx(SectionHeader, {
19
+ title: "Get started",
20
+ icon: envelope
21
+ })),
22
+ container = _render.container;
23
+ expect(container.querySelector('.newspack-section-header--small')).not.toBeInTheDocument();
24
+ expect(container.querySelector('.newspack-section-header__icon svg')).toHaveAttribute('width', '48');
25
+ });
26
+ it('renders a 24px icon and the small modifier at size="small"', function () {
27
+ var _render2 = render(/*#__PURE__*/_jsx(SectionHeader, {
28
+ title: "Get started",
29
+ icon: envelope,
30
+ size: "small"
31
+ })),
32
+ container = _render2.container;
33
+ expect(container.querySelector('.newspack-section-header--small')).toBeInTheDocument();
34
+ expect(container.querySelector('.newspack-section-header__icon svg')).toHaveAttribute('width', '24');
35
+ });
36
+ });
@@ -2,10 +2,10 @@
2
2
  * Section Header
3
3
  */
4
4
 
5
+ @use "~@wordpress/base-styles/breakpoints" as wp-breakpoints;
5
6
  @use "~@wordpress/base-styles/colors" as wp-colors;
6
7
  @use "~@wordpress/base-styles/variables" as wp-vars;
7
8
  @use "~@wordpress/base-styles/mixins" as wp-mixins;
8
- @use "../../../colors/colors.module" as colors;
9
9
 
10
10
  .newspack-section-header {
11
11
  flex: 1;
@@ -22,6 +22,9 @@
22
22
  &:has(> .newspack-section-header--no-margin) {
23
23
  margin-top: 0;
24
24
  }
25
+ &:has(> .newspack-section-header--hidden) {
26
+ margin-block: 0;
27
+ }
25
28
  &.newspack-section-header--has-primary-action {
26
29
  display: flex;
27
30
  flex-direction: column;
@@ -32,7 +35,7 @@
32
35
  }
33
36
  }
34
37
  &.newspack-section-header--has-back-nav {
35
- @media (min-width: 782px) {
38
+ @include wp-mixins.break-wide {
36
39
  .newspack-section-header__title-container,
37
40
  p {
38
41
  max-width: calc(50% - 16px);
@@ -42,7 +45,10 @@
42
45
  }
43
46
 
44
47
  &__back-nav {
45
- @media (min-width: 1280px) {
48
+ @media (max-width: #{wp-breakpoints.$break-wide - 1px}) {
49
+ display: none;
50
+ }
51
+ @include wp-mixins.break-wide {
46
52
  left: 0;
47
53
  position: absolute;
48
54
  top: 50%;
@@ -101,6 +107,18 @@
101
107
  }
102
108
  }
103
109
 
110
+ &#{&}--hidden {
111
+ .newspack-section-header__hidden-text {
112
+ display: none;
113
+ }
114
+
115
+ .newspack-section-header__back-nav {
116
+ @include wp-mixins.break-wide {
117
+ transform: translate(calc(-100% - 8px), calc(-50% + 12px));
118
+ }
119
+ }
120
+ }
121
+
104
122
  &__icon {
105
123
  background-color: var(--wp-admin-theme-color-lighter-10);
106
124
  border-radius: 100%;
@@ -125,9 +143,7 @@
125
143
  display: flex;
126
144
  gap: 8px;
127
145
 
128
- .newspack-section-header__menu,
129
- .newspack-section-header__secondary-action,
130
- .newspack-badge {
146
+ .newspack-section-header__secondary-action {
131
147
  margin-top: 8px;
132
148
  }
133
149
  }