@plone/volto 19.0.0-alpha.35 → 19.0.0-alpha.37

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 (218) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/README.md +1 -1
  3. package/locales/af/LC_MESSAGES/volto.po +29 -13
  4. package/locales/af.json +1 -1
  5. package/locales/ar/LC_MESSAGES/volto.po +29 -13
  6. package/locales/ar.json +1 -1
  7. package/locales/bg/LC_MESSAGES/volto.po +29 -13
  8. package/locales/bg.json +1 -1
  9. package/locales/bn/LC_MESSAGES/volto.po +29 -13
  10. package/locales/bn.json +1 -1
  11. package/locales/ca/LC_MESSAGES/volto.po +32 -16
  12. package/locales/ca.json +1 -1
  13. package/locales/cs/LC_MESSAGES/volto.po +30 -14
  14. package/locales/cs.json +1 -1
  15. package/locales/cy/LC_MESSAGES/volto.po +29 -13
  16. package/locales/cy.json +1 -1
  17. package/locales/da/LC_MESSAGES/volto.po +29 -13
  18. package/locales/da.json +1 -1
  19. package/locales/de/LC_MESSAGES/volto.po +32 -16
  20. package/locales/de.json +1 -1
  21. package/locales/el/LC_MESSAGES/volto.po +29 -13
  22. package/locales/el.json +1 -1
  23. package/locales/en/LC_MESSAGES/volto.po +25 -10
  24. package/locales/en.json +1 -1
  25. package/locales/en_AU/LC_MESSAGES/volto.po +29 -13
  26. package/locales/en_AU.json +1 -1
  27. package/locales/en_GB/LC_MESSAGES/volto.po +29 -13
  28. package/locales/en_GB.json +1 -1
  29. package/locales/eo/LC_MESSAGES/volto.po +29 -13
  30. package/locales/eo.json +1 -1
  31. package/locales/es/LC_MESSAGES/volto.po +67 -52
  32. package/locales/es.json +1 -1
  33. package/locales/et/LC_MESSAGES/volto.po +29 -13
  34. package/locales/et.json +1 -1
  35. package/locales/eu/LC_MESSAGES/volto.po +55 -40
  36. package/locales/eu.json +1 -1
  37. package/locales/fa/LC_MESSAGES/volto.po +29 -13
  38. package/locales/fa.json +1 -1
  39. package/locales/fi/LC_MESSAGES/volto.po +30 -14
  40. package/locales/fi.json +1 -1
  41. package/locales/fr/LC_MESSAGES/volto.po +208 -193
  42. package/locales/fr.json +1 -1
  43. package/locales/fu/LC_MESSAGES/volto.po +29 -13
  44. package/locales/fu.json +1 -1
  45. package/locales/gl/LC_MESSAGES/volto.po +58 -43
  46. package/locales/gl.json +1 -1
  47. package/locales/he/LC_MESSAGES/volto.po +29 -13
  48. package/locales/he.json +1 -1
  49. package/locales/hi/LC_MESSAGES/volto.po +34 -18
  50. package/locales/hi.json +1 -1
  51. package/locales/hr/LC_MESSAGES/volto.po +30 -14
  52. package/locales/hr.json +1 -1
  53. package/locales/hu/LC_MESSAGES/volto.po +29 -13
  54. package/locales/hu.json +1 -1
  55. package/locales/hy/LC_MESSAGES/volto.po +29 -13
  56. package/locales/hy.json +1 -1
  57. package/locales/id/LC_MESSAGES/volto.po +29 -13
  58. package/locales/id.json +1 -1
  59. package/locales/it/LC_MESSAGES/volto.po +34 -18
  60. package/locales/it.json +1 -1
  61. package/locales/ja/LC_MESSAGES/volto.po +29 -13
  62. package/locales/ja.json +1 -1
  63. package/locales/ka/LC_MESSAGES/volto.po +29 -13
  64. package/locales/ka.json +1 -1
  65. package/locales/kn/LC_MESSAGES/volto.po +29 -13
  66. package/locales/kn.json +1 -1
  67. package/locales/ko/LC_MESSAGES/volto.po +29 -13
  68. package/locales/ko.json +1 -1
  69. package/locales/lt/LC_MESSAGES/volto.po +30 -14
  70. package/locales/lt.json +1 -1
  71. package/locales/lv/LC_MESSAGES/volto.po +29 -13
  72. package/locales/lv.json +1 -1
  73. package/locales/mi/LC_MESSAGES/volto.po +29 -13
  74. package/locales/mi.json +1 -1
  75. package/locales/mk/LC_MESSAGES/volto.po +29 -13
  76. package/locales/mk.json +1 -1
  77. package/locales/my/LC_MESSAGES/volto.po +29 -13
  78. package/locales/my.json +1 -1
  79. package/locales/nb_NO/LC_MESSAGES/volto.po +29 -13
  80. package/locales/nb_NO.json +1 -1
  81. package/locales/nl/LC_MESSAGES/volto.po +69 -53
  82. package/locales/nl.json +1 -1
  83. package/locales/nn/LC_MESSAGES/volto.po +29 -13
  84. package/locales/nn.json +1 -1
  85. package/locales/pl/LC_MESSAGES/volto.po +30 -14
  86. package/locales/pl.json +1 -1
  87. package/locales/pt/LC_MESSAGES/volto.po +30 -14
  88. package/locales/pt.json +1 -1
  89. package/locales/pt_BR/LC_MESSAGES/volto.po +54 -39
  90. package/locales/pt_BR.json +1 -1
  91. package/locales/rm/LC_MESSAGES/volto.po +29 -13
  92. package/locales/rm.json +1 -1
  93. package/locales/ro/LC_MESSAGES/volto.po +30 -15
  94. package/locales/ro.json +1 -1
  95. package/locales/ru/LC_MESSAGES/volto.po +30 -14
  96. package/locales/ru.json +1 -1
  97. package/locales/sk/LC_MESSAGES/volto.po +30 -14
  98. package/locales/sk.json +1 -1
  99. package/locales/sl/LC_MESSAGES/volto.po +29 -13
  100. package/locales/sl.json +1 -1
  101. package/locales/sm/LC_MESSAGES/volto.po +29 -13
  102. package/locales/sm.json +1 -1
  103. package/locales/sq/LC_MESSAGES/volto.po +29 -13
  104. package/locales/sq.json +1 -1
  105. package/locales/sr/LC_MESSAGES/volto.po +30 -14
  106. package/locales/sr.json +1 -1
  107. package/locales/sr@cyrl/LC_MESSAGES/volto.po +29 -13
  108. package/locales/sr@cyrl.json +1 -1
  109. package/locales/sr@latn/LC_MESSAGES/volto.po +29 -13
  110. package/locales/sr@latn.json +1 -1
  111. package/locales/sv/LC_MESSAGES/volto.po +31 -15
  112. package/locales/sv.json +1 -1
  113. package/locales/ta/LC_MESSAGES/volto.po +30 -15
  114. package/locales/ta.json +1 -1
  115. package/locales/te/LC_MESSAGES/volto.po +29 -13
  116. package/locales/te.json +1 -1
  117. package/locales/th/LC_MESSAGES/volto.po +29 -13
  118. package/locales/th.json +1 -1
  119. package/locales/to/LC_MESSAGES/volto.po +29 -13
  120. package/locales/to.json +1 -1
  121. package/locales/tr/LC_MESSAGES/volto.po +29 -14
  122. package/locales/tr.json +1 -1
  123. package/locales/uk/LC_MESSAGES/volto.po +30 -14
  124. package/locales/uk.json +1 -1
  125. package/locales/vi/LC_MESSAGES/volto.po +29 -13
  126. package/locales/vi.json +1 -1
  127. package/locales/volto.pot +26 -11
  128. package/locales/zh_CN/LC_MESSAGES/volto.po +29 -14
  129. package/locales/zh_CN.json +1 -1
  130. package/locales/zh_Hant/LC_MESSAGES/volto.po +29 -13
  131. package/locales/zh_Hant.json +1 -1
  132. package/locales/zh_Hant_HK/LC_MESSAGES/volto.po +29 -13
  133. package/locales/zh_Hant_HK.json +1 -1
  134. package/package.json +10 -10
  135. package/src/components/manage/Add/Add.test.jsx +10 -3
  136. package/src/components/manage/Aliases/Aliases.test.jsx +5 -2
  137. package/src/components/manage/BlockChooser/BlockChooser.jsx +7 -10
  138. package/src/components/manage/Blocks/Block/Edit.jsx +19 -10
  139. package/src/components/manage/Blocks/Block/Order/Item.jsx +9 -4
  140. package/src/components/manage/Contents/Contents.test.jsx +7 -4
  141. package/src/components/manage/Contents/DropZoneContent.jsx +1 -0
  142. package/src/components/manage/Controlpanels/AddonsControlpanel.test.jsx +7 -4
  143. package/src/components/manage/Controlpanels/Aliases.test.jsx +7 -4
  144. package/src/components/manage/Controlpanels/BlockType.tsx +2 -3
  145. package/src/components/manage/Controlpanels/ContentType.test.jsx +12 -9
  146. package/src/components/manage/Controlpanels/ContentTypeLayout.test.jsx +12 -9
  147. package/src/components/manage/Controlpanels/ContentTypes.jsx +9 -2
  148. package/src/components/manage/Controlpanels/ContentTypes.test.jsx +7 -4
  149. package/src/components/manage/Controlpanels/Controlpanel.test.jsx +7 -4
  150. package/src/components/manage/Controlpanels/Controlpanels.test.jsx +13 -8
  151. package/src/components/manage/Controlpanels/Groups/GroupsControlpanel.test.jsx +7 -4
  152. package/src/components/manage/Controlpanels/ModerateComments.test.jsx +7 -4
  153. package/src/components/manage/Controlpanels/Rules/AddRule.test.jsx +7 -4
  154. package/src/components/manage/Controlpanels/Rules/ConfigureRule.test.jsx +9 -6
  155. package/src/components/manage/Controlpanels/Rules/EditRule.test.jsx +7 -4
  156. package/src/components/manage/Controlpanels/Rules/Rules.test.jsx +7 -4
  157. package/src/components/manage/Controlpanels/UndoControlpanel.test.jsx +7 -4
  158. package/src/components/manage/Controlpanels/Users/UserGroupMembershipControlPanel.test.jsx +7 -4
  159. package/src/components/manage/Controlpanels/Users/UsersControlpanel.jsx +58 -5
  160. package/src/components/manage/Controlpanels/Users/UsersControlpanel.ssr.test.jsx +624 -0
  161. package/src/components/manage/Controlpanels/Users/UsersControlpanel.test.jsx +21 -8
  162. package/src/components/manage/Delete/Delete.test.jsx +13 -8
  163. package/src/components/manage/Diff/Diff.test.jsx +7 -4
  164. package/src/components/manage/Edit/Edit.test.jsx +11 -6
  165. package/src/components/manage/Form/Form.jsx +6 -1
  166. package/src/components/manage/Form/ModalForm.jsx +164 -88
  167. package/src/components/manage/History/History.test.jsx +15 -8
  168. package/src/components/manage/LinksToItem/LinksToItem.test.jsx +7 -4
  169. package/src/components/manage/Multilingual/ManageTranslations.test.jsx +15 -12
  170. package/src/components/manage/Preferences/ChangePassword.test.jsx +7 -4
  171. package/src/components/manage/Preferences/PersonalPreferences.test.jsx +9 -6
  172. package/src/components/manage/Rules/Rules.test.jsx +5 -2
  173. package/src/components/manage/Sharing/Sharing.test.jsx +9 -6
  174. package/src/components/manage/Sidebar/ObjectBrowser.jsx +7 -0
  175. package/src/components/manage/Sidebar/ObjectBrowserBody.jsx +7 -3
  176. package/src/components/manage/Sidebar/ObjectBrowserBody.test.jsx +52 -0
  177. package/src/components/manage/Sidebar/Sidebar.jsx +2 -0
  178. package/src/components/manage/Sidebar/Sidebar.test.jsx +4 -1
  179. package/src/components/manage/Toolbar/Toolbar.jsx +89 -7
  180. package/src/components/manage/Toolbar/Toolbar.test.jsx +15 -10
  181. package/src/components/manage/Widgets/FormFieldWrapper.jsx +7 -5
  182. package/src/components/manage/Widgets/ObjectBrowserWidget.jsx +1 -0
  183. package/src/components/manage/Widgets/QuerystringWidget.test.jsx +3 -1
  184. package/src/components/manage/Widgets/TextWidget.jsx +4 -0
  185. package/src/components/manage/Widgets/TokenWidget.jsx +142 -186
  186. package/src/components/theme/App/App.test.jsx +13 -10
  187. package/src/components/theme/ContactForm/ContactForm.test.jsx +13 -8
  188. package/src/components/theme/MultilingualRedirector/MultilingualRedirector.test.jsx +6 -3
  189. package/src/components/theme/Search/Search.jsx +218 -328
  190. package/src/components/theme/Search/Search.test.jsx +14 -14
  191. package/src/components/theme/Sitemap/Sitemap.jsx +22 -30
  192. package/src/components/theme/Sitemap/Sitemap.test.jsx +18 -0
  193. package/src/components/theme/Unauthorized/Unauthorized.jsx +23 -30
  194. package/src/components/theme/Unauthorized/Unauthorized.test.jsx +6 -4
  195. package/src/components/theme/View/View.test.jsx +37 -24
  196. package/src/config/index.js +1 -0
  197. package/src/helpers/Api/Api.js +2 -2
  198. package/src/helpers/I18n/I18n.test.ts +44 -0
  199. package/src/helpers/I18n/I18n.ts +31 -0
  200. package/src/helpers/Robots/Robots.js +1 -1
  201. package/src/helpers/Robots/Robots.test.js +34 -0
  202. package/src/helpers/index.js +1 -0
  203. package/theme/themes/pastanaga/collections/form.overrides +21 -0
  204. package/theme/themes/pastanaga/elements/button.overrides +30 -3
  205. package/types/components/manage/Controlpanels/Relations/RelationsMatrix.d.ts +1 -1
  206. package/types/components/manage/Controlpanels/Users/UsersControlpanel.d.ts +2 -6
  207. package/types/components/manage/Controlpanels/Users/UsersControlpanel.ssr.test.d.ts +1 -0
  208. package/types/components/manage/Controlpanels/index.d.ts +1 -1
  209. package/types/components/manage/Multilingual/ManageTranslations.d.ts +1 -1
  210. package/types/components/manage/Sidebar/ObjectBrowser.d.ts +1 -1
  211. package/types/components/manage/Sidebar/ObjectBrowserBody.test.d.ts +1 -0
  212. package/types/components/manage/Widgets/ImageWidget.d.ts +1 -1
  213. package/types/components/manage/Widgets/InternalUrlWidget.d.ts +1 -1
  214. package/types/components/manage/Widgets/UrlWidget.d.ts +1 -1
  215. package/types/components/manage/Widgets/index.d.ts +2 -2
  216. package/types/components/theme/Search/Search.d.ts +1 -1
  217. package/types/helpers/I18n/I18n.d.ts +20 -0
  218. package/types/helpers/index.d.ts +1 -0
@@ -84,6 +84,7 @@ class ObjectBrowserBody extends Component {
84
84
  onSelectItem: PropTypes.func,
85
85
  dataName: PropTypes.string,
86
86
  maximumSelectionSize: PropTypes.number,
87
+ initialPath: PropTypes.string,
87
88
  contextURL: PropTypes.string,
88
89
  searchableTypes: PropTypes.arrayOf(PropTypes.string),
89
90
  onlyFolderishSelectable: PropTypes.bool,
@@ -113,18 +114,21 @@ class ObjectBrowserBody extends Component {
113
114
  */
114
115
  constructor(props) {
115
116
  super(props);
117
+ const defaultMultiplePath = props.initialPath || '/';
116
118
  this.state = {
117
119
  currentFolder:
118
- this.props.mode === 'multiple' ? '/' : this.props.contextURL || '/',
120
+ this.props.mode === 'multiple'
121
+ ? defaultMultiplePath
122
+ : this.props.contextURL || '/',
119
123
  currentImageFolder:
120
124
  this.props.mode === 'multiple'
121
- ? '/'
125
+ ? defaultMultiplePath
122
126
  : this.props.mode === 'image' && this.props.data?.url
123
127
  ? getParentURL(this.props.data.url)
124
128
  : '/',
125
129
  currentLinkFolder:
126
130
  this.props.mode === 'multiple'
127
- ? '/'
131
+ ? defaultMultiplePath
128
132
  : this.props.mode === 'link' && this.props.data?.href
129
133
  ? getParentURL(this.props.data.href)
130
134
  : '/',
@@ -0,0 +1,52 @@
1
+ import React from 'react';
2
+ import { render } from '@testing-library/react';
3
+ import configureStore from 'redux-mock-store';
4
+ import { Provider } from 'react-intl-redux';
5
+ import ObjectBrowserBody from './ObjectBrowserBody';
6
+
7
+ const mockStore = configureStore();
8
+
9
+ const baseState = {
10
+ search: { subrequests: {} },
11
+ intl: { locale: 'en', messages: {} },
12
+ };
13
+
14
+ const baseProps = {
15
+ block: 'test-block',
16
+ data: {},
17
+ closeObjectBrowser: () => {},
18
+ onChangeBlock: () => {},
19
+ };
20
+
21
+ const getInitialSearchPath = (actions) => {
22
+ const action = actions.find((a) => a.type === 'SEARCH_CONTENT');
23
+ return action?.request?.path?.split('/@search')[0];
24
+ };
25
+
26
+ describe('ObjectBrowserBody', () => {
27
+ it('uses initialPath as the default folder when mode=multiple', () => {
28
+ const store = mockStore(baseState);
29
+ render(
30
+ <Provider store={store}>
31
+ <ObjectBrowserBody
32
+ {...baseProps}
33
+ mode="multiple"
34
+ initialPath="/company/team"
35
+ />
36
+ </Provider>,
37
+ );
38
+
39
+ expect(getInitialSearchPath(store.getActions())).toBe('/company/team');
40
+ });
41
+
42
+ it('defaults to root when mode=multiple and initialPath is not provided', () => {
43
+ const store = mockStore(baseState);
44
+ render(
45
+ <Provider store={store}>
46
+ <ObjectBrowserBody {...baseProps} mode="multiple" />
47
+ </Provider>,
48
+ );
49
+
50
+ expect(getInitialSearchPath(store.getActions())).toBe('/');
51
+ });
52
+ });
@@ -155,6 +155,7 @@ const Sidebar = (props) => {
155
155
  key: 'documentTab',
156
156
  as: 'button',
157
157
  className: 'ui button',
158
+ type: 'button',
158
159
  content: type || intl.formatMessage(messages.document),
159
160
  },
160
161
  pane: (
@@ -170,6 +171,7 @@ const Sidebar = (props) => {
170
171
  key: 'blockTab',
171
172
  as: 'button',
172
173
  className: 'ui button',
174
+ type: 'button',
173
175
  content: intl.formatMessage(messages.block),
174
176
  },
175
177
  pane: (
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  import renderer from 'react-test-renderer';
3
3
  import configureStore from 'redux-mock-store';
4
4
  import { Provider } from 'react-intl-redux';
5
+ import { CookiesProvider } from 'react-cookie';
5
6
 
6
7
  import Sidebar from './Sidebar';
7
8
 
@@ -22,7 +23,9 @@ test('renders a sidebar component', () => {
22
23
  });
23
24
  const component = renderer.create(
24
25
  <Provider store={store}>
25
- <Sidebar />
26
+ <CookiesProvider>
27
+ <Sidebar />
28
+ </CookiesProvider>
26
29
  </Provider>,
27
30
  );
28
31
  const json = component.toJSON();
@@ -108,6 +108,18 @@ const messages = defineMessages({
108
108
  id: 'Unlock',
109
109
  defaultMessage: 'Unlock',
110
110
  },
111
+ menuOpened: {
112
+ id: 'Menu opened',
113
+ defaultMessage: 'Menu opened',
114
+ },
115
+ menuClosed: {
116
+ id: 'Menu closed',
117
+ defaultMessage: 'Menu closed',
118
+ },
119
+ focusOn: {
120
+ id: 'Focus on',
121
+ defaultMessage: 'Focus on',
122
+ },
111
123
  });
112
124
 
113
125
  let toolbarComponents = {
@@ -185,6 +197,7 @@ class Toolbar extends Component {
185
197
  toolbarRef = React.createRef();
186
198
  toolbarWindow = React.createRef();
187
199
  buttonRef = React.createRef();
200
+ announceRef = React.createRef();
188
201
 
189
202
  constructor(props) {
190
203
  super(props);
@@ -305,10 +318,40 @@ class Toolbar extends Component {
305
318
  }
306
319
  // PersonalTools always shows at bottom
307
320
  if (selector === 'personalTools') {
308
- this.setState((state) => ({
309
- showMenu: !state.showMenu,
310
- menuStyle: { bottom: 0 },
311
- }));
321
+ this.setState(
322
+ (state) => ({
323
+ showMenu: !state.showMenu,
324
+ menuStyle: { bottom: 0 },
325
+ }),
326
+ () => {
327
+ // Scoped only to personalTools — does not affect other toolbar flows
328
+ const candidates =
329
+ this.toolbarWindow.current?.querySelectorAll(
330
+ 'a, button, input, [tabindex]:not([tabindex="-1"])',
331
+ ) ?? [];
332
+ const firstVisible = Array.from(candidates).find((el) => {
333
+ const style = window.getComputedStyle(el);
334
+ return style.display !== 'none' && style.visibility !== 'hidden';
335
+ });
336
+ firstVisible?.focus();
337
+
338
+ // Announce to screen readers: menu opened + which element received focus
339
+ if (this.announceRef.current) {
340
+ const focusedLabel =
341
+ firstVisible?.getAttribute('aria-label') ||
342
+ firstVisible?.textContent?.trim() ||
343
+ '';
344
+ this.announceRef.current.textContent = '';
345
+ setTimeout(() => {
346
+ if (this.announceRef.current) {
347
+ this.announceRef.current.textContent = focusedLabel
348
+ ? `${this.props.intl.formatMessage(messages.menuOpened)}, ${this.props.intl.formatMessage(messages.focusOn)} ${focusedLabel}`
349
+ : this.props.intl.formatMessage(messages.menuOpened);
350
+ }
351
+ }, 100);
352
+ }
353
+ },
354
+ );
312
355
  } else if (selector === 'more') {
313
356
  this.setState((state) => ({
314
357
  showMenu: !state.showMenu,
@@ -337,10 +380,22 @@ class Toolbar extends Component {
337
380
 
338
381
  handleClickOutside = (e) => {
339
382
  const target = e.target;
340
- if (this.pusher && doesNodeContainClick(this.pusher, e)) return;
341
383
 
342
- // if the click is on the same button, do not close the menu as it
343
- // may be handled by the toggleMenu action
384
+ if (this.pusher && doesNodeContainClick(this.pusher, e)) {
385
+ return;
386
+ }
387
+
388
+ if (
389
+ this.toolbarRef.current &&
390
+ doesNodeContainClick(this.toolbarRef.current, e)
391
+ ) {
392
+ return;
393
+ }
394
+
395
+ if (target.closest('.ui.modal') || target.closest('.ui.dimmer')) {
396
+ return;
397
+ }
398
+
344
399
  const button =
345
400
  doesNodeContainClick(this.toolbarRef.current, e) &&
346
401
  this.findAncestor(target, 'button');
@@ -376,12 +431,39 @@ class Toolbar extends Component {
376
431
  <BodyClass
377
432
  className={expanded ? 'has-toolbar' : 'has-toolbar-collapsed'}
378
433
  />
434
+ <span
435
+ aria-live="assertive"
436
+ aria-atomic="true"
437
+ role="status"
438
+ className="visually-hidden"
439
+ ref={this.announceRef}
440
+ />
379
441
  <div
380
442
  style={this.state.menuStyle}
381
443
  className={
382
444
  this.state.showMenu ? 'toolbar-content show' : 'toolbar-content'
383
445
  }
384
446
  ref={this.toolbarWindow}
447
+ onBlur={(e) => {
448
+ if (!this.toolbarWindow.current?.contains(e.relatedTarget)) {
449
+ this.toolbarRef.current
450
+ ?.querySelector('button.toolbar-handler-button')
451
+ ?.focus();
452
+
453
+ this.closeMenu();
454
+
455
+ if (this.announceRef.current) {
456
+ this.announceRef.current.textContent = '';
457
+ // Timeout to allow the screen reader to pick up the change in content after the menu is closed
458
+ setTimeout(() => {
459
+ if (this.announceRef.current) {
460
+ this.announceRef.current.textContent =
461
+ this.props.intl.formatMessage(messages.menuClosed);
462
+ }
463
+ }, 100);
464
+ }
465
+ }
466
+ }}
385
467
  >
386
468
  {this.state.showMenu && (
387
469
  // This sets the scroll locker in the body tag in mobile
@@ -5,6 +5,7 @@ import { Provider } from 'react-intl-redux';
5
5
  import { MemoryRouter } from 'react-router-dom';
6
6
  import jwt from 'jsonwebtoken';
7
7
  import thunk from 'redux-thunk';
8
+ import { CookiesProvider } from 'react-cookie';
8
9
  import { PluggablesProvider } from '@plone/volto/components/manage/Pluggable';
9
10
 
10
11
  import Toolbar from './Toolbar';
@@ -130,11 +131,13 @@ describe('Toolbar', () => {
130
131
  });
131
132
  const component = renderer.create(
132
133
  <Provider store={store}>
133
- <PluggablesProvider>
134
- <MemoryRouter>
135
- <Toolbar pathname="/test" inner={<span />} />
136
- </MemoryRouter>
137
- </PluggablesProvider>
134
+ <CookiesProvider>
135
+ <PluggablesProvider>
136
+ <MemoryRouter>
137
+ <Toolbar pathname="/test" inner={<span />} />
138
+ </MemoryRouter>
139
+ </PluggablesProvider>
140
+ </CookiesProvider>
138
141
  </Provider>,
139
142
  );
140
143
  const json = component.toJSON();
@@ -264,11 +267,13 @@ describe('Toolbar', () => {
264
267
  });
265
268
  const component = renderer.create(
266
269
  <Provider store={store}>
267
- <PluggablesProvider>
268
- <MemoryRouter>
269
- <Toolbar pathname="/test" inner={<span />} />
270
- </MemoryRouter>
271
- </PluggablesProvider>
270
+ <CookiesProvider>
271
+ <PluggablesProvider>
272
+ <MemoryRouter>
273
+ <Toolbar pathname="/test" inner={<span />} />
274
+ </MemoryRouter>
275
+ </PluggablesProvider>
276
+ </CookiesProvider>
272
277
  </Provider>,
273
278
  );
274
279
  const json = component.toJSON();
@@ -61,11 +61,13 @@ const FormFieldWrapper = ({
61
61
  <>
62
62
  {children}
63
63
 
64
- {map(error, (message) => (
65
- <Label key={message} basic color="red" className="form-error-label">
66
- {message}
67
- </Label>
68
- ))}
64
+ <div aria-live="polite" aria-atomic="true">
65
+ {map(error, (message) => (
66
+ <Label key={message} basic color="red" className="form-error-label">
67
+ {message}
68
+ </Label>
69
+ ))}
70
+ </div>
69
71
  </>
70
72
  );
71
73
 
@@ -307,6 +307,7 @@ export class ObjectBrowserWidgetComponent extends Component {
307
307
  this.props.openObjectBrowser({
308
308
  mode: this.props.mode,
309
309
  currentPath: this.props.initialPath || this.props.location.pathname,
310
+ initialPath: this.props.initialPath,
310
311
  propDataName: 'value',
311
312
  onSelectItem: (url, item) => {
312
313
  this.onChange(item);
@@ -51,6 +51,8 @@ test('can take a schemaEnhancer', async () => {
51
51
  />
52
52
  </Provider>,
53
53
  );
54
- await waitFor(() => {});
54
+ await waitFor(() => {
55
+ expect(component.toJSON()?.children).toHaveLength(3);
56
+ });
55
57
  expect(component.toJSON()).toMatchSnapshot();
56
58
  });
@@ -19,6 +19,8 @@ const TextWidget = (props) => {
19
19
  placeholder,
20
20
  isDisabled,
21
21
  focus,
22
+ required,
23
+ error,
22
24
  } = props;
23
25
 
24
26
  const ref = useRef();
@@ -49,6 +51,8 @@ const TextWidget = (props) => {
49
51
  onClick={() => onClick()}
50
52
  minLength={minLength || null}
51
53
  maxLength={maxLength || null}
54
+ aria-required={required ? 'true' : undefined}
55
+ aria-invalid={error?.length > 0 ? 'true' : undefined}
52
56
  />
53
57
  {icon && iconAction && (
54
58
  <button className={`field-${id}-action-button`} onClick={iconAction}>