@wordpress/components 27.0.0 → 27.1.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 (208) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/build/base-control/index.native.js.map +1 -1
  3. package/build/border-box-control/border-box-control/component.js.map +1 -1
  4. package/build/border-box-control/border-box-control-split-controls/component.js.map +1 -1
  5. package/build/border-control/border-control-dropdown/component.js.map +1 -1
  6. package/build/button/index.js +2 -2
  7. package/build/button/index.js.map +1 -1
  8. package/build/button/index.native.js.map +1 -1
  9. package/build/confirm-dialog/component.js.map +1 -1
  10. package/build/custom-select-control-v2/default-component/index.js.map +1 -1
  11. package/build/custom-select-control-v2/index.js +2 -2
  12. package/build/custom-select-control-v2/index.js.map +1 -1
  13. package/build/custom-select-control-v2/types.js.map +1 -1
  14. package/build/draggable/index.native.js +2 -2
  15. package/build/draggable/index.native.js.map +1 -1
  16. package/build/dropdown-menu/index.native.js.map +1 -1
  17. package/build/flex/flex/hook.js +1 -1
  18. package/build/flex/flex/hook.js.map +1 -1
  19. package/build/font-size-picker/index.native.js.map +1 -1
  20. package/build/form-token-field/index.js.map +1 -1
  21. package/build/h-stack/hook.js +6 -1
  22. package/build/h-stack/hook.js.map +1 -1
  23. package/build/mobile/bottom-sheet/button.native.js.map +1 -1
  24. package/build/mobile/bottom-sheet/index.native.js.map +1 -1
  25. package/build/mobile/bottom-sheet/range-cell.native.js.map +1 -1
  26. package/build/mobile/bottom-sheet/stepper-cell/index.native.js.map +1 -1
  27. package/build/mobile/bottom-sheet-select-control/index.native.js.map +1 -1
  28. package/build/mobile/bottom-sheet-text-control/index.native.js.map +1 -1
  29. package/build/mobile/gradient/index.native.js.map +1 -1
  30. package/build/mobile/image/index.native.js +4 -13
  31. package/build/mobile/image/index.native.js.map +1 -1
  32. package/build/mobile/media-edit/index.native.js.map +1 -1
  33. package/build/palette-edit/index.js.map +1 -1
  34. package/build/query-controls/index.native.js.map +1 -1
  35. package/build/range-control/index.js.map +1 -1
  36. package/build/search-control/index.native.js.map +1 -1
  37. package/build/snackbar/index.js +3 -2
  38. package/build/snackbar/index.js.map +1 -1
  39. package/build/snackbar/list.js +2 -1
  40. package/build/snackbar/list.js.map +1 -1
  41. package/build/snackbar/types.js.map +1 -1
  42. package/build/tabs/index.js +7 -7
  43. package/build/tabs/index.js.map +1 -1
  44. package/build/tabs/types.js.map +1 -1
  45. package/build/utils/hooks/index.js +0 -7
  46. package/build/utils/hooks/index.js.map +1 -1
  47. package/build-module/base-control/index.native.js.map +1 -1
  48. package/build-module/border-box-control/border-box-control/component.js.map +1 -1
  49. package/build-module/border-box-control/border-box-control-split-controls/component.js.map +1 -1
  50. package/build-module/border-control/border-control-dropdown/component.js.map +1 -1
  51. package/build-module/button/index.js +2 -2
  52. package/build-module/button/index.js.map +1 -1
  53. package/build-module/button/index.native.js.map +1 -1
  54. package/build-module/confirm-dialog/component.js.map +1 -1
  55. package/build-module/custom-select-control-v2/default-component/index.js.map +1 -1
  56. package/build-module/custom-select-control-v2/index.js +1 -1
  57. package/build-module/custom-select-control-v2/index.js.map +1 -1
  58. package/build-module/custom-select-control-v2/types.js.map +1 -1
  59. package/build-module/draggable/index.native.js +2 -2
  60. package/build-module/draggable/index.native.js.map +1 -1
  61. package/build-module/dropdown-menu/index.native.js.map +1 -1
  62. package/build-module/flex/flex/hook.js +1 -1
  63. package/build-module/flex/flex/hook.js.map +1 -1
  64. package/build-module/font-size-picker/index.native.js.map +1 -1
  65. package/build-module/form-token-field/index.js.map +1 -1
  66. package/build-module/h-stack/hook.js +6 -1
  67. package/build-module/h-stack/hook.js.map +1 -1
  68. package/build-module/mobile/bottom-sheet/button.native.js.map +1 -1
  69. package/build-module/mobile/bottom-sheet/index.native.js.map +1 -1
  70. package/build-module/mobile/bottom-sheet/range-cell.native.js.map +1 -1
  71. package/build-module/mobile/bottom-sheet/stepper-cell/index.native.js.map +1 -1
  72. package/build-module/mobile/bottom-sheet-select-control/index.native.js.map +1 -1
  73. package/build-module/mobile/bottom-sheet-text-control/index.native.js.map +1 -1
  74. package/build-module/mobile/gradient/index.native.js.map +1 -1
  75. package/build-module/mobile/image/index.native.js +6 -15
  76. package/build-module/mobile/image/index.native.js.map +1 -1
  77. package/build-module/mobile/media-edit/index.native.js.map +1 -1
  78. package/build-module/palette-edit/index.js.map +1 -1
  79. package/build-module/query-controls/index.native.js.map +1 -1
  80. package/build-module/range-control/index.js.map +1 -1
  81. package/build-module/search-control/index.native.js.map +1 -1
  82. package/build-module/snackbar/index.js +3 -2
  83. package/build-module/snackbar/index.js.map +1 -1
  84. package/build-module/snackbar/list.js +2 -1
  85. package/build-module/snackbar/list.js.map +1 -1
  86. package/build-module/snackbar/types.js.map +1 -1
  87. package/build-module/tabs/index.js +7 -7
  88. package/build-module/tabs/index.js.map +1 -1
  89. package/build-module/tabs/types.js.map +1 -1
  90. package/build-module/utils/hooks/index.js +0 -1
  91. package/build-module/utils/hooks/index.js.map +1 -1
  92. package/build-style/style-rtl.css +8 -1
  93. package/build-style/style.css +8 -1
  94. package/build-types/custom-select-control-v2/default-component/index.d.ts +2 -1
  95. package/build-types/custom-select-control-v2/default-component/index.d.ts.map +1 -1
  96. package/build-types/custom-select-control-v2/index.d.ts +1 -1
  97. package/build-types/custom-select-control-v2/index.d.ts.map +1 -1
  98. package/build-types/custom-select-control-v2/legacy-component/test/index.d.ts +2 -0
  99. package/build-types/custom-select-control-v2/legacy-component/test/index.d.ts.map +1 -0
  100. package/build-types/custom-select-control-v2/stories/default.story.d.ts +4 -3
  101. package/build-types/custom-select-control-v2/stories/default.story.d.ts.map +1 -1
  102. package/build-types/custom-select-control-v2/stories/legacy.story.d.ts +2 -2
  103. package/build-types/custom-select-control-v2/stories/legacy.story.d.ts.map +1 -1
  104. package/build-types/custom-select-control-v2/types.d.ts +0 -1
  105. package/build-types/custom-select-control-v2/types.d.ts.map +1 -1
  106. package/build-types/flex/flex/hook.d.ts +2 -3
  107. package/build-types/flex/flex/hook.d.ts.map +1 -1
  108. package/build-types/h-stack/hook.d.ts +2 -4
  109. package/build-types/h-stack/hook.d.ts.map +1 -1
  110. package/build-types/navigation/stories/utils/hide-if-empty.d.ts.map +1 -1
  111. package/build-types/radio-group/stories/index.story.d.ts.map +1 -1
  112. package/build-types/snackbar/index.d.ts +5 -2
  113. package/build-types/snackbar/index.d.ts.map +1 -1
  114. package/build-types/snackbar/list.d.ts.map +1 -1
  115. package/build-types/snackbar/test/index.d.ts +2 -0
  116. package/build-types/snackbar/test/index.d.ts.map +1 -0
  117. package/build-types/snackbar/test/list.d.ts +2 -0
  118. package/build-types/snackbar/test/list.d.ts.map +1 -0
  119. package/build-types/snackbar/types.d.ts +18 -2
  120. package/build-types/snackbar/types.d.ts.map +1 -1
  121. package/build-types/tabs/index.d.ts +1 -1
  122. package/build-types/tabs/types.d.ts +1 -1
  123. package/build-types/utils/hooks/index.d.ts +0 -1
  124. package/build-types/v-stack/hook.d.ts +2 -4
  125. package/build-types/v-stack/hook.d.ts.map +1 -1
  126. package/package.json +19 -19
  127. package/src/base-control/index.native.js +1 -1
  128. package/src/base-control/test/index.tsx +1 -1
  129. package/src/border-box-control/border-box-control/component.tsx +1 -1
  130. package/src/border-box-control/border-box-control-split-controls/component.tsx +4 -4
  131. package/src/border-control/border-control-dropdown/component.tsx +1 -1
  132. package/src/button/index.native.js +1 -1
  133. package/src/button/index.tsx +1 -1
  134. package/src/button/style.scss +1 -3
  135. package/src/circular-option-picker/test/index.tsx +2 -4
  136. package/src/combobox-control/test/index.tsx +1 -1
  137. package/src/confirm-dialog/component.tsx +1 -1
  138. package/src/confirm-dialog/test/index.tsx +5 -21
  139. package/src/custom-select-control-v2/default-component/index.tsx +4 -1
  140. package/src/custom-select-control-v2/index.tsx +1 -1
  141. package/src/custom-select-control-v2/legacy-component/test/index.tsx +457 -0
  142. package/src/custom-select-control-v2/stories/legacy.story.tsx +5 -6
  143. package/src/custom-select-control-v2/test/index.tsx +279 -749
  144. package/src/custom-select-control-v2/types.ts +0 -1
  145. package/src/disabled/test/index.tsx +1 -1
  146. package/src/draggable/index.native.js +2 -2
  147. package/src/draggable/test/index.native.js +6 -2
  148. package/src/dropdown-menu/index.native.js +2 -2
  149. package/src/flex/flex/hook.ts +1 -1
  150. package/src/font-size-picker/index.native.js +2 -2
  151. package/src/form-token-field/index.tsx +1 -1
  152. package/src/h-stack/hook.tsx +2 -1
  153. package/src/h-stack/test/index.tsx +10 -0
  154. package/src/item-group/test/index.js +2 -2
  155. package/src/mobile/bottom-sheet/bottom-sheet-navigation/test/navigation-container.native.js +10 -15
  156. package/src/mobile/bottom-sheet/button.native.js +1 -5
  157. package/src/mobile/bottom-sheet/index.native.js +2 -2
  158. package/src/mobile/bottom-sheet/range-cell.native.js +1 -1
  159. package/src/mobile/bottom-sheet/stepper-cell/index.native.js +2 -2
  160. package/src/mobile/bottom-sheet-select-control/index.native.js +1 -1
  161. package/src/mobile/bottom-sheet-text-control/index.native.js +1 -1
  162. package/src/mobile/gradient/index.native.js +1 -1
  163. package/src/mobile/image/index.native.js +8 -23
  164. package/src/mobile/media-edit/index.native.js +1 -1
  165. package/src/modal/test/index.tsx +1 -1
  166. package/src/navigation/stories/utils/hide-if-empty.tsx +2 -6
  167. package/src/palette-edit/index.tsx +2 -2
  168. package/src/popover/test/index.tsx +1 -4
  169. package/src/query-controls/index.native.js +2 -2
  170. package/src/radio-group/stories/index.story.tsx +1 -0
  171. package/src/range-control/index.tsx +3 -3
  172. package/src/range-control/test/index.tsx +2 -2
  173. package/src/search-control/index.native.js +1 -1
  174. package/src/snackbar/index.tsx +5 -2
  175. package/src/snackbar/list.tsx +6 -1
  176. package/src/snackbar/stories/list.story.tsx +0 -3
  177. package/src/snackbar/test/index.tsx +267 -0
  178. package/src/snackbar/test/list.tsx +46 -0
  179. package/src/snackbar/types.ts +31 -3
  180. package/src/tabs/README.md +18 -18
  181. package/src/tabs/index.tsx +7 -7
  182. package/src/tabs/stories/index.story.tsx +1 -1
  183. package/src/tabs/test/index.tsx +30 -30
  184. package/src/tabs/types.ts +1 -1
  185. package/src/toggle-group-control/test/index.tsx +1 -1
  186. package/src/tools-panel/stories/index.story.tsx +8 -8
  187. package/src/tools-panel/test/index.tsx +10 -28
  188. package/src/tooltip/style.scss +2 -1
  189. package/src/tooltip/test/index.native.js +3 -3
  190. package/src/tree-grid/test/index.tsx +1 -1
  191. package/src/utils/hooks/index.js +0 -1
  192. package/src/v-stack/test/index.tsx +10 -0
  193. package/tsconfig.tsbuildinfo +1 -1
  194. package/build/custom-select-control-v2/legacy-adapter.js +0 -29
  195. package/build/custom-select-control-v2/legacy-adapter.js.map +0 -1
  196. package/build/utils/hooks/use-latest-ref.js +0 -33
  197. package/build/utils/hooks/use-latest-ref.js.map +0 -1
  198. package/build-module/custom-select-control-v2/legacy-adapter.js +0 -21
  199. package/build-module/custom-select-control-v2/legacy-adapter.js.map +0 -1
  200. package/build-module/utils/hooks/use-latest-ref.js +0 -27
  201. package/build-module/utils/hooks/use-latest-ref.js.map +0 -1
  202. package/build-types/custom-select-control-v2/legacy-adapter.d.ts +0 -6
  203. package/build-types/custom-select-control-v2/legacy-adapter.d.ts.map +0 -1
  204. package/build-types/utils/hooks/use-latest-ref.d.ts +0 -15
  205. package/build-types/utils/hooks/use-latest-ref.d.ts.map +0 -1
  206. package/src/custom-select-control-v2/legacy-adapter.tsx +0 -25
  207. package/src/utils/hooks/test/use-latest-ref.js +0 -119
  208. package/src/utils/hooks/use-latest-ref.ts +0 -29
@@ -0,0 +1,267 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { render, screen, within } from '@testing-library/react';
5
+ import { click } from '@ariakit/test';
6
+
7
+ /**
8
+ * WordPress dependencies
9
+ */
10
+ import { speak } from '@wordpress/a11y';
11
+ import { SVG, Path } from '@wordpress/primitives';
12
+
13
+ /**
14
+ * Internal dependencies
15
+ */
16
+ import Snackbar from '../index';
17
+
18
+ jest.mock( '@wordpress/a11y', () => ( { speak: jest.fn() } ) );
19
+ const mockedSpeak = jest.mocked( speak );
20
+
21
+ describe( 'Snackbar', () => {
22
+ const testId = 'snackbar';
23
+
24
+ beforeEach( () => {
25
+ mockedSpeak.mockReset();
26
+ } );
27
+
28
+ it( 'should render correctly', () => {
29
+ render( <Snackbar>Message</Snackbar> );
30
+
31
+ const snackbar = screen.getByTestId( testId );
32
+
33
+ expect( snackbar ).toBeVisible();
34
+ expect( snackbar ).toHaveTextContent( 'Message' );
35
+ } );
36
+
37
+ it( 'should render with an additional className', () => {
38
+ render( <Snackbar className="gutenberg">Message</Snackbar> );
39
+
40
+ expect( screen.getByTestId( testId ) ).toHaveClass( 'gutenberg' );
41
+ } );
42
+
43
+ it( 'should render with an icon', () => {
44
+ const testIcon = (
45
+ <SVG data-testid="icon">
46
+ <Path />
47
+ </SVG>
48
+ );
49
+
50
+ render( <Snackbar icon={ testIcon }>Message</Snackbar> );
51
+
52
+ const snackbar = screen.getByTestId( testId );
53
+ const icon = within( snackbar ).getByTestId( 'icon' );
54
+
55
+ expect( icon ).toBeVisible();
56
+ } );
57
+
58
+ it( 'should be dismissible by clicking the snackbar', async () => {
59
+ const onRemove = jest.fn();
60
+ const onDismiss = jest.fn();
61
+
62
+ render(
63
+ <Snackbar onRemove={ onRemove } onDismiss={ onDismiss }>
64
+ Message
65
+ </Snackbar>
66
+ );
67
+
68
+ const snackbar = screen.getByTestId( testId );
69
+
70
+ expect( snackbar ).toHaveAttribute( 'role', 'button' );
71
+ expect( snackbar ).toHaveAttribute(
72
+ 'aria-label',
73
+ 'Dismiss this notice'
74
+ );
75
+
76
+ await click( snackbar );
77
+
78
+ expect( onRemove ).toHaveBeenCalledTimes( 1 );
79
+ expect( onDismiss ).toHaveBeenCalledTimes( 1 );
80
+ } );
81
+
82
+ it( 'should not be dismissible by clicking the snackbar when the `explicitDismiss` prop is set to `true`', async () => {
83
+ const onRemove = jest.fn();
84
+ const onDismiss = jest.fn();
85
+
86
+ render(
87
+ <Snackbar
88
+ explicitDismiss
89
+ onRemove={ onRemove }
90
+ onDismiss={ onDismiss }
91
+ >
92
+ Message
93
+ </Snackbar>
94
+ );
95
+
96
+ const snackbar = screen.getByTestId( testId );
97
+
98
+ expect( snackbar ).not.toHaveAttribute( 'role', 'button' );
99
+ expect( snackbar ).not.toHaveAttribute(
100
+ 'aria-label',
101
+ 'Dismiss this notice'
102
+ );
103
+ expect( snackbar ).toHaveClass(
104
+ 'components-snackbar-explicit-dismiss'
105
+ );
106
+
107
+ await click( snackbar );
108
+
109
+ expect( onRemove ).not.toHaveBeenCalled();
110
+ expect( onDismiss ).not.toHaveBeenCalled();
111
+ } );
112
+
113
+ it( 'should be dismissible by clicking the close button when the `explicitDismiss` prop is set to `true`', async () => {
114
+ const onRemove = jest.fn();
115
+ const onDismiss = jest.fn();
116
+
117
+ render(
118
+ <Snackbar
119
+ explicitDismiss
120
+ onRemove={ onRemove }
121
+ onDismiss={ onDismiss }
122
+ >
123
+ Message
124
+ </Snackbar>
125
+ );
126
+
127
+ const snackbar = screen.getByTestId( testId );
128
+ const closeButton = within( snackbar ).getByRole( 'button', {
129
+ name: 'Dismiss this notice',
130
+ } );
131
+
132
+ await click( closeButton );
133
+
134
+ expect( onRemove ).toHaveBeenCalledTimes( 1 );
135
+ expect( onDismiss ).toHaveBeenCalledTimes( 1 );
136
+ } );
137
+
138
+ describe( 'actions', () => {
139
+ it( 'should render only the first action with a warning when multiple actions are passed', () => {
140
+ render(
141
+ <Snackbar
142
+ actions={ [
143
+ { label: 'One', url: 'https://example.com' },
144
+ { label: 'Two', url: 'https://example.com' },
145
+ { label: 'Three', url: 'https://example.com' },
146
+ ] }
147
+ >
148
+ Message
149
+ </Snackbar>
150
+ );
151
+
152
+ expect( console ).toHaveWarnedWith(
153
+ 'Snackbar can only have one action. Use Notice if your message requires many actions.'
154
+ );
155
+
156
+ const snackbar = screen.getByTestId( testId );
157
+ const action = within( snackbar ).getByRole( 'link' );
158
+
159
+ expect( action ).toBeVisible();
160
+ expect( action ).toHaveTextContent( 'One' );
161
+ } );
162
+
163
+ it( 'should be rendered as a link when the `url` prop is set', () => {
164
+ render(
165
+ <Snackbar
166
+ actions={ [
167
+ { label: 'View post', url: 'https://example.com' },
168
+ ] }
169
+ >
170
+ Post updated.
171
+ </Snackbar>
172
+ );
173
+
174
+ const snackbar = screen.getByTestId( testId );
175
+ const link = within( snackbar ).getByRole( 'link', {
176
+ name: 'View post',
177
+ } );
178
+
179
+ expect( link ).toHaveAttribute( 'href', 'https://example.com' );
180
+ } );
181
+
182
+ it( 'should be rendered as a button and call `onClick` when the `onClick` prop is set', async () => {
183
+ const onClick = jest.fn();
184
+
185
+ render(
186
+ <Snackbar actions={ [ { label: 'View post', onClick } ] }>
187
+ Post updated.
188
+ </Snackbar>
189
+ );
190
+
191
+ const snackbar = screen.getByTestId( testId );
192
+ const button = within( snackbar ).getByRole( 'button', {
193
+ name: 'View post',
194
+ } );
195
+
196
+ await click( button );
197
+
198
+ expect( onClick ).toHaveBeenCalledTimes( 1 );
199
+ } );
200
+
201
+ it( 'should be rendered as a link when the `url` prop and the `onClick` are set', () => {
202
+ render(
203
+ <Snackbar
204
+ actions={ [
205
+ {
206
+ label: 'View post',
207
+ url: 'https://example.com',
208
+ onClick: () => {},
209
+ },
210
+ ] }
211
+ >
212
+ Post updated.
213
+ </Snackbar>
214
+ );
215
+
216
+ const snackbar = screen.getByTestId( testId );
217
+ const link = within( snackbar ).getByRole( 'link', {
218
+ name: 'View post',
219
+ } );
220
+ expect( link ).toBeVisible();
221
+ } );
222
+ } );
223
+
224
+ describe( 'useSpokenMessage', () => {
225
+ it( 'should speak the given message', () => {
226
+ render( <Snackbar>FYI</Snackbar> );
227
+
228
+ expect( speak ).toHaveBeenCalledWith( 'FYI', 'polite' );
229
+ } );
230
+
231
+ it( 'should speak the given message by explicit politeness', () => {
232
+ render( <Snackbar politeness="assertive">Uh oh!</Snackbar> );
233
+
234
+ expect( speak ).toHaveBeenCalledWith( 'Uh oh!', 'assertive' );
235
+ } );
236
+
237
+ it( 'should coerce a message to a string', () => {
238
+ // This test assumes that `@wordpress/a11y` is capable of handling
239
+ // markup strings appropriately.
240
+ render(
241
+ <Snackbar>
242
+ With <em>emphasis</em> this time.
243
+ </Snackbar>
244
+ );
245
+
246
+ expect( speak ).toHaveBeenCalledWith(
247
+ 'With <em>emphasis</em> this time.',
248
+ 'polite'
249
+ );
250
+ } );
251
+
252
+ it( 'should not re-speak an effectively equivalent element message', () => {
253
+ const { rerender } = render(
254
+ <Snackbar>
255
+ With <em>emphasis</em> this time.
256
+ </Snackbar>
257
+ );
258
+ rerender(
259
+ <Snackbar>
260
+ With <em>emphasis</em> this time.
261
+ </Snackbar>
262
+ );
263
+
264
+ expect( speak ).toHaveBeenCalledTimes( 1 );
265
+ } );
266
+ } );
267
+ } );
@@ -0,0 +1,46 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { render, screen } from '@testing-library/react';
5
+ import { click } from '@ariakit/test';
6
+
7
+ /**
8
+ * Internal dependencies
9
+ */
10
+ import SnackbarList from '../list';
11
+
12
+ window.scrollTo = jest.fn();
13
+
14
+ describe( 'SnackbarList', () => {
15
+ afterEach( () => {
16
+ jest.resetAllMocks();
17
+ } );
18
+
19
+ it( 'should get focus after a snackbar is dismissed', async () => {
20
+ render(
21
+ <SnackbarList
22
+ notices={ [
23
+ {
24
+ id: 'ID_1',
25
+ content: 'Post published.',
26
+ explicitDismiss: true,
27
+ },
28
+ {
29
+ id: 'ID_2',
30
+ content: 'Post updated.',
31
+ explicitDismiss: true,
32
+ },
33
+ ] }
34
+ onRemove={ () => {} }
35
+ />
36
+ );
37
+
38
+ await click(
39
+ screen.getAllByRole( 'button', {
40
+ name: 'Dismiss this notice',
41
+ } )[ 0 ]
42
+ );
43
+
44
+ expect( screen.getByTestId( 'snackbar-list' ) ).toHaveFocus();
45
+ } );
46
+ } );
@@ -6,7 +6,11 @@ import type { MutableRefObject, ReactNode } from 'react';
6
6
  /**
7
7
  * Internal dependencies
8
8
  */
9
- import type { NoticeProps, NoticeChildren } from '../notice/types';
9
+ import type {
10
+ NoticeProps,
11
+ NoticeChildren,
12
+ NoticeAction,
13
+ } from '../notice/types';
10
14
 
11
15
  type SnackbarOnlyProps = {
12
16
  /**
@@ -28,8 +32,32 @@ type SnackbarOnlyProps = {
28
32
  listRef?: MutableRefObject< HTMLDivElement | null >;
29
33
  };
30
34
 
31
- export type SnackbarProps = Omit< NoticeProps, '__unstableHTML' > &
32
- SnackbarOnlyProps;
35
+ export type SnackbarProps = Pick<
36
+ NoticeProps,
37
+ | 'className'
38
+ | 'children'
39
+ | 'spokenMessage'
40
+ | 'onRemove'
41
+ | 'politeness'
42
+ | 'onDismiss'
43
+ > &
44
+ SnackbarOnlyProps & {
45
+ /**
46
+ * An array of action objects. Each member object should contain:
47
+ *
48
+ * - `label`: `string` containing the text of the button/link
49
+ * - `url`: `string` OR `onClick`: `( event: SyntheticEvent ) => void` to specify
50
+ * what the action does.
51
+ *
52
+ * The default appearance of an action button is inferred based on whether
53
+ * `url` or `onClick` are provided, rendering the button as a link if
54
+ * appropriate. If both props are provided, `url` takes precedence, and the
55
+ * action button will render as an anchor tag.
56
+ *
57
+ * @default []
58
+ */
59
+ actions?: Pick< NoticeAction, 'label' | 'url' | 'onClick' >[];
60
+ };
33
61
 
34
62
  export type SnackbarListProps = {
35
63
  notices: Array<
@@ -14,7 +14,7 @@ Tabs organizes content across different screens, data sets, and interactions. It
14
14
 
15
15
  #### Uncontrolled Mode
16
16
 
17
- Tabs can be used in an uncontrolled mode, where the component manages its own state. In this mode, the `initialTabId` prop can be used to set the initially selected tab. If this prop is not set, the first tab will be selected by default. In addition, in most cases where the currently active tab becomes disabled or otherwise unavailable, uncontrolled mode will automatically fall back to selecting the first available tab.
17
+ Tabs can be used in an uncontrolled mode, where the component manages its own state. In this mode, the `defaultTabId` prop can be used to set the initially selected tab. If this prop is not set, the first tab will be selected by default. In addition, in most cases where the currently active tab becomes disabled or otherwise unavailable, uncontrolled mode will automatically fall back to selecting the first available tab.
18
18
 
19
19
  ```jsx
20
20
  import { Tabs } from '@wordpress/components';
@@ -24,25 +24,25 @@ const onSelect = ( tabName ) => {
24
24
  };
25
25
 
26
26
  const MyUncontrolledTabs = () => (
27
- <Tabs onSelect={onSelect} initialTab="tab2">
28
- <Tabs.TabList >
29
- <Tabs.Tab id={ 'tab1' } title={ 'Tab 1' }>
27
+ <Tabs onSelect={ onSelect } defaultTabId="tab2">
28
+ <Tabs.TabList>
29
+ <Tabs.Tab tabId="tab1" title="Tab 1">
30
30
  Tab 1
31
31
  </Tabs.Tab>
32
- <Tabs.Tab id={ 'tab2' } title={ 'Tab 2' }>
32
+ <Tabs.Tab tabId="tab2" title="Tab 2">
33
33
  Tab 2
34
34
  </Tabs.Tab>
35
- <Tabs.Tab id={ 'tab3' } title={ 'Tab 3' }>
35
+ <Tabs.Tab tabId="tab3" title="Tab 3">
36
36
  Tab 3
37
37
  </Tabs.Tab>
38
38
  </Tabs.TabList>
39
- <Tabs.TabPanel id={ 'tab1' }>
39
+ <Tabs.TabPanel tabId="tab1">
40
40
  <p>Selected tab: Tab 1</p>
41
41
  </Tabs.TabPanel>
42
- <Tabs.TabPanel id={ 'tab2' }>
42
+ <Tabs.TabPanel tabId="tab2">
43
43
  <p>Selected tab: Tab 2</p>
44
44
  </Tabs.TabPanel>
45
- <Tabs.TabPanel id={ 'tab3' }>
45
+ <Tabs.TabPanel tabId="tab3">
46
46
  <p>Selected tab: Tab 3</p>
47
47
  </Tabs.TabPanel>
48
48
  </Tabs>
@@ -51,7 +51,7 @@ const MyUncontrolledTabs = () => (
51
51
 
52
52
  #### Controlled Mode
53
53
 
54
- Tabs can also be used in a controlled mode, where the parent component specifies the `selectedTabId` and the `onSelect` props to control tab selection. In this mode, the `initialTabId` prop will be ignored if it is provided. If the `selectedTabId` is `null`, no tab is selected. In this mode, if the currently selected tab becomes disabled or otherwise unavailable, the component will _not_ fall back to another available tab, leaving the controlling component in charge of implementing the desired logic.
54
+ Tabs can also be used in a controlled mode, where the parent component specifies the `selectedTabId` and the `onSelect` props to control tab selection. In this mode, the `defaultTabId` prop will be ignored if it is provided. If the `selectedTabId` is `null`, no tab is selected. In this mode, if the currently selected tab becomes disabled or otherwise unavailable, the component will _not_ fall back to another available tab, leaving the controlling component in charge of implementing the desired logic.
55
55
 
56
56
  ```jsx
57
57
  import { Tabs } from '@wordpress/components';
@@ -71,24 +71,24 @@ const MyControlledTabs = () => (
71
71
  onSelect( selectedId );
72
72
  } }
73
73
  >
74
- <Tabs.TabList >
75
- <Tabs.Tab id={ 'tab1' } title={ 'Tab 1' }>
74
+ <Tabs.TabList>
75
+ <Tabs.Tab tabId="tab1" title="Tab 1">
76
76
  Tab 1
77
77
  </Tabs.Tab>
78
- <Tabs.Tab id={ 'tab2' } title={ 'Tab 2' }>
78
+ <Tabs.Tab tabId="tab2" title="Tab 2">
79
79
  Tab 2
80
80
  </Tabs.Tab>
81
- <Tabs.Tab id={ 'tab3' } title={ 'Tab 3' }>
81
+ <Tabs.Tab tabId="tab3" title="Tab 3">
82
82
  Tab 3
83
83
  </Tabs.Tab>
84
84
  </Tabs.TabList>
85
- <Tabs.TabPanel id={ 'tab1' }>
85
+ <Tabs.TabPanel tabId="tab1">
86
86
  <p>Selected tab: Tab 1</p>
87
87
  </Tabs.TabPanel>
88
- <Tabs.TabPanel id={ 'tab2' }>
88
+ <Tabs.TabPanel tabId="tab2">
89
89
  <p>Selected tab: Tab 2</p>
90
90
  </Tabs.TabPanel>
91
- <Tabs.TabPanel id={ 'tab3' }>
91
+ <Tabs.TabPanel tabId="tab3">
92
92
  <p>Selected tab: Tab 3</p>
93
93
  </Tabs.TabPanel>
94
94
  </Tabs>
@@ -120,7 +120,7 @@ When `true`, the tab will be selected when receiving focus (automatic tab activa
120
120
  - Required: No
121
121
  - Default: `true`
122
122
 
123
- ###### `initialTabId`: `string`
123
+ ###### `defaultTabId`: `string`
124
124
 
125
125
  The id of the tab to be selected upon mounting of component. If this prop is not set, the first tab will be selected by default. The id provided will be internally prefixed with a unique instance ID to avoid collisions.
126
126
 
@@ -26,7 +26,7 @@ import { TabPanel } from './tabpanel';
26
26
 
27
27
  function Tabs( {
28
28
  selectOnMove = true,
29
- initialTabId,
29
+ defaultTabId,
30
30
  orientation = 'horizontal',
31
31
  onSelect,
32
32
  children,
@@ -36,7 +36,7 @@ function Tabs( {
36
36
  const store = Ariakit.useTabStore( {
37
37
  selectOnMove,
38
38
  orientation,
39
- defaultSelectedId: initialTabId && `${ instanceId }-${ initialTabId }`,
39
+ defaultSelectedId: defaultTabId && `${ instanceId }-${ defaultTabId }`,
40
40
  setSelectedId: ( selectedId ) => {
41
41
  const strippedDownId =
42
42
  typeof selectedId === 'string'
@@ -66,7 +66,7 @@ function Tabs( {
66
66
  return ! item.dimmed;
67
67
  } );
68
68
  const initialTab = items.find(
69
- ( item ) => item.id === `${ instanceId }-${ initialTabId }`
69
+ ( item ) => item.id === `${ instanceId }-${ defaultTabId }`
70
70
  );
71
71
 
72
72
  // Handle selecting the initial tab.
@@ -78,8 +78,8 @@ function Tabs( {
78
78
  // Wait for the denoted initial tab to be declared before making a
79
79
  // selection. This ensures that if a tab is declared lazily it can
80
80
  // still receive initial selection, as well as ensuring no tab is
81
- // selected if an invalid `initialTabId` is provided.
82
- if ( initialTabId && ! initialTab ) {
81
+ // selected if an invalid `defaultTabId` is provided.
82
+ if ( defaultTabId && ! initialTab ) {
83
83
  return;
84
84
  }
85
85
 
@@ -101,7 +101,7 @@ function Tabs( {
101
101
  }, [
102
102
  firstEnabledTab,
103
103
  initialTab,
104
- initialTabId,
104
+ defaultTabId,
105
105
  isControlled,
106
106
  items,
107
107
  selectedId,
@@ -122,7 +122,7 @@ function Tabs( {
122
122
  }
123
123
 
124
124
  // If the currently selected tab becomes disabled, fall back to the
125
- // `initialTabId` if possible. Otherwise select the first
125
+ // `defaultTabId` if possible. Otherwise select the first
126
126
  // enabled tab (if there is one).
127
127
  if ( initialTab && ! initialTab.dimmed ) {
128
128
  setSelectedId( initialTab.id );
@@ -73,7 +73,7 @@ const DisabledTabTemplate: StoryFn< typeof Tabs > = ( props ) => {
73
73
  return (
74
74
  <Tabs { ...props }>
75
75
  <Tabs.TabList>
76
- <Tabs.Tab tabId="tab1" disabled={ true }>
76
+ <Tabs.Tab tabId="tab1" disabled>
77
77
  Tab 1
78
78
  </Tabs.Tab>
79
79
  <Tabs.Tab tabId="tab2">Tab 2</Tabs.Tab>