@eeacms/volto-eea-design-system 1.0.2 → 1.0.4

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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,53 @@ All notable changes to this project will be documented in this file. Dates are d
4
4
 
5
5
  Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
6
6
 
7
+ ### [1.0.4](https://github.com/eea/volto-eea-design-system/compare/1.0.3...1.0.4) - 27 March 2023
8
+
9
+ #### :rocket: New Features
10
+
11
+ - feat(copyright): Add copyright prefix - Image - refs #250724 [Alin Voinea - [`6a72772`](https://github.com/eea/volto-eea-design-system/commit/6a727723c15aee499ed7cedc9f364c5e2c8014bb)]
12
+
13
+ #### :house: Internal changes
14
+
15
+ - style(copyright): Cleanup useless min-height - refs #250724 [Alin Voinea - [`f2457df`](https://github.com/eea/volto-eea-design-system/commit/f2457df6376ac1a4d00f87eee90e61f66f7ffebb)]
16
+
17
+ #### :hammer_and_wrench: Others
18
+
19
+ - Back to dev [Alin Voinea - [`cfd6eba`](https://github.com/eea/volto-eea-design-system/commit/cfd6eba8b01eceff4e28ab7ab51b2457672ac172)]
20
+ ### [1.0.3](https://github.com/eea/volto-eea-design-system/compare/1.0.2...1.0.3) - 24 March 2023
21
+
22
+ #### :bug: Bug Fixes
23
+
24
+ - fix: improve full-width class [Miu Razvan - [`9322259`](https://github.com/eea/volto-eea-design-system/commit/93222590a630b27f3dfccb7df0a50070c9c9901c)]
25
+ - fix(header): Remove z-index from subsite logo #320 from eea/subsite-logo [ichim-david - [`5091100`](https://github.com/eea/volto-eea-design-system/commit/50911009918faf7d3064d97ea7b685ad71970521)]
26
+ - fix(header): Remove z-index from subsite logo [kreafox - [`d433a97`](https://github.com/eea/volto-eea-design-system/commit/d433a9788d76db0f1c08ef6bb2313f479c2bb19b)]
27
+
28
+ #### :nail_care: Enhancements
29
+
30
+ - change(banner): use custom-made Popup for better accessibility [David Ichim - [`10d0fcf`](https://github.com/eea/volto-eea-design-system/commit/10d0fcfb28ca97efe9fa5c0f6c9c350b76a73140)]
31
+ - change(popup): added also the basic property [David Ichim - [`a4497ac`](https://github.com/eea/volto-eea-design-system/commit/a4497acddde258ed31cda09f4d905e003a1e4611)]
32
+ - change(popup): added most important popup properties from Semantic ui implementation [David Ichim - [`61f65bc`](https://github.com/eea/volto-eea-design-system/commit/61f65bc0e5806aaac33b54db36d5360fd05a48cc)]
33
+ - change(header): Add search popup customizations from eea-website-theme [Krisztina Elekes - [`43e5a78`](https://github.com/eea/volto-eea-design-system/commit/43e5a78be8efa1098ea0fc87f43f40f2b5d482c1)]
34
+ - change(banner): use custom-made Popup for better accessibility [David Ichim - [`9108bee`](https://github.com/eea/volto-eea-design-system/commit/9108bee5f671505be5199e72a4749bb0af0c0cb9)]
35
+ - change(popup): create custom popup for better accessibility [David Ichim - [`036aac9`](https://github.com/eea/volto-eea-design-system/commit/036aac95509b6d78b2d3b251578a7de878e28371)]
36
+ - change(colors): update gray-4 color value #321 from eea/update-gray-4 [ichim-david - [`f458ff0`](https://github.com/eea/volto-eea-design-system/commit/f458ff0965debd3629cdd78362244836d0d42687)]
37
+ - refactor(tokens): updated gray-4 [Giorgos Stamatis - [`b890df7`](https://github.com/eea/volto-eea-design-system/commit/b890df7693880fb965e41752eda64df992a1cdc4)]
38
+ - change(banner): MetadataField now uses proper time tag when value is datetime [David Ichim - [`b4c4d34`](https://github.com/eea/volto-eea-design-system/commit/b4c4d34d5905a6771a281fc3db1174b4998c8fa8)]
39
+ - change(footer): Fix error and empty div if no social links are present #319 from eea/footer-social [ichim-david - [`8922246`](https://github.com/eea/volto-eea-design-system/commit/89222466b76a4720af73c0d516074efec0757c34)]
40
+ - change(footer): Fix error and empty div if no social links are present [kreafox - [`5d934a6`](https://github.com/eea/volto-eea-design-system/commit/5d934a6545ae783ff41dc9e3eda389c571d1369b)]
41
+
42
+ #### :hammer_and_wrench: Others
43
+
44
+ - (feat):Page Header Banner accessibility #316 from eea/accesibility-banner [ichim-david - [`e587f46`](https://github.com/eea/volto-eea-design-system/commit/e587f4657de137273053480a3536a066ab032a29)]
45
+ - lint 3 [Dobricean Ioan Dorian - [`2e0bed1`](https://github.com/eea/volto-eea-design-system/commit/2e0bed19a24d8abfa230212cd8c09f8313dc00f2)]
46
+ - prettier [Dobricean Ioan Dorian - [`6ed78e5`](https://github.com/eea/volto-eea-design-system/commit/6ed78e50ee68accca10b06b0790c231ddeb1a1fa)]
47
+ - lint [Dobricean Ioan Dorian - [`646dfaa`](https://github.com/eea/volto-eea-design-system/commit/646dfaa729b51367ce7545ea928837a481a5485a)]
48
+ - lint 1 [Dobricean Ioan Dorian - [`b4c9580`](https://github.com/eea/volto-eea-design-system/commit/b4c958034870a9861c542359144e3c56f9157994)]
49
+ - lint [Dobricean Ioan Dorian - [`ca41def`](https://github.com/eea/volto-eea-design-system/commit/ca41def7a3743a8328f26cec868bd20395b62446)]
50
+ - cleaning [Dobricean Ioan Dorian - [`4391aa6`](https://github.com/eea/volto-eea-design-system/commit/4391aa6c6611d1a15f5977eb150416909ad83bc1)]
51
+ - refactor [Dobricean Ioan Dorian - [`9789201`](https://github.com/eea/volto-eea-design-system/commit/9789201c7966cd711bfa85fe448f6f6df2583eaf)]
52
+ - storybook [Dobricean Ioan Dorian - [`c8c77de`](https://github.com/eea/volto-eea-design-system/commit/c8c77de372060328d535b190f30747797db0d23a)]
53
+ - banner accesibility [Dobricean Ioan Dorian - [`5e2f23b`](https://github.com/eea/volto-eea-design-system/commit/5e2f23bae30b5bb14d3f607e0cfeb85d0cfe4a9f)]
7
54
  ### [1.0.2](https://github.com/eea/volto-eea-design-system/compare/1.0.1...1.0.2) - 14 March 2023
8
55
 
9
56
  #### :bug: Bug Fixes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-eea-design-system",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "@eeacms/volto-eea-design-system: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: IDM2 A-Team",
@@ -6,7 +6,6 @@ import config from '@plone/volto/registry';
6
6
 
7
7
  Banner.propTypes = {
8
8
  title: PropTypes.string,
9
- image: PropTypes.bool,
10
9
  };
11
10
 
12
11
  const socialPlatforms = {
@@ -66,16 +65,19 @@ function Banner({ image, metadata, properties, children, ...rest }) {
66
65
  );
67
66
  }
68
67
 
69
- Banner.Action = function ({ id, title, icon, onClick, className, color }) {
68
+ Banner.Action = React.forwardRef(function (
69
+ { id, title, titleClass, icon, onClick, className, color },
70
+ ref,
71
+ ) {
70
72
  return (
71
- <div className="action">
73
+ <div className="action" ref={ref}>
72
74
  <Button className={className} basic icon inverted onClick={onClick}>
73
75
  <Icon className={icon} color={color}></Icon>
74
- <span className="mobile hidden">{title}</span>
76
+ <span className={titleClass || 'mobile hidden'}>{title}</span>
75
77
  </Button>
76
78
  </div>
77
79
  );
78
- };
80
+ });
79
81
 
80
82
  Banner.Content = ({ children, actions }) => {
81
83
  return (
@@ -98,12 +100,12 @@ Banner.Title = ({ children }) => {
98
100
  Banner.Subtitle = ({ children }) => <p className="subtitle">{children}</p>;
99
101
  Banner.Metadata = ({ children }) => <p className="metadata">{children}</p>;
100
102
 
101
- Banner.MetadataField = ({ hidden, type = 'text', label, value, title }) => {
103
+ Banner.MetadataField = ({ hidden, type = 'text', label, value }) => {
102
104
  const locale = config.settings.dateLocale || 'en-gb';
103
105
  if (hidden || !value) return '';
104
106
  if (type === 'date' && value)
105
107
  return (
106
- <span className={`field ${type}`} title={title?.replace('{}', value)}>
108
+ <time className={`field ${type}`} dateTime={value}>
107
109
  {label}{' '}
108
110
  {formatDate({
109
111
  date: value,
@@ -114,7 +116,7 @@ Banner.MetadataField = ({ hidden, type = 'text', label, value, title }) => {
114
116
  },
115
117
  locale: locale,
116
118
  })}
117
- </span>
119
+ </time>
118
120
  );
119
121
  return (
120
122
  <span className={`field ${type}`}>
@@ -1,8 +1,9 @@
1
- import React from 'react';
1
+ import React, { useRef } from 'react';
2
2
  import Banner from './Banner';
3
3
  // eslint-disable-next-line import/no-unresolved
4
4
  import imgUrl from '@eeacms/volto-eea-design-system/../theme/themes/eea/assets/images/banner.png';
5
- import { Popup, Icon } from 'semantic-ui-react';
5
+ import { Icon } from 'semantic-ui-react';
6
+ import Popup from '@eeacms/volto-eea-design-system/ui/Popup/Popup';
6
7
  import Copyright from '../Copyright/Copyright';
7
8
 
8
9
  export default {
@@ -12,54 +13,60 @@ export default {
12
13
  title: {
13
14
  description: 'banner title',
14
15
  table: {
15
- defaultValue: { summary: '""' },
16
+ defaultValue: { summary: '' },
16
17
  type: { summary: 'string' },
17
18
  },
18
19
  },
19
20
  metadata: {
20
21
  description: 'banner metadata',
21
22
  table: {
22
- defaultValue: { summary: '""' },
23
+ defaultValue: { summary: '' },
23
24
  type: { summary: 'object' },
24
25
  },
25
26
  },
26
27
  image: {
27
28
  description: 'set or unset banner image',
28
29
  table: {
29
- defaultValue: { summary: '""' },
30
+ defaultValue: { summary: '' },
30
31
  type: { summary: 'boolean' },
31
32
  },
32
33
  },
33
34
  hideShareButton: {
34
35
  description: 'hide/show share button',
35
36
  table: {
36
- defaultValue: { summary: '""' },
37
+ defaultValue: { summary: '' },
37
38
  type: { summary: 'boolean' },
38
39
  },
39
40
  },
40
41
  hideDownloadButton: {
41
42
  description: 'hide/show download button',
42
43
  table: {
43
- defaultValue: { summary: '""' },
44
+ defaultValue: { summary: '' },
44
45
  type: { summary: 'boolean' },
45
46
  },
46
47
  },
47
48
  copyright: {
48
49
  table: {
49
50
  category: 'Copyright',
50
- defaultValue: { summary: '""' },
51
+ defaultValue: { summary: '' },
52
+ type: { summary: 'string' },
53
+ },
54
+ },
55
+ copyrightPrefix: {
56
+ table: {
57
+ category: 'Copyright',
58
+ defaultValue: { summary: '' },
51
59
  type: { summary: 'string' },
52
60
  },
53
61
  },
54
62
  copyrightIcon: {
55
63
  table: {
56
64
  category: 'Copyright',
57
- defaultValue: { summary: '""' },
65
+ defaultValue: { summary: '' },
58
66
  type: { summary: 'string' },
59
67
  },
60
68
  },
61
69
  copyrightPosition: {
62
- name: 'Position',
63
70
  control: {
64
71
  type: 'inline-radio',
65
72
  options: ['left', 'right'],
@@ -73,69 +80,83 @@ export default {
73
80
  },
74
81
  };
75
82
 
76
- const Template = (args) => (
77
- <Banner {...args} image={args.image ? imgUrl : null}>
78
- <Banner.Content
79
- actions={
80
- <>
81
- {' '}
82
- {!args.hideShareButton && (
83
- <Popup
84
- className="share-popup"
85
- trigger={
86
- <Banner.Action
87
- icon="ri-share-fill"
88
- title="Share"
89
- className="share"
90
- />
91
- }
92
- content={() => (
93
- <>
94
- <p>Share to:</p>
95
- <div className="actions">
96
- <Banner.Action icon="ri-facebook-fill" />
97
- <Banner.Action icon="ri-twitter-fill" />
98
- <Banner.Action icon="ri-linkedin-fill" />
99
- </div>
100
- </>
101
- )}
102
- position="top center"
103
- basic
104
- />
105
- )}
106
- {!args.hideDownloadButton && (
107
- <Banner.Action
108
- icon="ri-download-2-line"
109
- title="Download"
110
- className="download"
111
- />
112
- )}
113
- </>
114
- }
115
- >
116
- <Banner.Subtitle>{args.subtitle}</Banner.Subtitle>
117
- <Banner.Title>{args.title}</Banner.Title>
118
- {args.metadata && (
119
- <Banner.Metadata>
83
+ const Template = (args) => {
84
+ const popupRef = useRef(null);
85
+ return (
86
+ <Banner {...args} image={args.image ? imgUrl : null}>
87
+ <Banner.Content
88
+ actions={
120
89
  <>
121
- {args.metadata.map((meta, index) => (
122
- <Banner.MetadataField
123
- {...meta}
124
- key={index}
125
- ></Banner.MetadataField>
126
- ))}
90
+ {!args.hideShareButton && (
91
+ <Popup
92
+ className="share-popup"
93
+ trigger={
94
+ <Banner.Action
95
+ icon="ri-share-fill"
96
+ title="Share"
97
+ className="share"
98
+ />
99
+ }
100
+ content={
101
+ <>
102
+ <p>Share to:</p>
103
+ <div className="actions" ref={popupRef}>
104
+ <Banner.Action
105
+ icon="ri-facebook-fill"
106
+ title={'Share page to Facebook'}
107
+ titleClass={'hiddenStructure'}
108
+ />
109
+ <Banner.Action
110
+ icon="ri-twitter-fill"
111
+ title={'Share page to Twitter'}
112
+ titleClass={'hiddenStructure'}
113
+ />
114
+ <Banner.Action
115
+ icon="ri-linkedin-fill"
116
+ title={'Share page to Linkedin'}
117
+ titleClass={'hiddenStructure'}
118
+ />
119
+ </div>
120
+ </>
121
+ }
122
+ position="top center"
123
+ />
124
+ )}
125
+ {!args.hideDownloadButton && (
126
+ <Banner.Action
127
+ icon="ri-download-2-line"
128
+ title="Download"
129
+ className="download"
130
+ />
131
+ )}
127
132
  </>
128
- </Banner.Metadata>
129
- )}
130
- <Copyright copyrightPosition={args.copyrightPosition}>
131
- <Copyright.Icon>
132
- <Icon className={args.copyrightIcon} />
133
- </Copyright.Icon>
134
- <Copyright.Text>{args.copyright}</Copyright.Text>
135
- </Copyright>
136
- </Banner.Content>
137
- </Banner>
138
- );
133
+ }
134
+ >
135
+ <Banner.Subtitle>{args.subtitle}</Banner.Subtitle>
136
+ <Banner.Title>{args.title}</Banner.Title>
137
+ {args.metadata && (
138
+ <Banner.Metadata>
139
+ <>
140
+ {args.metadata.map((meta, index) => (
141
+ <Banner.MetadataField
142
+ {...meta}
143
+ key={index}
144
+ ></Banner.MetadataField>
145
+ ))}
146
+ </>
147
+ </Banner.Metadata>
148
+ )}
149
+ <Copyright copyrightPosition={args.copyrightPosition}>
150
+ <Copyright.Prefix>{args.copyrightPrefix}</Copyright.Prefix>
151
+ <Copyright.Icon>
152
+ <Icon className={args.copyrightIcon} />
153
+ </Copyright.Icon>
154
+ <Copyright.Text>{args.copyright}</Copyright.Text>
155
+ </Copyright>
156
+ </Banner.Content>
157
+ </Banner>
158
+ );
159
+ };
139
160
 
140
161
  export const Default = Template.bind({});
141
162
  Default.args = {
@@ -150,7 +171,8 @@ Default.args = {
150
171
  image: true,
151
172
  hideShareButton: false,
152
173
  hideDownloadButton: false,
174
+ copyrightPrefix: 'Image',
153
175
  copyrightPosition: 'left',
154
176
  copyrightIcon: 'ri-copyright-line',
155
- copyright: 'Image copyright: Velit fusce sed sem ut.',
177
+ copyright: 'John Smith, Well with Nature /EEA',
156
178
  };
@@ -13,6 +13,15 @@ function Copyright({ children, ...rest }) {
13
13
  );
14
14
  }
15
15
 
16
+ Copyright.Prefix = ({ children, ...rest }) =>
17
+ children ? (
18
+ <span {...rest} className={'icon-prefix'}>
19
+ {children}
20
+ </span>
21
+ ) : (
22
+ ''
23
+ );
24
+
16
25
  Copyright.Icon = ({ children, ...rest }) => (
17
26
  <span {...rest} className={'icon-wrapper'}>
18
27
  {children}
@@ -7,7 +7,6 @@ export default {
7
7
  component: Copyright,
8
8
  argTypes: {
9
9
  copyrightPosition: {
10
- name: 'Position',
11
10
  control: {
12
11
  type: 'inline-radio',
13
12
  options: ['left', 'right'],
@@ -24,10 +23,11 @@ export const Default = (args) => (
24
23
  <Container>
25
24
  <Segment className={'inverted'}>
26
25
  <Copyright copyrightPosition={args.copyrightPosition}>
26
+ <Copyright.Prefix>{args.copyrightPrefix}</Copyright.Prefix>
27
27
  <Copyright.Icon>
28
- <Icon className={args.icon} />
28
+ <Icon className={args.copyrightIcon} />
29
29
  </Copyright.Icon>
30
- <Copyright.Text>{args.text}</Copyright.Text>
30
+ <Copyright.Text>{args.copyright}</Copyright.Text>
31
31
  </Copyright>
32
32
  </Segment>
33
33
  </Container>
@@ -35,6 +35,7 @@ export const Default = (args) => (
35
35
 
36
36
  Default.args = {
37
37
  copyrightPosition: 'left',
38
- icon: 'ri-copyright-line',
39
- text: 'Image copyright: Velit fusce sed sem ut.',
38
+ copyrightPrefix: 'Image',
39
+ copyrightIcon: 'ri-copyright-line',
40
+ copyright: 'John Smith, Well with Nature /EEA',
40
41
  };
@@ -1,21 +1,23 @@
1
1
  import React from 'react';
2
- import { Icon } from 'semantic-ui-react';
2
+ import { Grid, Icon } from 'semantic-ui-react';
3
3
  import PropTypes from 'prop-types';
4
4
 
5
5
  const Social = (props) => {
6
6
  if (props.children) {
7
- return <div>{props.children}</div>;
7
+ return <div className="social">{props.children}</div>;
8
8
  }
9
9
 
10
- return (
11
- <div className="social">
12
- {props.social?.map((item, index) => (
13
- <a href={item.link} aria-label={`${item.name} link`} key={index}>
14
- <Icon className={item.icon}></Icon>
15
- </a>
16
- ))}
17
- </div>
18
- );
10
+ return props.social && props.social.length > 0 ? (
11
+ <Grid.Row>
12
+ <div className="social">
13
+ {props.social?.map((item, index) => (
14
+ <a href={item.link} aria-label={`${item.name} link`} key={index}>
15
+ <Icon className={item.icon}></Icon>
16
+ </a>
17
+ ))}
18
+ </div>
19
+ </Grid.Row>
20
+ ) : null;
19
21
  };
20
22
 
21
23
  Social.propTypes = {
@@ -42,9 +42,7 @@ const SubFooter = (props) => {
42
42
 
43
43
  <Footer.Description description={props.description} />
44
44
 
45
- <Grid.Row>
46
- <Footer.Social social={props.social} />
47
- </Grid.Row>
45
+ <Footer.Social social={props.social} />
48
46
 
49
47
  <Grid className="mobile only">
50
48
  {props.managedBy &&
@@ -131,6 +131,7 @@ const Main = ({
131
131
  menuItems,
132
132
  renderMenuItem,
133
133
  renderGlobalMenuItem,
134
+ headerSearchBox,
134
135
  pathname,
135
136
  transparency,
136
137
  inverted,
@@ -321,6 +322,7 @@ const Main = ({
321
322
  onClose={searchOnClick}
322
323
  searchInputRef={searchInputRef}
323
324
  triggerRefs={[searchButtonRef]}
325
+ headerSearchBox={headerSearchBox}
324
326
  />
325
327
  )}
326
328
  <HeaderMenuPopUp
@@ -1245,6 +1245,30 @@ const menuItems = [
1245
1245
  },
1246
1246
  ];
1247
1247
 
1248
+ const headerSearchBox = [
1249
+ {
1250
+ isDefault: true,
1251
+ path: '/en/advanced-search',
1252
+ placeholder: 'Search or ask your question...',
1253
+ description: 'For more search options',
1254
+ buttonTitle: 'Go to advanced search',
1255
+ searchSuggestions: {
1256
+ maxToShow: 6,
1257
+ suggestionsTitle: 'Try our suggestions',
1258
+ suggestions: [
1259
+ 'What is PFAS?',
1260
+ 'Which transport mode has the lowest pollution?',
1261
+ 'Which countries use most renewable energy?',
1262
+ 'How many premature deaths are attributed to PM2.5?',
1263
+ 'How many premature deaths are attributed to air pollution?',
1264
+ 'How much have new cars co2 emissions decreased?',
1265
+ 'What countries had the highest land take in the EEA-39?',
1266
+ 'How many people are exposed to air pollution?',
1267
+ ],
1268
+ },
1269
+ },
1270
+ ];
1271
+
1248
1272
  const debounce = (func) => {
1249
1273
  let timer;
1250
1274
  return (event) => {
@@ -1394,6 +1418,7 @@ const Template = (args) => {
1394
1418
  pathname={pathname}
1395
1419
  logo={<Logo {...logoProps} inverted={args.inverted} />}
1396
1420
  menuItems={menuItems}
1421
+ headerSearchBox={headerSearchBox}
1397
1422
  renderMenuItem={(item, options = {}, props) => {
1398
1423
  const { onClick } = options;
1399
1424
  return (
@@ -1,43 +1,132 @@
1
- import React from 'react';
2
- import { Container, Input } from 'semantic-ui-react';
3
-
1
+ import React, { useEffect } from 'react';
2
+ import { Container, Input, List } from 'semantic-ui-react';
3
+ import { withRouter, Link } from 'react-router-dom';
4
4
  import { useClickOutside } from '@eeacms/volto-eea-design-system/helpers';
5
5
 
6
- function HeaderSearchPopUp({ onClose, searchInputRef, triggerRefs = [] }) {
6
+ const getRandomItems = (arr, max) => {
7
+ return (
8
+ arr?.slice(0, max).map(function () {
9
+ return this.splice(Math.floor(Math.random() * this.length), 1)[0];
10
+ }, arr.slice()) || []
11
+ );
12
+ };
13
+
14
+ function HeaderSearchPopUp({
15
+ history,
16
+ location,
17
+ onClose,
18
+ searchInputRef,
19
+ headerSearchBox,
20
+ triggerRefs = [],
21
+ }) {
7
22
  const nodeRef = React.useRef();
23
+ const headerSearchViews = headerSearchBox || [];
24
+ const defaultView = headerSearchViews.filter((v) => v.isDefault);
25
+ const localView = headerSearchViews.filter((v) =>
26
+ location.pathname.includes(v.path),
27
+ );
28
+ const activeView = localView.length > 0 ? localView[0] : defaultView[0];
29
+
30
+ const {
31
+ path = '',
32
+ buttonTitle,
33
+ description,
34
+ placeholder = 'Search',
35
+ searchSuggestions,
36
+ } = activeView || {};
37
+ const { suggestionsTitle, suggestions, maxToShow } = searchSuggestions || {};
38
+
39
+ const [text, setText] = React.useState('');
40
+ const [visibleSuggestions, setVisibileSuggestions] = React.useState(
41
+ getRandomItems(suggestions, maxToShow),
42
+ );
43
+
44
+ useEffect(() => {
45
+ setVisibileSuggestions(getRandomItems(suggestions, maxToShow));
46
+ }, [maxToShow, suggestions]);
8
47
 
9
48
  useClickOutside({ targetRefs: [nodeRef, ...triggerRefs], callback: onClose });
10
49
 
50
+ const onChangeText = (event, { value }) => {
51
+ setText(value);
52
+ event.preventDefault();
53
+ };
54
+
55
+ const onSubmit = (event) => {
56
+ history.push(`${path}?q=${text}`);
57
+
58
+ if (window?.searchContext?.resetSearch) {
59
+ window.searchContext.resetSearch({ searchTerm: text });
60
+ }
61
+
62
+ onClose();
63
+ event.preventDefault();
64
+ };
65
+
66
+ const onClickHandler = (suggestion) => {
67
+ if (window?.searchContext?.resetSearch) {
68
+ window.searchContext.resetSearch({ searchTerm: suggestion });
69
+ }
70
+
71
+ onClose();
72
+ };
73
+
11
74
  return (
12
75
  <div id="search-box" ref={nodeRef}>
13
76
  <div className="wrapper">
14
77
  <Container>
15
- <form>
78
+ <form method="get" onSubmit={onSubmit}>
16
79
  <Input
17
80
  ref={searchInputRef}
18
81
  className="search"
19
- icon={{ className: 'ri-search-line', link: true }}
20
- placeholder="Search..."
82
+ onChange={onChangeText}
83
+ icon={{
84
+ className: 'ri-search-line',
85
+ link: true,
86
+ onClick: onSubmit,
87
+ }}
88
+ placeholder={placeholder}
21
89
  fluid
22
90
  />
23
91
  </form>
24
- </Container>
92
+ {searchSuggestions && suggestions.length > 0 && (
93
+ <div className="search-suggestions">
94
+ {suggestionsTitle && <h4>{suggestionsTitle}</h4>}
25
95
 
26
- <div className="advanced-search">
27
- <Container>
28
- <div>For more search options</div>
29
- <a
30
- href="/"
31
- className="ui button white inverted"
32
- title="Advanced search"
33
- >
34
- Go to advanced search
35
- </a>
36
- </Container>
37
- </div>
96
+ <List>
97
+ {visibleSuggestions.map((item, i) => {
98
+ return (
99
+ <List.Item key={i}>
100
+ <Link
101
+ to={`${path}?q=${item}`}
102
+ onClick={() => onClickHandler(item)}
103
+ >
104
+ {item}
105
+ </Link>
106
+ </List.Item>
107
+ );
108
+ })}
109
+ </List>
110
+ </div>
111
+ )}
112
+ </Container>
113
+ {buttonTitle && (
114
+ <div className="advanced-search">
115
+ <Container>
116
+ <div>{description}</div>
117
+ <a
118
+ href={defaultView[0].path}
119
+ className="ui button white inverted"
120
+ title="Advanced search"
121
+ >
122
+ {buttonTitle}
123
+ </a>
124
+ </Container>
125
+ </div>
126
+ )}
38
127
  </div>
39
128
  </div>
40
129
  );
41
130
  }
42
131
 
43
- export default HeaderSearchPopUp;
132
+ export default withRouter(HeaderSearchPopUp);
@@ -24,9 +24,9 @@ function Hero({
24
24
  alignContent,
25
25
  backgroundVariant,
26
26
  children,
27
-
28
27
  has_copyright,
29
28
  copyright,
29
+ copyrightPrefix,
30
30
  copyrightIcon,
31
31
  copyrightPosition,
32
32
  }) {
@@ -49,6 +49,7 @@ function Hero({
49
49
 
50
50
  {has_copyright && (
51
51
  <Copyright copyrightPosition={copyrightPosition}>
52
+ <Copyright.Prefix>{copyrightPrefix}</Copyright.Prefix>
52
53
  <Copyright.Icon>
53
54
  <Icon className={copyrightIcon} />
54
55
  </Copyright.Icon>
@@ -63,7 +63,6 @@ export default {
63
63
  },
64
64
  },
65
65
  copyrightPosition: {
66
- name: 'Position',
67
66
  control: {
68
67
  type: 'inline-radio',
69
68
  options: ['left', 'right'],
@@ -74,6 +73,13 @@ export default {
74
73
  defaultValue: { summary: '"left"' },
75
74
  },
76
75
  },
76
+ copyrightPrefix: {
77
+ table: {
78
+ category: 'Copyright',
79
+ defaultValue: { summary: '""' },
80
+ type: { summary: 'string' },
81
+ },
82
+ },
77
83
  copyrightIcon: {
78
84
  table: {
79
85
  category: 'Copyright',
@@ -130,8 +136,9 @@ Default.args = {
130
136
 
131
137
  has_copyright: true,
132
138
  copyrightPosition: 'left',
139
+ copyrightPrefix: 'Image',
133
140
  copyrightIcon: 'ri-copyright-line',
134
- copyright: 'Image copyright: Velit fusce sed sem ut.',
141
+ copyright: 'John Smith, Well with Nature /EEA',
135
142
  };
136
143
  Default.parameters = {
137
144
  controls: {
@@ -167,8 +174,9 @@ Playground.args = {
167
174
 
168
175
  has_copyright: true,
169
176
  copyrightPosition: 'left',
177
+ copyrightPrefix: 'Image',
170
178
  copyrightIcon: 'ri-copyright-line',
171
- copyright: 'Image copyright: Velit fusce sed sem ut.',
179
+ copyright: 'John Smith, Well with Nature /EEA',
172
180
  };
173
181
  Playground.argTypes = {
174
182
  fullWidth: {
@@ -253,6 +261,13 @@ Playground.argTypes = {
253
261
  type: { summary: 'string' },
254
262
  },
255
263
  },
264
+ copyrightPrefix: {
265
+ table: {
266
+ category: 'Copyright',
267
+ defaultValue: { summary: '""' },
268
+ type: { summary: 'string' },
269
+ },
270
+ },
256
271
  copyrightIcon: {
257
272
  table: {
258
273
  category: 'Copyright',
@@ -0,0 +1,135 @@
1
+ /* Simplified popup with several options found in the semantic ui implementation
2
+ * https://github.com/Semantic-Org/Semantic-UI-React/blob/master/src/modules/Popup/Popup.js
3
+ * */
4
+ import React from 'react';
5
+ import { createPopper } from '@popperjs/core';
6
+ import EventStack from '@semantic-ui-react/event-stack';
7
+ import cx from 'classnames';
8
+
9
+ export const positionsMapping = {
10
+ 'top center': 'top',
11
+ 'top left': 'top-start',
12
+ 'top right': 'top-end',
13
+
14
+ 'bottom center': 'bottom',
15
+ 'bottom left': 'bottom-start',
16
+ 'bottom right': 'bottom-end',
17
+
18
+ 'right center': 'right',
19
+ 'left center': 'left',
20
+ };
21
+
22
+ class Popup extends React.Component {
23
+ constructor(props) {
24
+ super(props);
25
+
26
+ this.triggerRef = React.createRef();
27
+ this.popupRef = React.createRef();
28
+
29
+ this.state = {
30
+ isOpen: false,
31
+ };
32
+
33
+ this.togglePopup = this.togglePopup.bind(this);
34
+ this.closeOnEscape = this.closeOnEscape.bind(this);
35
+ }
36
+
37
+ componentDidMount() {
38
+ this.popper = createPopper(this.triggerRef.current, this.popupRef.current, {
39
+ placement: positionsMapping[this.props.position] || 'bottom-end',
40
+ strategy: this.props.positionFixed || 'absolute',
41
+ modifiers: [
42
+ {
43
+ name: 'offset',
44
+ options: {
45
+ offset: this.props.offset,
46
+ },
47
+ },
48
+ ...this.props.popperModifiers,
49
+ ],
50
+ });
51
+ }
52
+
53
+ componentWillUnmount() {
54
+ this.popper && this.popper.destroy();
55
+ }
56
+
57
+ togglePopup() {
58
+ this.setState(
59
+ (state) => {
60
+ return {
61
+ isOpen: !state.isOpen,
62
+ };
63
+ },
64
+ () => {
65
+ this.popper.forceUpdate();
66
+ },
67
+ );
68
+ }
69
+ closeOnEscape(e) {
70
+ if (e.key === 'Escape') {
71
+ this.setState((state) => {
72
+ return {
73
+ isOpen: !state.isOpen,
74
+ };
75
+ });
76
+ }
77
+ }
78
+
79
+ render() {
80
+ const { trigger, className, size, position, basic, content } = this.props;
81
+ const event = this.props.on;
82
+ const onEvent = 'on' + event.charAt(0).toUpperCase() + event.slice(1);
83
+ return (
84
+ <React.Fragment>
85
+ {trigger &&
86
+ React.cloneElement(trigger, {
87
+ [onEvent]: this.togglePopup,
88
+ ref: this.triggerRef,
89
+ })}
90
+
91
+ <div className="popup-container" ref={this.popupRef}>
92
+ {this.state.isOpen && (
93
+ <EventStack name="keydown" on={this.closeOnEscape} />
94
+ )}
95
+ <React.Fragment>
96
+ <div
97
+ className={cx(
98
+ 'ui popup transition',
99
+ className,
100
+ size,
101
+ position,
102
+ basic ? 'basic' : '',
103
+ this.state.isOpen ? 'visible' : '',
104
+ )}
105
+ >
106
+ {content}
107
+ </div>
108
+ </React.Fragment>
109
+ </div>
110
+ </React.Fragment>
111
+ );
112
+ }
113
+ }
114
+
115
+ Popup.defaultProps = {
116
+ position: 'bottom center',
117
+ basic: false,
118
+ size: 'small',
119
+ offset: [0, 0],
120
+ positionFixed: false,
121
+ className: '',
122
+ wide: false,
123
+ on: 'click',
124
+ popperModifiers: [],
125
+ // disabled,
126
+ // flowing,
127
+ // header,
128
+ // inverted,
129
+ // pinned,
130
+ // popper,
131
+ // popperDependencies,
132
+ // style,
133
+ };
134
+
135
+ export default Popup;
@@ -1,5 +1,8 @@
1
1
  import { React } from 'react';
2
- import { Button, Segment, Popup, Image, Icon } from 'semantic-ui-react';
2
+ import { Button, Segment, Image, Icon } from 'semantic-ui-react';
3
+
4
+ import Popup from './Popup';
5
+
3
6
  import EUflag from '@eeacms/volto-eea-design-system/../theme/themes/eea/assets/images/europe-flag.svg';
4
7
 
5
8
  export default {
@@ -135,4 +135,5 @@
135
135
  @import (optional) "@{siteFolder}/@{addon}/@{addontype}s/@{addonelement}.overrides";
136
136
  }
137
137
 
138
+
138
139
  /* End Config */
@@ -109,20 +109,40 @@ body {
109
109
  }
110
110
 
111
111
  /* Hack for escape the blocks container in blocks full width */
112
+ [class~="view-defaultview"] [id="page-document"] > .full-width,
113
+ [class~="view-viewview"] [id="page-document"] > .full-width {
114
+ max-width: initial !important;
115
+ }
116
+
112
117
  .has--size--full:not(.block-editor-columnsBlock),
113
118
  .full-width {
114
119
  position: relative;
120
+ width: calc(100vw - var(--scrollbar-width, @scrollbarWidth)) !important;
115
121
  right: 50%;
116
122
  left: 50%;
117
- width: 100vw !important;
118
123
  max-width: initial !important;
119
- margin-right: -50vw !important;
120
- margin-left: -50vw !important;
124
+ margin-left: calc(-50vw + var(--scrollbar-width, @scrollbarWidth) / 2) !important;
125
+ margin-right: calc(-50vw + var(--scrollbar-width, @scrollbarWidth) / 2) !important;
121
126
  }
122
127
 
123
- [class~="view-defaultview"] [id="page-document"] > .full-width,
124
- [class~="view-viewview"] [id="page-document"] > .full-width {
125
- max-width: initial !important;
128
+ @media only screen and (min-width: @largestMobileScreen) {
129
+ body.has-toolbar {
130
+ .has--size--full:not(.block-editor-columnsBlock),
131
+ .full-width {
132
+ width: calc(100vw - @toolbarWidth - var(--scrollbar-width, @scrollbarWidth)) !important;
133
+ margin-left: calc(-50vw + (@toolbarWidth + var(--scrollbar-width, @scrollbarWidth)) / 2) !important;
134
+ margin-right: calc(-50vw + (@toolbarWidth + var(--scrollbar-width, @scrollbarWidth)) / 2) !important;
135
+ }
136
+ }
137
+
138
+ body.has-toolbar-collapsed {
139
+ .has--size--full:not(.block-editor-columnsBlock),
140
+ .full-width {
141
+ width: calc(100vw - @toolbarWidthMin - var(--scrollbar-width, @scrollbarWidth)) !important;
142
+ margin-left: calc(-50vw + (var(--scrollbar-width, @scrollbarWidth) + @toolbarWidthMin) / 2) !important;
143
+ margin-right: calc(-50vw + (var(--scrollbar-width, @scrollbarWidth) + @toolbarWidthMin) / 2) !important;
144
+ }
145
+ }
126
146
  }
127
147
 
128
148
  .has--size--full:not(.block-editor-columnsBlock) .ui.grid {
@@ -59,7 +59,7 @@
59
59
  align-items: @mobileActionsAlignItems;
60
60
  justify-content: flex-end;
61
61
 
62
- .action {
62
+ > .action {
63
63
  .ui.basic.inverted.button {
64
64
  /* used basic inverted button for minimun overrides on box-shadow and active state background */
65
65
  box-shadow: @bannerActionButtonBoxShadow !important;
@@ -112,6 +112,8 @@
112
112
  .ui.popup.share-popup {
113
113
  padding: @sharePopupPadding;
114
114
  filter: @sharePopupFilter;
115
+ min-width: @sharePopupMinWidth;
116
+ position: initial; // without position initial popper cannot correctly place popup
115
117
 
116
118
  p {
117
119
  font-size: @sharePopupFontSize;
@@ -165,7 +167,7 @@
165
167
  flex-direction: @tabletActionsFlexDirection;
166
168
  align-items: @tabletActionsAlignItems;
167
169
 
168
- .action {
170
+ > .action {
169
171
  min-width: @tabletActionsActionMinWidth;
170
172
 
171
173
  .ui.basic.inverted.button i.icon {
@@ -189,10 +191,12 @@
189
191
 
190
192
  .actions {
191
193
  display: flex;
192
- flex-flow: row;
194
+ flex-flow: row !important;
195
+ justify-content: flex-start !important;
193
196
 
194
197
  .action {
195
198
  display: inherit;
199
+ min-width: 1rem !important;
196
200
  }
197
201
  }
198
202
  }
@@ -79,6 +79,7 @@
79
79
 
80
80
  /* Share Popup */
81
81
  @sharePopupPadding: @tinyGap;
82
+ @sharePopupMinWidth: 80px;
82
83
  @sharePopupFilter: drop-shadow(0px 2px 2px rgba(0, 0, 0, 0.25));
83
84
  @tabletSharePopupMinWidth: 120px;
84
85
  // Text
@@ -14,7 +14,6 @@
14
14
  display: flex;
15
15
  color: @copyrightContentColor;
16
16
  font-size: @copyrightContentFontSize;
17
- min-height: @copyrightMinHeight;
18
17
  align-items: @copyrightAlignItems;
19
18
  line-height: @copyrightLineHeight;
20
19
  gap: @copyrightContentPaddingRight;
@@ -12,8 +12,7 @@
12
12
  @copyrightWrapperPaddingLeft: @rem-space-3;
13
13
  @copyrightWrapperPaddingRight: @rem-space-3;
14
14
  @copyrightWrapperBottom: @rem-space-4;
15
- @copyrightMinHeight: @rem-space-8;
16
- @copyrightAlignItems: center;
15
+ @copyrightAlignItems: start;
17
16
 
18
17
  /* Image block */
19
18
  @floatImageLeftMaxWidth: 50%;
@@ -596,7 +596,6 @@
596
596
  @media only screen and (min-width: @computerBreakpoint) {
597
597
  .eea.header .subsite-logo {
598
598
  position: absolute;
599
- z-index: 1;
600
599
  top: @subsiteLogoTopPosition;
601
600
  left: calc(100% + @subsiteFlexGap);
602
601
  width: 400px;
@@ -780,6 +779,7 @@
780
779
  font-size: @megaMenuGlanceListItemFontSize;
781
780
  font-weight: @megaMenuGlanceListItemFontWeight;
782
781
  }
782
+
783
783
  .list.menu-list {
784
784
  margin-top: @megaMenuGlanceMenuListMarginTop;
785
785
  }
@@ -5,11 +5,14 @@
5
5
  @import '@eeacms/volto-eea-design-system/../theme/themes/eea/globals/utilities';
6
6
 
7
7
  // Accessibility outline on focus-visible for every component
8
- button:focus-visible,
9
8
  *:focus-visible {
10
9
  outline: @focusVisibleOutline;
11
10
  }
12
11
 
12
+ button:focus-visible {
13
+ outline: @focusVisibleOutline !important;
14
+ }
15
+
13
16
  h1, h2, h3, h4, h5, h6 {
14
17
  line-height: @font-lineheight-0;
15
18
  letter-spacing: @font-letterspacing-00;
@@ -58,6 +58,6 @@
58
58
  @grey-1: #F9F9F9;
59
59
  @grey-2: #E6E7E8;
60
60
  @grey-3: #BCBEC0;
61
- @grey-4: #67696b; /* 10% shade of #808285 which passed AA validation on white bg */
61
+ @grey-4: #747678;
62
62
  @grey-5: #323232;
63
63
  @grey-6: #000000;