design-comuni-plone-theme 11.1.4 → 11.2.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 (31) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/RELEASE.md +15 -1
  3. package/locales/de/LC_MESSAGES/volto.po +5 -0
  4. package/locales/en/LC_MESSAGES/volto.po +5 -0
  5. package/locales/es/LC_MESSAGES/volto.po +5 -0
  6. package/locales/fr/LC_MESSAGES/volto.po +5 -0
  7. package/locales/it/LC_MESSAGES/volto.po +5 -0
  8. package/locales/volto.pot +6 -1
  9. package/package.json +2 -2
  10. package/publiccode.yml +2 -2
  11. package/src/components/Collapse.jsx +16 -11
  12. package/src/components/ItaliaTheme/Blocks/TextCard/CardWithImage/Block.jsx +32 -44
  13. package/src/components/ItaliaTheme/Blocks/TextCard/SimpleCard/Block.jsx +28 -34
  14. package/src/components/ItaliaTheme/Blocks/VideoGallery/Block/ViewBlock.jsx +33 -37
  15. package/src/components/ItaliaTheme/MegaMenu/MegaMenu.jsx +16 -6
  16. package/src/components/ItaliaTheme/MenuSecondary/MenuSecondary.jsx +3 -2
  17. package/src/components/ItaliaTheme/Search/ResultItem.jsx +30 -15
  18. package/src/components/ItaliaTheme/Search/Search.jsx +49 -19
  19. package/src/config/italiaConfig.js +5 -6
  20. package/src/customizations/volto/components/manage/Blocks/HTML/Edit.jsx +42 -16
  21. package/src/customizations/volto/components/manage/Blocks/Listing/ListingBody.jsx +6 -2
  22. package/src/customizations/volto/components/theme/Navigation/Navigation.jsx +65 -36
  23. package/src/theme/ItaliaTheme/Blocks/_alert.scss +6 -4
  24. package/src/theme/ItaliaTheme/Blocks/_countdown.scss +1 -1
  25. package/src/theme/ItaliaTheme/Blocks/_gridGalleryTemplate.scss +7 -2
  26. package/src/theme/ItaliaTheme/Blocks/_numbers.scss +1 -1
  27. package/src/theme/ItaliaTheme/Components/_card.scss +1 -1
  28. package/src/theme/ItaliaTheme/Components/_search.scss +1 -0
  29. package/src/theme/_site-variables.scss +7 -4
  30. package/src/theme/bootstrap-override/_bootstrap-italia-site.scss +1 -0
  31. package/src/theme/bootstrap-override/bootstrap-italia/_focus.scss +3 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,42 @@
1
1
 
2
2
 
3
+ ## [11.2.0](https://github.com/redturtle/design-comuni-plone-theme/compare/v11.1.4...v11.2.0) (2024-01-11)
4
+
5
+
6
+ ### Features
7
+
8
+ * customizable Alert block colors and text color ([#470](https://github.com/redturtle/design-comuni-plone-theme/issues/470)) ([4aa6f76](https://github.com/redturtle/design-comuni-plone-theme/commit/4aa6f7607be0ac8a76f1d519eee82483d9320a05))
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * a11y for navigation in megamenu and mobile menu ([#456](https://github.com/redturtle/design-comuni-plone-theme/issues/456)) ([6e4c1ef](https://github.com/redturtle/design-comuni-plone-theme/commit/6e4c1efbf96c372bf78a67ecf86ade64b7b2bb6a))
14
+ * **a11y:** a11y - colore sfondo opzione con focus in tendina "ordina per" ([#457](https://github.com/redturtle/design-comuni-plone-theme/issues/457)) ([d81b3a9](https://github.com/redturtle/design-comuni-plone-theme/commit/d81b3a9f34822242e10942a4acccb5978996a06b))
15
+ * added aria-live and aria-labels for filters in Search page ([#462](https://github.com/redturtle/design-comuni-plone-theme/issues/462)) ([13cf7da](https://github.com/redturtle/design-comuni-plone-theme/commit/13cf7dac5f8aaf5deaee5720ccd2e9a54c6326db))
16
+ * added focus style for skiplinks for a11y ([#458](https://github.com/redturtle/design-comuni-plone-theme/issues/458)) ([94e5cca](https://github.com/redturtle/design-comuni-plone-theme/commit/94e5cca0b671aa5bfc1febf4f51b306f71de43be))
17
+ * aria tags to avoid double feedback on SR ([#468](https://github.com/redturtle/design-comuni-plone-theme/issues/468)) ([867df42](https://github.com/redturtle/design-comuni-plone-theme/commit/867df42a8ae96f0546afb43e12490553648128f7))
18
+ * background color contrast for blocks number, countdown and gallery grid ([#433](https://github.com/redturtle/design-comuni-plone-theme/issues/433)) ([d005222](https://github.com/redturtle/design-comuni-plone-theme/commit/d005222a994d0117f41fcf7d9e93ead1c8e71f1f))
19
+ * broken videos in Video Gallery block ([#461](https://github.com/redturtle/design-comuni-plone-theme/issues/461)) ([e977673](https://github.com/redturtle/design-comuni-plone-theme/commit/e9776738df702dd915e1dab45f3cdbb227fa4a6a))
20
+ * default in white header scss variable ([3194ab8](https://github.com/redturtle/design-comuni-plone-theme/commit/3194ab8139edfadff747494c9609e7b2fa79b057))
21
+ * font and spaces of Card blocks ([#476](https://github.com/redturtle/design-comuni-plone-theme/issues/476)) ([3b45cc8](https://github.com/redturtle/design-comuni-plone-theme/commit/3b45cc890f769ab839f9abd30968ff9ca4ef82e7))
22
+ * listing bg color ([#475](https://github.com/redturtle/design-comuni-plone-theme/issues/475)) ([544be04](https://github.com/redturtle/design-comuni-plone-theme/commit/544be046ddca345f1b0c9073a4a57c876281031b))
23
+ * lowered flex basis of card-body in LocationItem cards ([#460](https://github.com/redturtle/design-comuni-plone-theme/issues/460)) ([697f54c](https://github.com/redturtle/design-comuni-plone-theme/commit/697f54c9f81947898caa27f4aa76dee0b16d0616))
24
+ * toolbar buttons for html block ([#477](https://github.com/redturtle/design-comuni-plone-theme/issues/477)) ([ed41904](https://github.com/redturtle/design-comuni-plone-theme/commit/ed419046c9184387e4daac4de86f8b0cd09924b4))
25
+
26
+
27
+ ### Maintenance
28
+
29
+ * **deps:** bump http-cache-semantics from 4.1.0 to 4.1.1 ([#464](https://github.com/redturtle/design-comuni-plone-theme/issues/464)) ([88d5d2c](https://github.com/redturtle/design-comuni-plone-theme/commit/88d5d2c8423ea3052ad2a4ea54623e072a86e0e8))
30
+ * **deps:** bump json5 from 1.0.1 to 1.0.2 ([#467](https://github.com/redturtle/design-comuni-plone-theme/issues/467)) ([1dbc958](https://github.com/redturtle/design-comuni-plone-theme/commit/1dbc9582e49866edc74ff65ce4b96c8218e713d9))
31
+ * **deps:** bump semver from 5.7.1 to 5.7.2 ([#446](https://github.com/redturtle/design-comuni-plone-theme/issues/446)) ([49a6e2f](https://github.com/redturtle/design-comuni-plone-theme/commit/49a6e2f217b779ba4f57ca030335af12b91b7337))
32
+ * **deps:** bump simple-git from 3.14.1 to 3.22.0 ([#465](https://github.com/redturtle/design-comuni-plone-theme/issues/465)) ([6d956dd](https://github.com/redturtle/design-comuni-plone-theme/commit/6d956dda6575f6acd5321b223b67c593db27d1e1))
33
+ * replace react-highlight-words with simple custom code ([#463](https://github.com/redturtle/design-comuni-plone-theme/issues/463)) ([809e92e](https://github.com/redturtle/design-comuni-plone-theme/commit/809e92e647a23dfcfb2d3c15616e17fc32388984))
34
+
35
+
36
+ ### Documentation
37
+
38
+ * updated publiccode and release log ([285b7ce](https://github.com/redturtle/design-comuni-plone-theme/commit/285b7ced0dc20b0e6e35d9849ded449913279a83))
39
+
3
40
  ## [11.1.4](https://github.com/RedTurtle/design-comuni-plone-theme/compare/v11.1.3...v11.1.4) (2024-01-05)
4
41
 
5
42
 
package/RELEASE.md CHANGED
@@ -41,7 +41,21 @@
41
41
  - ...
42
42
  -->
43
43
 
44
- ## Versione 11.1.4 (dd/mm/yyyy)
44
+ ## Versione 11.2.0 (11/01/2023)
45
+
46
+ ### Migliorie
47
+
48
+ - Migliorata l'accessibilità nella pagina di Ricerca.
49
+ - Diminuita la larghezza del testo nelle card che indicano i luoghi.
50
+
51
+ ### Fix
52
+
53
+ - Risolto un problema nel blocco Video Gallery, per cui alcuni video di youtube non erano riproducibili.
54
+ - Risolto problema nel funzionamento della toolbar per il blocco HTML.
55
+ - Sistemate spaziature e font su mobile del blocco Card con Immagine e Card Semplice, migliorato il layout di quest'ultimo.
56
+ - È stato migliorato il contrasto minimo necessario tra sfondo e testo nei blocchi numeri, countdown e galleria a griglia.
57
+
58
+ ## Versione 11.1.4 (05/01/2024)
45
59
 
46
60
  ### Fix
47
61
 
@@ -742,6 +742,11 @@ msgstr ""
742
742
  msgid "actions"
743
743
  msgstr ""
744
744
 
745
+ #: components/ItaliaTheme/Search/Search
746
+ # defaultMessage: {filterNumber} filtri attivati
747
+ msgid "active_filters"
748
+ msgstr ""
749
+
745
750
  #: components/ItaliaTheme/Header/HeaderSearch/SearchModal
746
751
  # defaultMessage: Vai alla ricerca per sezioni avanzata
747
752
  msgid "advandedSectionsFilters"
@@ -727,6 +727,11 @@ msgstr ""
727
727
  msgid "actions"
728
728
  msgstr "View actions"
729
729
 
730
+ #: components/ItaliaTheme/Search/Search
731
+ # defaultMessage: {filterNumber} filtri attivati
732
+ msgid "active_filters"
733
+ msgstr ""
734
+
730
735
  #: components/ItaliaTheme/Header/HeaderSearch/SearchModal
731
736
  # defaultMessage: Vai alla ricerca per sezioni avanzata
732
737
  msgid "advandedSectionsFilters"
@@ -736,6 +736,11 @@ msgstr ""
736
736
  msgid "actions"
737
737
  msgstr "Ver acciones"
738
738
 
739
+ #: components/ItaliaTheme/Search/Search
740
+ # defaultMessage: {filterNumber} filtri attivati
741
+ msgid "active_filters"
742
+ msgstr ""
743
+
739
744
  #: components/ItaliaTheme/Header/HeaderSearch/SearchModal
740
745
  # defaultMessage: Vai alla ricerca per sezioni avanzata
741
746
  msgid "advandedSectionsFilters"
@@ -744,6 +744,11 @@ msgstr ""
744
744
  msgid "actions"
745
745
  msgstr "Voir les actions"
746
746
 
747
+ #: components/ItaliaTheme/Search/Search
748
+ # defaultMessage: {filterNumber} filtri attivati
749
+ msgid "active_filters"
750
+ msgstr ""
751
+
747
752
  #: components/ItaliaTheme/Header/HeaderSearch/SearchModal
748
753
  # defaultMessage: Vai alla ricerca per sezioni avanzata
749
754
  msgid "advandedSectionsFilters"
@@ -727,6 +727,11 @@ msgstr "Account"
727
727
  msgid "actions"
728
728
  msgstr "Vedi azioni"
729
729
 
730
+ #: components/ItaliaTheme/Search/Search
731
+ # defaultMessage: {filterNumber} filtri attivati
732
+ msgid "active_filters"
733
+ msgstr ""
734
+
730
735
  #: components/ItaliaTheme/Header/HeaderSearch/SearchModal
731
736
  # defaultMessage: Vai alla ricerca per sezioni avanzata
732
737
  msgid "advandedSectionsFilters"
package/locales/volto.pot CHANGED
@@ -1,7 +1,7 @@
1
1
  msgid ""
2
2
  msgstr ""
3
3
  "Project-Id-Version: Plone\n"
4
- "POT-Creation-Date: 2023-12-20T09:24:02.911Z\n"
4
+ "POT-Creation-Date: 2024-01-11T11:04:31.849Z\n"
5
5
  "Last-Translator: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
6
6
  "Language-Team: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
7
7
  "MIME-Version: 1.0\n"
@@ -729,6 +729,11 @@ msgstr ""
729
729
  msgid "actions"
730
730
  msgstr ""
731
731
 
732
+ #: components/ItaliaTheme/Search/Search
733
+ # defaultMessage: {filterNumber} filtri attivati
734
+ msgid "active_filters"
735
+ msgstr ""
736
+
732
737
  #: components/ItaliaTheme/Header/HeaderSearch/SearchModal
733
738
  # defaultMessage: Vai alla ricerca per sezioni avanzata
734
739
  msgid "advandedSectionsFilters"
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "design-comuni-plone-theme",
3
3
  "description": "Volto Theme for Italia design guidelines",
4
4
  "license": "GPL-v3",
5
- "version": "11.1.4",
5
+ "version": "11.2.0",
6
6
  "main": "src/index.js",
7
7
  "keywords": [
8
8
  "volto-addon",
@@ -131,8 +131,8 @@
131
131
  "htmldiff-js": "1.0.5",
132
132
  "marked": "9.0.0",
133
133
  "react-dropzone": "11.0.1",
134
+ "react-focus-lock": "2.9.4",
134
135
  "react-google-recaptcha-v3": "1.7.0",
135
- "react-highlight-words": "0.18.0",
136
136
  "react-select": "^4.3.1",
137
137
  "react-slick": "^0.29.0",
138
138
  "slick-carousel": "1.8.1",
package/publiccode.yml CHANGED
@@ -227,9 +227,9 @@ maintenance:
227
227
  name: io-Comune - Il sito AgID per Comuni ed Enti Pubblici
228
228
  platforms:
229
229
  - web
230
- releaseDate: '2024-01-05'
230
+ releaseDate: '2024-01-11'
231
231
  softwareType: standalone/web
232
- softwareVersion: 11.1.4
232
+ softwareVersion: 11.2.0
233
233
  url: 'https://github.com/italia/design-comuni-plone-theme'
234
234
  usedBy:
235
235
  - ASP Comuni Modenesi Area Nord
@@ -39,10 +39,10 @@ const Collapse = ({
39
39
  children,
40
40
  isOpen,
41
41
  onOverlayClick,
42
+ showCloseButton = true, // deprecato da v12.0.0
42
43
  ...attributes
43
44
  }) => {
44
45
  const intl = useIntl();
45
-
46
46
  if (navbar && header) {
47
47
  const classes = classNames(className, 'navbar-collapse', {
48
48
  expanded: isOpen,
@@ -60,16 +60,21 @@ const Collapse = ({
60
60
  style={{ display: isOpen ? 'block' : 'none' }}
61
61
  onClick={onOverlayClick}
62
62
  ></div>
63
- <div className="close-div">
64
- <button
65
- className="btn close-menu"
66
- type="button"
67
- title={intl.formatMessage(messages.CloseMenu)}
68
- onClick={onOverlayClick}
69
- >
70
- <Icon color="white" icon="it-close-big" padding={false} />
71
- </button>
72
- </div>
63
+ {/* Deprecato - non viene più utilizzato da v12.0.0 per ragioni di accessibilità
64
+ Close button ora presente in Navigation.jsx
65
+ */}
66
+ {showCloseButton && (
67
+ <div className="close-div">
68
+ <button
69
+ className="btn close-menu"
70
+ type="button"
71
+ title={intl.formatMessage(messages.CloseMenu)}
72
+ onClick={onOverlayClick}
73
+ >
74
+ <Icon color="white" icon="it-close-big" padding={false} />
75
+ </button>
76
+ </div>
77
+ )}
73
78
  {children}
74
79
  </CollapseBase>
75
80
  );
@@ -1,14 +1,7 @@
1
1
  /* eslint-disable jsx-a11y/no-static-element-interactions */
2
2
  /* eslint-disable jsx-a11y/click-events-have-key-events */
3
- import React, { useState, useRef, useEffect } from 'react';
4
- import {
5
- Card,
6
- CardBody,
7
- CardText,
8
- Container,
9
- Row,
10
- Col,
11
- } from 'design-react-kit';
3
+ import React, { useState, useEffect } from 'react';
4
+ import { Card, CardBody, Container, Row, Col } from 'design-react-kit';
12
5
  import { defineMessages, useIntl } from 'react-intl';
13
6
  import PropTypes from 'prop-types';
14
7
  import redraft from 'redraft';
@@ -113,7 +106,7 @@ const Block = ({
113
106
  )}
114
107
  </h2>
115
108
  <Card color="white" className="card-bg rounded" noWrapper={false}>
116
- <CardBody className="pb-0">
109
+ <CardBody>
117
110
  {inEditMode ? (
118
111
  <Container>
119
112
  <Row
@@ -123,19 +116,20 @@ const Block = ({
123
116
  })}
124
117
  >
125
118
  {hasImage && (
126
- <Col className="py-4 px-0" key={'col-0'}>
119
+ <Col className="my-1 px-0" key={'col-0'}>
127
120
  {renderImage(data?.image, hasImage, data?.sizeNatural)}
128
121
  </Col>
129
122
  )}
130
123
  <div
131
124
  key={'col-1'}
132
- className={cx('p-4 mb-2', {
125
+ className={cx('px-4 mb-2', {
133
126
  'col-12': !hasImage,
134
127
  'col-8':
135
128
  (hasImage && data?.sizeImage === 's') ||
136
129
  (hasImage && !data?.sizeImage),
137
130
  'col-6': hasImage && data?.sizeImage === 'm',
138
131
  'col-4': hasImage && data?.sizeImage === 'l',
132
+ 'ps-0': data?.rightImage,
139
133
  })}
140
134
  >
141
135
  <div
@@ -146,29 +140,24 @@ const Block = ({
146
140
  setSelectedField('content');
147
141
  }}
148
142
  >
149
- <CardText
150
- className="simple-text-card text"
151
- style={{ padding: 0 }}
152
- >
153
- <TextEditorWidget
154
- data={data}
155
- fieldName="image_card_content"
156
- selected={selectedField === 'content'}
157
- block={block}
158
- onChangeBlock={(data) => onChange(data)}
159
- placeholder={intl.formatMessage(
160
- messages.image_card_content,
161
- )}
162
- showToolbar={true}
163
- onSelectBlock={onSelectBlock}
164
- onAddBlock={onAddBlock}
165
- index={index}
166
- onFocusNextBlock={onFocusNextBlock}
167
- onFocusPreviousBlock={() => {
168
- setSelectedField('title');
169
- }}
170
- />
171
- </CardText>
143
+ <TextEditorWidget
144
+ data={data}
145
+ fieldName="image_card_content"
146
+ selected={selectedField === 'content'}
147
+ block={block}
148
+ onChangeBlock={(data) => onChange(data)}
149
+ placeholder={intl.formatMessage(
150
+ messages.image_card_content,
151
+ )}
152
+ showToolbar={true}
153
+ onSelectBlock={onSelectBlock}
154
+ onAddBlock={onAddBlock}
155
+ index={index}
156
+ onFocusNextBlock={onFocusNextBlock}
157
+ onFocusPreviousBlock={() => {
158
+ setSelectedField('title');
159
+ }}
160
+ />
172
161
  </div>
173
162
  </div>
174
163
  </Row>
@@ -180,28 +169,27 @@ const Block = ({
180
169
  'revert-row': data?.rightImage,
181
170
  })}
182
171
  >
183
- <Col className="py-4 px-0" key={'col-0'} data-testid={'col-0'}>
172
+ <Col className="my-1 p-0" key={'col-0'} data-testid={'col-0'}>
184
173
  {renderImage(data?.image, hasImage, data?.sizeNatural)}
185
174
  </Col>
186
175
  <div
187
176
  key={'col-1'}
188
177
  data-testid={'col-1'}
189
- className={cx('p-4', {
178
+ className={cx('px-4', {
190
179
  'col-12': !hasImage,
191
180
  'col-8':
192
181
  (hasImage && data?.sizeImage === 's') ||
193
182
  (hasImage && !data?.sizeImage),
194
183
  'col-6': hasImage && data?.sizeImage === 'm',
195
184
  'col-4': hasImage && data?.sizeImage === 'l',
185
+ 'ps-0': data?.rightImage,
196
186
  })}
197
187
  >
198
- <CardText>
199
- {redraft(
200
- content,
201
- config.settings.richtextViewSettings.ToHTMLRenderers,
202
- config.settings.richtextViewSettings.ToHTMLOptions,
203
- )}
204
- </CardText>
188
+ {redraft(
189
+ content,
190
+ config.settings.richtextViewSettings.ToHTMLRenderers,
191
+ config.settings.richtextViewSettings.ToHTMLOptions,
192
+ )}
205
193
  </div>
206
194
  </Row>
207
195
  </Container>
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable jsx-a11y/no-static-element-interactions */
2
2
  /* eslint-disable jsx-a11y/click-events-have-key-events */
3
- import React, { useState, useRef, useEffect } from 'react';
4
- import { Card, CardBody, CardTitle, CardText } from 'design-react-kit';
3
+ import React, { useState, useEffect } from 'react';
4
+ import { Card, CardBody, CardTitle } from 'design-react-kit';
5
5
  import { defineMessages, useIntl } from 'react-intl';
6
6
  import PropTypes from 'prop-types';
7
7
  import redraft from 'redraft';
@@ -98,28 +98,26 @@ const Block = ({
98
98
  setSelectedField('content');
99
99
  }}
100
100
  >
101
- <CardText>
102
- <TextEditorWidget
103
- data={data}
104
- fieldName="simple_card_content"
105
- selected={selectedField === 'content'}
106
- block={block}
107
- onChangeBlock={(data) =>
108
- onChange(data, 'simple_card_content')
109
- }
110
- placeholder={intl.formatMessage(
111
- messages.simple_card_content,
112
- )}
113
- showToolbar={true}
114
- onSelectBlock={onSelectBlock}
115
- onAddBlock={onAddBlock}
116
- index={index}
117
- onFocusNextBlock={onFocusNextBlock}
118
- onFocusPreviousBlock={() => {
119
- setSelectedField('title');
120
- }}
121
- />
122
- </CardText>
101
+ <TextEditorWidget
102
+ data={data}
103
+ fieldName="simple_card_content"
104
+ selected={selectedField === 'content'}
105
+ block={block}
106
+ onChangeBlock={(data) =>
107
+ onChange(data, 'simple_card_content')
108
+ }
109
+ placeholder={intl.formatMessage(
110
+ messages.simple_card_content,
111
+ )}
112
+ showToolbar={true}
113
+ onSelectBlock={onSelectBlock}
114
+ onAddBlock={onAddBlock}
115
+ index={index}
116
+ onFocusNextBlock={onFocusNextBlock}
117
+ onFocusPreviousBlock={() => {
118
+ setSelectedField('title');
119
+ }}
120
+ />
123
121
  </div>
124
122
  </>
125
123
  ) : (
@@ -127,16 +125,12 @@ const Block = ({
127
125
  <CardTitle tag="h4" id={block.id + '-title'}>
128
126
  {title}
129
127
  </CardTitle>
130
- <Divider />
131
- <div>
132
- <CardText>
133
- {redraft(
134
- content,
135
- config.settings.richtextViewSettings.ToHTMLRenderers,
136
- config.settings.richtextViewSettings.ToHTMLOptions,
137
- )}
138
- </CardText>
139
- </div>
128
+ <hr />
129
+ {redraft(
130
+ content,
131
+ config.settings.richtextViewSettings.ToHTMLRenderers,
132
+ config.settings.richtextViewSettings.ToHTMLOptions,
133
+ )}
140
134
  </>
141
135
  )}
142
136
  </div>
@@ -6,13 +6,10 @@
6
6
  import React from 'react';
7
7
  import PropTypes from 'prop-types';
8
8
  import { Embed } from 'semantic-ui-react';
9
- import {
10
- isInternalURL,
11
- getParentUrl,
12
- flattenToAppURL,
13
- } from '@plone/volto/helpers';
9
+ import { isInternalURL, getParentUrl } from '@plone/volto/helpers';
14
10
  import { ConditionalEmbed } from 'volto-gdpr-privacy';
15
11
  import { FontAwesomeIcon } from 'design-comuni-plone-theme/components/ItaliaTheme';
12
+ import { videoUrlHelper } from 'design-comuni-plone-theme/helpers';
16
13
  import { useIntl, defineMessages } from 'react-intl';
17
14
  import config from '@plone/volto/registry';
18
15
 
@@ -34,23 +31,36 @@ const messages = defineMessages({
34
31
  */
35
32
  const ViewBlock = ({ data, index, isEditMode = false }) => {
36
33
  const intl = useIntl();
37
- let placeholder = data.preview_image
38
- ? isInternalURL(data.preview_image)
39
- ? `${flattenToAppURL(data.preview_image)}/@@images/image`
40
- : data.preview_image
41
- : null;
42
34
 
43
- if (!placeholder && data.url) {
44
- if (data.url.match('youtu')) {
45
- //load video preview image from youtube
35
+ let placeholder = null;
36
+ let videoID = null;
37
+ let listID = null;
46
38
 
47
- const videoID = data.url.match(/.be\//)
48
- ? data.url.match(/^.*\.be\/(.*)/)?.[1]
49
- : data.url.match(/^.*\?v=(.*)$/)?.[1];
50
- placeholder = 'https://img.youtube.com/vi/' + videoID + '/hqdefault.jpg';
51
- } else if (data.url.match('vimeo')) {
52
- const videoID = data.url.match(/^.*\.com\/(.*)/)[1];
53
- placeholder = 'https://vumbnail.com/' + videoID + '.jpg';
39
+ if (data.url) {
40
+ const [computedID, computedPlaceholder] = videoUrlHelper(
41
+ data.url,
42
+ data?.preview_image,
43
+ );
44
+ if (computedID) {
45
+ videoID = computedID;
46
+ }
47
+ if (computedPlaceholder) {
48
+ placeholder = computedPlaceholder;
49
+ }
50
+
51
+ if (data.url.match('list')) {
52
+ const matches = data.url.match(/^.*\?list=(.*)|^.*&list=(.*)$/);
53
+ listID = matches[1] || matches[2];
54
+
55
+ let thumbnailID = null;
56
+ if (data.url.match(/\?v=(.*)&list/)) {
57
+ thumbnailID = data.url.match(/^.*\?v=(.*)&list(.*)/)[1];
58
+ }
59
+ if (data.url.match(/\?v=(.*)\?list/)) {
60
+ thumbnailID = data.url.match(/^.*\?v=(.*)\?list(.*)/)[1];
61
+ }
62
+ placeholder =
63
+ 'https://img.youtube.com/vi/' + thumbnailID + '/hqdefault.jpg';
54
64
  }
55
65
  }
56
66
 
@@ -90,31 +100,17 @@ const ViewBlock = ({ data, index, isEditMode = false }) => {
90
100
  <>
91
101
  {data.url.match('list') ? (
92
102
  <Embed
93
- url={`https://www.youtube.com/embed/videoseries?list=${
94
- data.url.match(/^.*\?list=(.*)$/)[1]
95
- }`}
103
+ url={`https://www.youtube.com/embed/videoseries?list=${listID}`}
96
104
  {...embedSettings}
97
105
  />
98
106
  ) : (
99
- <Embed
100
- id={
101
- data.url.match(/.be\//)
102
- ? data.url.match(/^.*\.be\/(.*)/)?.[1]
103
- : data.url.match(/^.*\?v=(.*)$/)?.[1]
104
- }
105
- source="youtube"
106
- {...embedSettings}
107
- />
107
+ <Embed id={videoID} source="youtube" {...embedSettings} />
108
108
  )}
109
109
  </>
110
110
  ) : (
111
111
  <>
112
112
  {data.url.match('vimeo') ? (
113
- <Embed
114
- id={data.url.match(/^.*\.com\/(.*)/)[1]}
115
- source="vimeo"
116
- {...embedSettings}
117
- />
113
+ <Embed id={videoID} source="vimeo" {...embedSettings} />
118
114
  ) : (
119
115
  <>
120
116
  {data.url.match('.mp4') ? (
@@ -112,13 +112,14 @@ const MegaMenu = ({ item, pathname }) => {
112
112
 
113
113
  if (item.mode === 'simpleLink') {
114
114
  return item.linkUrl?.length > 0 ? (
115
- <NavItem tag="li">
115
+ <NavItem tag="li" active={isItemActive} role="none">
116
116
  <NavLink
117
117
  href={item.linkUrl === '' ? '/' : null}
118
118
  item={item.linkUrl[0]?.['@id'] ? item.linkUrl[0] : '#'}
119
119
  tag={UniversalLink}
120
120
  active={isItemActive}
121
121
  data-element={item.id_lighthouse}
122
+ role="menuitem"
122
123
  >
123
124
  <span dangerouslySetInnerHTML={{ __html: item.title }}></span>
124
125
  {isItemActive && (
@@ -238,7 +239,7 @@ const MegaMenu = ({ item, pathname }) => {
238
239
  }
239
240
 
240
241
  return (
241
- <NavItem tag="li" className="megamenu" active={isItemActive}>
242
+ <NavItem tag="li" className="megamenu" active={isItemActive} role="none">
242
243
  <UncontrolledDropdown
243
244
  nav
244
245
  inNavbar
@@ -269,6 +270,9 @@ const MegaMenu = ({ item, pathname }) => {
269
270
  }
270
271
  }}
271
272
  title={intl.formatMessage(messages.closeMenu)}
273
+ // APG spec: on Tab menu closes, so remove it from focusable elements
274
+ // https://www.w3.org/WAI/ARIA/apg/patterns/menubar/examples/menubar-navigation/
275
+ tabIndex="-1"
272
276
  >
273
277
  <Icon icon="it-close" />
274
278
  </Button>
@@ -278,10 +282,14 @@ const MegaMenu = ({ item, pathname }) => {
278
282
  <Row>
279
283
  {childrenGroups.map((group, index) => (
280
284
  <Col lg={12 / max_cols} key={'group_' + index}>
281
- <LinkList className="bordered">
285
+ <LinkList
286
+ className="bordered"
287
+ role="menu"
288
+ aria-label={item.title ?? ''}
289
+ >
282
290
  {group.map((child, idx) => {
283
291
  return (
284
- <li key={child['@id'] + idx}>
292
+ <li key={child['@id'] + idx} role="none">
285
293
  {child.showAsHeader ? (
286
294
  <h3
287
295
  className={cx('list-item', {
@@ -298,6 +306,7 @@ const MegaMenu = ({ item, pathname }) => {
298
306
  key={child['@id']}
299
307
  onClick={() => setMenuStatus(false)}
300
308
  role="menuitem"
309
+ aria-current="page"
301
310
  >
302
311
  <span>{child.title}</span>
303
312
  </ConditionalLink>
@@ -362,12 +371,13 @@ const MegaMenu = ({ item, pathname }) => {
362
371
  <Row>
363
372
  <Col lg={8} />
364
373
  <Col lg={4}>
365
- <LinkList>
366
- <li className="it-more text-end">
374
+ <LinkList role="menu" aria-label={item.showMoreText ?? ''}>
375
+ <li className="it-more text-end" role="none">
367
376
  <UniversalLink
368
377
  className="list-item medium"
369
378
  item={item.showMoreLink[0]}
370
379
  onClick={() => setMenuStatus(false)}
380
+ role="menuitem"
371
381
  >
372
382
  <span>
373
383
  {item.showMoreText?.length > 0
@@ -44,17 +44,18 @@ const MenuSecondary = ({ pathname }) => {
44
44
 
45
45
  return (
46
46
  items?.length > 0 && (
47
- <Nav navbar className="navbar-secondary" role="navigation">
47
+ <Nav navbar className="navbar-secondary" role="menubar">
48
48
  {items.map((item, i) => {
49
49
  let url = item.href || item.linkUrl?.[0]?.['@id'] || '';
50
50
 
51
51
  return (
52
- <NavItem tag="li" key={i}>
52
+ <NavItem tag="li" active={isMenuActive(url)} key={i} role="none">
53
53
  <NavLink
54
54
  href={url === '' ? '/' : flattenToAppURL(url)}
55
55
  tag={UniversalLink}
56
56
  active={isMenuActive(url)}
57
57
  data-element={item.id_lighthouse}
58
+ role="menuitem"
58
59
  >
59
60
  <span
60
61
  className={item.inEvidence ? 'fw-bold' : ''}
@@ -1,32 +1,47 @@
1
1
  import React from 'react';
2
2
  import { Card, CardBody } from 'design-react-kit';
3
3
  import { UniversalLink } from '@plone/volto/components';
4
- import Highlighter from 'react-highlight-words';
5
4
 
6
- const ResultItem = ({ item, index, section, searchableText }) => {
7
- const filteredWords = searchableText.split(' ');
5
+ const Marker = ({ text = '', highlight = '' }) => {
6
+ if (!highlight.trim()) {
7
+ return text;
8
+ }
9
+ const regex = new RegExp(
10
+ `(${highlight
11
+ .split(' ')
12
+ // remove any characters not in these ranges
13
+ .map((s) => s.replace(/[^a-zA-Z0-9À-ÖØ-öø-ÿ]/g, ''))
14
+ .filter((s) => s !== '')
15
+ .join('|')})`,
16
+ 'gi',
17
+ );
18
+ // Split on highlight term and include term into parts, ignore case
19
+ const parts = text.split(regex);
20
+ return (
21
+ <>
22
+ {parts.map((part, i) =>
23
+ part.match(regex) ? (
24
+ <mark className="highlighted-text">{part}</mark>
25
+ ) : (
26
+ part
27
+ ),
28
+ )}
29
+ </>
30
+ );
31
+ };
8
32
 
33
+ const ResultItem = ({ item, index, section, searchableText }) => {
9
34
  return (
10
35
  <Card noWrapper={true} className="mt-3 mb-3">
11
36
  <CardBody className="shadow-sm px-4 pt-4 pb-4 rounded">
12
37
  {section}
13
38
  <h4 className="card-title">
14
39
  <UniversalLink item={item}>
15
- <Highlighter
16
- highlightClassName="highlighted-text"
17
- searchWords={filteredWords}
18
- autoEscape={true}
19
- textToHighlight={item.title}
20
- />
40
+ <Marker highlight={searchableText} text={item.title} />
21
41
  </UniversalLink>
22
42
  </h4>
23
43
  <p className="text-paragraph">
24
- <Highlighter
25
- highlightClassName="highlighted-text"
26
- searchWords={filteredWords}
27
- autoEscape={true}
28
- textToHighlight={item.description}
29
- />
44
+ <Marker highlight={searchableText} text={item.description} />
30
45
  </p>
31
46
  </CardBody>
32
47
  </Card>
@@ -151,6 +151,10 @@ const messages = defineMessages({
151
151
  id: 'search_skip_to_search_results',
152
152
  defaultMessage: 'Vai ai risultati di ricerca',
153
153
  },
154
+ active_filters: {
155
+ id: 'active_filters',
156
+ defaultMessage: '{filterNumber} filtri attivati',
157
+ },
154
158
  });
155
159
 
156
160
  const searchOrderDict = {
@@ -444,11 +448,21 @@ const Search = () => {
444
448
  <div className="pt-4 pt-lg-0">
445
449
  <h6 className="text-uppercase">
446
450
  {intl.formatMessage(messages.sections)}
447
- {activeSections > 0 && (
448
- <span className="badge bg-secondary ms-3">
449
- {activeSections}
450
- </span>
451
- )}
451
+
452
+ <span
453
+ className={cx('badge bg-secondary ms-3', {
454
+ 'visually-hidden': activeSections === 0,
455
+ })}
456
+ aria-live="polite"
457
+ aria-label={intl.formatMessage(
458
+ messages.active_filters,
459
+ {
460
+ filterNumber: activeSections,
461
+ },
462
+ )}
463
+ >
464
+ {activeSections}
465
+ </span>
452
466
  </h6>
453
467
  <div className="mt-4">
454
468
  <SearchSections
@@ -470,11 +484,21 @@ const Search = () => {
470
484
  >
471
485
  <h6 className="text-uppercase">
472
486
  {intl.formatMessage(messages.topics)}
473
- {activeTopics > 0 && (
474
- <span className="badge bg-secondary ms-3">
475
- {activeTopics}
476
- </span>
477
- )}
487
+
488
+ <span
489
+ className={cx('badge bg-secondary ms-3', {
490
+ 'visually-hidden': activeTopics === 0,
491
+ })}
492
+ aria-live="polite"
493
+ aria-label={intl.formatMessage(
494
+ messages.active_filters,
495
+ {
496
+ filterNumber: activeTopics,
497
+ },
498
+ )}
499
+ >
500
+ {activeTopics}
501
+ </span>
478
502
  </h6>
479
503
  <div className="form-check mt-4">
480
504
  <SearchTopics
@@ -507,14 +531,21 @@ const Search = () => {
507
531
  <div className="p-3 shadow-sm bg-white">
508
532
  <h6 className="text-uppercase">
509
533
  {intl.formatMessage(messages.content_types)}
510
- {activePortalTypes > 0 && (
511
- <span
512
- className="badge bg-secondary ms-3"
513
- aria-live="polite"
514
- >
515
- {activePortalTypes}
516
- </span>
517
- )}
534
+
535
+ <span
536
+ className={cx('badge bg-secondary ms-3', {
537
+ 'visually-hidden': activePortalTypes === 0,
538
+ })}
539
+ aria-live="polite"
540
+ aria-label={intl.formatMessage(
541
+ messages.active_filters,
542
+ {
543
+ filterNumber: activePortalTypes,
544
+ },
545
+ )}
546
+ >
547
+ {activePortalTypes}
548
+ </span>
518
549
  </h6>
519
550
  <div className="form-checck mt-4">
520
551
  <SearchCTs
@@ -613,7 +644,6 @@ const Search = () => {
613
644
  <Col lg={9} tag="section" className="py-lg-5">
614
645
  <div
615
646
  className="search-results-wrapper"
616
- role="region"
617
647
  id="search-results-region"
618
648
  aria-live="polite"
619
649
  >
@@ -65,8 +65,8 @@ import { schemaListing } from 'design-comuni-plone-theme/components/ItaliaTheme/
65
65
 
66
66
  import reducers from 'design-comuni-plone-theme/reducers';
67
67
 
68
- const ReleaseLog = loadable(
69
- () => import('design-comuni-plone-theme/components/ReleaseLog/ReleaseLog'),
68
+ const ReleaseLog = loadable(() =>
69
+ import('design-comuni-plone-theme/components/ReleaseLog/ReleaseLog'),
70
70
  );
71
71
 
72
72
  const messages = defineMessages({
@@ -486,10 +486,9 @@ export default function applyConfig(voltoConfig) {
486
486
  },
487
487
  };
488
488
  // Remove Horizontal Menu variation of TOC Block
489
- config.blocks.blocksConfig.toc.variations =
490
- config.blocks.blocksConfig.toc.variations.filter(
491
- (v) => v.id !== 'horizontalMenu',
492
- );
489
+ config.blocks.blocksConfig.toc.variations = config.blocks.blocksConfig.toc.variations.filter(
490
+ (v) => v.id !== 'horizontalMenu',
491
+ );
493
492
 
494
493
  // COMPONENTS
495
494
  config.components = {
@@ -23,6 +23,7 @@ import clearSVG from '@plone/volto/icons/clear.svg';
23
23
  import codeSVG from '@plone/volto/icons/code.svg';
24
24
  import indentSVG from '@plone/volto/icons/indent.svg';
25
25
  import Sidebar from 'design-comuni-plone-theme/components/ItaliaTheme/Blocks/HTML/Sidebar.jsx';
26
+ import { Toast } from '@plone/volto/components';
26
27
 
27
28
  const Editor = loadable(() => import('react-simple-code-editor'));
28
29
 
@@ -157,21 +158,26 @@ class Edit extends Component {
157
158
  */
158
159
  onPreview() {
159
160
  try {
160
- const code = this.props.prettierStandalone
161
+ this.props.prettierStandalone
161
162
  .format(this.getValue(), {
162
163
  parser: 'html',
163
164
  plugins: [this.props.prettierParserHtml],
164
165
  })
165
- .trim();
166
- this.setState(
167
- {
168
- isPreview: !this.state.isPreview,
169
- },
170
- () => this.onChangeCode(code),
171
- );
166
+ .then((value) => {
167
+ this.onChangeCode(value.trim());
168
+ });
169
+ this.setState({
170
+ isPreview: !this.state.isPreview,
171
+ });
172
172
  } catch (ex) {
173
173
  // error while parsing the user-typed HTML
174
- // TODO: show a toast notification or something similar to the user
174
+ this.props.toastify.toast.error(
175
+ <Toast
176
+ error
177
+ title="Errore"
178
+ content="C'è stato un errore nel formattare il codice html inserito"
179
+ />,
180
+ );
175
181
  }
176
182
  }
177
183
 
@@ -182,16 +188,23 @@ class Edit extends Component {
182
188
  */
183
189
  onPrettify = () => {
184
190
  try {
185
- const code = this.props.prettierStandalone
191
+ this.props.prettierStandalone
186
192
  .format(this.getValue(), {
187
193
  parser: 'html',
188
194
  plugins: [this.props.prettierParserHtml],
189
195
  })
190
- .trim();
191
- this.onChangeCode(code);
196
+ .then((value) => {
197
+ this.onChangeCode(value.trim());
198
+ });
192
199
  } catch (ex) {
193
200
  // error while parsing the user-typed HTML
194
- // TODO: show a toast notification or something similar to the user
201
+ this.props.toastify.toast.error(
202
+ <Toast
203
+ error
204
+ title="Errore"
205
+ content="C'è stato un errore nel formattare il codice html inserito"
206
+ />,
207
+ );
195
208
  }
196
209
  };
197
210
 
@@ -259,6 +272,7 @@ class Edit extends Component {
259
272
  aria-label={this.props.intl.formatMessage(messages.source)}
260
273
  active={!this.state.isPreview}
261
274
  onClick={this.onCodeEditor}
275
+ type="button"
262
276
  >
263
277
  <Icon name={codeSVG} size="24px" />
264
278
  </Button>
@@ -275,6 +289,7 @@ class Edit extends Component {
275
289
  aria-label={this.props.intl.formatMessage(messages.preview)}
276
290
  active={this.state.isPreview}
277
291
  onClick={this.onPreview}
292
+ type="button"
278
293
  >
279
294
  <Icon name={showSVG} size="24px" />
280
295
  </Button>
@@ -290,6 +305,7 @@ class Edit extends Component {
290
305
  basic
291
306
  aria-label={this.props.intl.formatMessage(messages.prettier)}
292
307
  onClick={this.onPrettify}
308
+ type="button"
293
309
  >
294
310
  <Icon name={indentSVG} size="24px" />
295
311
  </Button>
@@ -302,7 +318,12 @@ class Edit extends Component {
302
318
  <Popup
303
319
  trigger={
304
320
  <Button.Group>
305
- <Button icon basic onClick={() => this.onChangeCode('')}>
321
+ <Button
322
+ icon
323
+ basic
324
+ type="button"
325
+ onClick={() => this.onChangeCode('')}
326
+ >
306
327
  <Icon name={clearSVG} size="24px" color="#e40166" />
307
328
  </Button>
308
329
  </Button.Group>
@@ -343,7 +364,7 @@ class Edit extends Component {
343
364
  : () => {}
344
365
  }
345
366
  padding={8}
346
- className="html-editor container"
367
+ className="html-editor"
347
368
  ref={(node) => {
348
369
  if (node) {
349
370
  this.codeEditorRef.current = node;
@@ -383,7 +404,12 @@ const withPrismMarkup = (WrappedComponent) => (props) => {
383
404
  };
384
405
 
385
406
  export default compose(
386
- injectLazyLibs(['prettierStandalone', 'prettierParserHtml', 'prismCore']),
407
+ injectLazyLibs([
408
+ 'prettierStandalone',
409
+ 'prettierParserHtml',
410
+ 'prismCore',
411
+ 'toastify',
412
+ ]),
387
413
  withPrismMarkup,
388
414
  injectIntl,
389
415
  )(Edit);
@@ -68,7 +68,11 @@ const ListingBody = React.memo(
68
68
 
69
69
  if (!block?.show_block_bg && !isSearchBlockResults) return 'full-width';
70
70
 
71
- let bg_color = data.bg_color ? `bg-${data.bg_color}` : '';
71
+ let bg_color = config.blocks?.blocksConfig[
72
+ 'listing'
73
+ ]?.listing_bg_colors.some((color) => color.name === data.bg_color)
74
+ ? `bg-${data.bg_color}`
75
+ : 'bg-light';
72
76
 
73
77
  if (block.template === 'gridGalleryTemplate') {
74
78
  return `section section-muted section-inset-shadow py-5 ${bg_color} ${
@@ -76,7 +80,7 @@ const ListingBody = React.memo(
76
80
  }`;
77
81
  } else {
78
82
  return `py-5 ${bg_color} ${
79
- isSearchBlockResults ? 'template-wrapper' : 'bg-light full-width'
83
+ isSearchBlockResults ? 'template-wrapper' : 'full-width'
80
84
  }`;
81
85
  }
82
86
  };
@@ -4,6 +4,7 @@
4
4
  */
5
5
 
6
6
  import React, { useEffect, useState } from 'react';
7
+ import { defineMessages, useIntl } from 'react-intl';
7
8
  import PropTypes from 'prop-types';
8
9
  import { useDispatch, useSelector } from 'react-redux';
9
10
  import { UniversalLink } from '@plone/volto/components';
@@ -25,9 +26,13 @@ import {
25
26
  } from 'design-comuni-plone-theme/components/ItaliaTheme';
26
27
 
27
28
  import { getDropdownMenuNavitems, getItemsByPath } from 'volto-dropdownmenu';
29
+ import FocusLock from 'react-focus-lock';
28
30
 
29
31
  const Navigation = ({ pathname }) => {
32
+ const intl = useIntl();
30
33
  const [collapseOpen, setCollapseOpen] = useState(false);
34
+ const [focusTrapActive, setFocusTrapActive] = useState(false);
35
+
31
36
  const dispatch = useDispatch();
32
37
 
33
38
  const subsite = useSelector((state) => state.subsite?.data);
@@ -73,6 +78,7 @@ const Navigation = ({ pathname }) => {
73
78
  }
74
79
 
75
80
  setCollapseOpen(false);
81
+ setFocusTrapActive(false);
76
82
  };
77
83
 
78
84
  document.body.addEventListener('click', blocksClickListener);
@@ -89,7 +95,10 @@ const Navigation = ({ pathname }) => {
89
95
  aria-controls="#it-navigation-collapse"
90
96
  aria-expanded={collapseOpen}
91
97
  aria-label="Toggle navigation"
92
- onClick={() => setCollapseOpen(!collapseOpen)}
98
+ onClick={() => {
99
+ setCollapseOpen(!collapseOpen);
100
+ setFocusTrapActive(!focusTrapActive);
101
+ }}
93
102
  >
94
103
  <Icon icon="it-burger" />
95
104
  </HeaderToggler>
@@ -99,44 +108,57 @@ const Navigation = ({ pathname }) => {
99
108
  navbar
100
109
  onOverlayClick={() => setCollapseOpen(!collapseOpen)}
101
110
  id="it-navigation-collapse"
111
+ showCloseButton={false}
102
112
  >
103
- <div className="menu-wrapper">
104
- <div className="it-brand-wrapper" role="navigation">
105
- <UniversalLink
106
- href={
107
- subsite?.['@id'] ? flattenToAppURL(subsite['@id']) : '/'
108
- }
109
- onClick={() => setCollapseOpen(false)}
113
+ <FocusLock disabled={!focusTrapActive}>
114
+ <div className="menu-wrapper">
115
+ <div className="it-brand-wrapper" role="navigation">
116
+ <UniversalLink
117
+ href={
118
+ subsite?.['@id'] ? flattenToAppURL(subsite['@id']) : '/'
119
+ }
120
+ onClick={() => setCollapseOpen(false)}
121
+ >
122
+ {subsite?.subsite_logo ? logoSubsite : <Logo />}
123
+ <BrandText mobile={true} subsite={subsite} />
124
+ </UniversalLink>
125
+ </div>
126
+ {/* Main Menu */}
127
+ <Nav data-element="main-navigation" navbar role="menubar">
128
+ {menu
129
+ ?.filter((item) => item.visible)
130
+ ?.map((item, index) => (
131
+ <MegaMenu
132
+ item={item}
133
+ pathname={pathname}
134
+ key={index + 'mm'}
135
+ />
136
+ ))}
137
+ </Nav>
138
+
139
+ {/* Secondary Menu */}
140
+ <MenuSecondary pathname={pathname} />
141
+
142
+ {/* Headerslim Menu - main site */}
143
+ {!subsite && <TertiaryMenu />}
144
+
145
+ {/* Social Links */}
146
+ <SocialHeader />
147
+
148
+ {/* Headerslim Menu - parent site (if subsite) */}
149
+ {subsite && <ParentSiteMenu />}
150
+ </div>
151
+ <div className="close-div">
152
+ <button
153
+ className="btn close-menu"
154
+ type="button"
155
+ title={intl.formatMessage(messages.CloseMenu)}
156
+ onClick={() => setCollapseOpen(!collapseOpen)}
110
157
  >
111
- {subsite?.subsite_logo ? logoSubsite : <Logo />}
112
- <BrandText mobile={true} subsite={subsite} />
113
- </UniversalLink>
158
+ <Icon color="white" icon="it-close-big" padding={false} />
159
+ </button>
114
160
  </div>
115
- {/* Main Menu */}
116
- <Nav data-element="main-navigation" navbar>
117
- {menu
118
- ?.filter((item) => item.visible)
119
- ?.map((item, index) => (
120
- <MegaMenu
121
- item={item}
122
- pathname={pathname}
123
- key={index + 'mm'}
124
- />
125
- ))}
126
- </Nav>
127
-
128
- {/* Secondary Menu */}
129
- <MenuSecondary pathname={pathname} />
130
-
131
- {/* Headerslim Menu - main site */}
132
- {!subsite && <TertiaryMenu />}
133
-
134
- {/* Social Links */}
135
- <SocialHeader />
136
-
137
- {/* Headerslim Menu - parent site (if subsite) */}
138
- {subsite && <ParentSiteMenu />}
139
- </div>
161
+ </FocusLock>
140
162
  </Collapse>
141
163
  </HeaderContent>
142
164
  ) : null}
@@ -144,6 +166,13 @@ const Navigation = ({ pathname }) => {
144
166
  );
145
167
  };
146
168
 
169
+ const messages = defineMessages({
170
+ CloseMenu: {
171
+ id: 'close-menu',
172
+ defaultMessage: 'Chiudi menu',
173
+ },
174
+ });
175
+
147
176
  Navigation.propTypes = {
148
177
  pathname: PropTypes.string.isRequired,
149
178
  };
@@ -17,26 +17,28 @@
17
17
 
18
18
  .bg-alert-danger {
19
19
  background-color: $alert-danger;
20
- color: $white;
20
+ color: $alert-danger-text;
21
21
 
22
22
  a {
23
- color: $white;
23
+ color: $alert-danger-text;
24
24
  }
25
25
  }
26
26
 
27
27
  .bg-alert-warning {
28
28
  background-color: $alert-warning;
29
+ color: $alert-warning-text;
29
30
 
30
31
  a {
31
- color: $body-color;
32
+ color: $alert-warning-text;
32
33
  }
33
34
  }
34
35
 
35
36
  .bg-alert-info {
36
37
  background-color: $alert-info;
38
+ color: $alert-info-text;
37
39
 
38
40
  a {
39
- color: $body-color;
41
+ color: $alert-info-text;
40
42
  }
41
43
  }
42
44
 
@@ -46,7 +46,7 @@
46
46
  position: absolute;
47
47
  width: 100%;
48
48
  height: 100%;
49
- background-color: rgba(#000, 0.5);
49
+ background-color: rgba(#000, 0.65);
50
50
  content: '';
51
51
  }
52
52
  }
@@ -154,10 +154,15 @@
154
154
  right: 0;
155
155
  bottom: 0;
156
156
  left: 0;
157
- background: rgba(0, 0, 0, 0.6);
158
157
  content: '';
159
- opacity: 0.75;
160
158
  transition: opacity 0.3s ease;
159
+ background: rgba(0, 0, 0, 0.6);
160
+ opacity: 0.75;
161
+ }
162
+
163
+ &:not(:has(picture))::before {
164
+ background-color: rgba(#000, 0.75);
165
+ opacity: 0.9;
161
166
  }
162
167
 
163
168
  &:hover,
@@ -36,7 +36,7 @@
36
36
  position: absolute;
37
37
  width: 100%;
38
38
  height: 100%;
39
- background-color: rgba(#000, 0.5);
39
+ background-color: rgba(#000, 0.65);
40
40
  content: '';
41
41
  }
42
42
  }
@@ -60,7 +60,7 @@
60
60
  }
61
61
 
62
62
  &.card-teaser .card-body {
63
- flex: 1 0 75%;
63
+ flex: 1 0 74%;
64
64
  }
65
65
  }
66
66
 
@@ -7,5 +7,6 @@
7
7
  border-color: var(--focus-outline-color) !important;
8
8
  box-shadow: 0 0 0 2px var(--focus-outline-color) !important;
9
9
  outline: none !important;
10
+ background-color: #0062e2;
10
11
  }
11
12
  }
@@ -21,7 +21,7 @@ $font-family-monospace-light: Roboto Mono Light !default;
21
21
 
22
22
  // Per abilitare l'header bianco impostare a true
23
23
  // e impostare "$header-center-bg-color: white" come qui sotto
24
- $enable-header-white-background: false;
24
+ $enable-header-white-background: false !default;
25
25
  // $header-center-bg-color: white;
26
26
  // $header-slim-bg-color: #3f3f3f;
27
27
 
@@ -42,9 +42,12 @@ $caption-text: #455b71 !default;
42
42
  $primary-a0: hsl($primary-h, 62%, 97%) !default;
43
43
 
44
44
  // ALERT-BLOCK CUSTOM COLORS
45
- $alert-danger: #a32219;
46
- $alert-warning: #eb973f;
47
- $alert-info: #f0c250;
45
+ $alert-danger: #a32219 !default;
46
+ $alert-danger-text: #fff !default;
47
+ $alert-warning: #eb973f !default;
48
+ $alert-warning-text: #000 !default;
49
+ $alert-info: #f0c250 !default;
50
+ $alert-info-text: #000 !default;
48
51
 
49
52
  $argument-icon-color: $tertiary !default;
50
53
  $argument-icon-bg: #f5f6f7 !default;
@@ -203,4 +203,5 @@
203
203
  // gestione dei focus
204
204
  @import 'bootstrap-italia/src/scss/utilities/focus';
205
205
  @import 'bootstrap-italia/src/scss/utilities/icons';
206
+ @import './bootstrap-italia/focus';
206
207
  }
@@ -0,0 +1,3 @@
1
+ .skiplinks a:focus:not(.focus--mouse) {
2
+ border: 2px solid;
3
+ }