@eeacms/volto-eea-design-system 1.14.0 → 1.16.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 (39) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/DEVELOP.md +56 -0
  3. package/README.md +18 -0
  4. package/docker-compose.yml +28 -0
  5. package/locales/de/LC_MESSAGES/volto.po +14 -0
  6. package/locales/it/LC_MESSAGES/volto.po +14 -0
  7. package/locales/ro/LC_MESSAGES/volto.po +14 -0
  8. package/locales/volto.pot +16 -0
  9. package/package.json +2 -2
  10. package/src/helpers/eventHandlers.js +6 -0
  11. package/src/helpers/index.js +1 -0
  12. package/src/ui/Accordion/Accordion.stories.js +70 -25
  13. package/src/ui/Banner/Banner.jsx +9 -2
  14. package/src/ui/Card/Card.stories.jsx +57 -32
  15. package/src/ui/Header/Header.jsx +4 -0
  16. package/src/ui/Header/Header.stories.js +26 -4
  17. package/src/ui/Header/HeaderMenuPopUp.js +116 -103
  18. package/src/ui/Header/HeaderSearchPopUp.js +9 -11
  19. package/src/ui/Popup/Popup.jsx +84 -95
  20. package/src/ui/Popup/Popup.stories.jsx +2 -2
  21. package/src/ui/Statistic/Statistic.stories.js +122 -104
  22. package/theme/plugins.js +182 -0
  23. package/theme/themes/eea/elements/input.overrides +20 -7
  24. package/theme/themes/eea/extras/banner.less +0 -1
  25. package/theme/themes/eea/extras/custom.overrides +5 -0
  26. package/theme/themes/eea/extras/header.less +3 -22
  27. package/theme/themes/eea/extras/header.variables +1 -1
  28. package/theme/themes/eea/extras/main.overrides +6 -0
  29. package/theme/themes/eea/extras/tagList.less +1 -1
  30. package/theme/themes/eea/extras/tagList.variables +1 -1
  31. package/theme/themes/eea/globals/site.variables +3 -3
  32. package/theme/themes/eea/globals/utilities.less +9 -0
  33. package/theme/themes/eea/modules/accordion.overrides +44 -42
  34. package/theme/themes/eea/modules/accordion.variables +4 -4
  35. package/theme/themes/eea/modules/popup.overrides +4 -0
  36. package/theme/themes/eea/views/card.overrides +16 -2
  37. package/theme/themes/eea/views/card.variables +1 -0
  38. package/.i18n.babel.config.js +0 -1
  39. /package/src/ui/Hero/{Hero.stories.jsx → Hero.st.jsx} +0 -0
@@ -1,10 +1,19 @@
1
1
  import React from 'react';
2
2
  import { Statistic, Container, Button } from 'semantic-ui-react';
3
- import CountUp, { useCountUp } from 'react-countup';
3
+ import { CountUp, useCountUp } from '@eeacms/countup';
4
4
 
5
5
  export default {
6
6
  title: 'Components/Statistic',
7
7
  component: Statistic,
8
+ args: {
9
+ label: 'Statistic Label',
10
+ value: 'Value',
11
+ size: 'small',
12
+ horizontal: false,
13
+ linked: false,
14
+ inverted: false,
15
+ backgroundVariant: 'primary',
16
+ },
8
17
  argTypes: {
9
18
  size: {
10
19
  control: {
@@ -43,39 +52,65 @@ export default {
43
52
  type: { summary: 'string' },
44
53
  },
45
54
  },
55
+
56
+ label: {
57
+ description: 'label content of the Statistic',
58
+ },
59
+ value: {
60
+ description: 'value content of the statistic',
61
+ },
62
+ inverted: {
63
+ description: 'Is the theme inverted',
64
+ table: {
65
+ type: {
66
+ summary: 'boolean',
67
+ },
68
+ },
69
+ },
70
+ linked: {
71
+ description: 'Add link to statistic',
72
+ table: {
73
+ type: {
74
+ summary: 'boolean',
75
+ },
76
+ },
77
+ },
46
78
  },
47
79
  };
48
80
 
49
- const Template = (args) => (
50
- <div
51
- className={`full-width color-bg-${
52
- args.inverted ? args.backgroundVariant : ''
53
- }`}
54
- >
55
- <Container>
56
- <Statistic.Group {...args}>
57
- {args.elements &&
58
- args.elements.map((element, index) => (
59
- <Statistic
60
- as="a"
61
- href={element.href}
62
- key={index}
63
- {...element}
64
- ></Statistic>
65
- ))}
66
- {!args.elements && (
67
- <>
68
- {args.linked ? (
69
- <Statistic as="a" href="/#" {...args}></Statistic>
70
- ) : (
71
- <Statistic {...args}></Statistic>
72
- )}{' '}
73
- </>
74
- )}
75
- </Statistic.Group>
76
- </Container>
77
- </div>
78
- );
81
+ const Template = (args) => {
82
+ const { backgroundVariant, elements, linked, ...sematicProps } = args;
83
+ return (
84
+ <div
85
+ className={`full-width color-bg-${
86
+ sematicProps.inverted ? backgroundVariant : ''
87
+ }`}
88
+ >
89
+ <Container>
90
+ <Statistic.Group {...sematicProps}>
91
+ {elements &&
92
+ elements.map((element, index) => (
93
+ <Statistic
94
+ as="a"
95
+ href={element.href}
96
+ key={index}
97
+ {...element}
98
+ ></Statistic>
99
+ ))}
100
+ {!elements && (
101
+ <>
102
+ {linked ? (
103
+ <Statistic as="a" href="/#" {...sematicProps}></Statistic>
104
+ ) : (
105
+ <Statistic {...sematicProps}></Statistic>
106
+ )}{' '}
107
+ </>
108
+ )}
109
+ </Statistic.Group>
110
+ </Container>
111
+ </div>
112
+ );
113
+ };
79
114
 
80
115
  export const Default = Template.bind({});
81
116
  Default.args = {
@@ -192,7 +227,7 @@ const CustomTemplate = (args) => (
192
227
  <Container>
193
228
  <Statistic.Group {...args}>
194
229
  {args.elements &&
195
- args.elements.map((element, index) => (
230
+ args.elements.map((element) => (
196
231
  <a href={element.href} className="ui small statistic">
197
232
  <div className={`value ${args.valueVariation}`}>
198
233
  {element.value}
@@ -300,34 +335,62 @@ Custom.argTypes = {
300
335
  ////////////////////////////////// Animation Stories
301
336
 
302
337
  const AnimationTemplate = (args) => {
303
- const { start, reset, pauseResume } = useCountUp({
304
- ref: 'counter',
338
+ const [run, setRun] = React.useState(true);
339
+ const { reset, value } = useCountUp({
305
340
  start: args.start,
306
341
  end: args.end,
307
- delay: args.delay,
308
342
  duration: args.duration,
309
- decimals: args.decimals,
310
- decimal: args.decimal,
311
- prefix: args.prefix,
312
- suffix: args.suffix,
343
+ decimalPlaces: args.decimals,
344
+ decimalSeparator: args.decimal,
345
+ formatter: (value) => {
346
+ let prefix = args.prefix || '';
347
+ let suffix = args.suffix || '';
348
+ let valueFixed = value.toFixed(args.decimals);
349
+
350
+ if (args.decimal === ',')
351
+ return (
352
+ prefix + new Intl.NumberFormat('ro-RO').format(valueFixed) + suffix
353
+ );
354
+ else return prefix + valueFixed + suffix;
355
+ },
356
+ isCounting: run,
357
+ useIntersection: false,
313
358
  });
314
359
 
315
360
  return (
316
361
  <Container>
317
362
  <Statistic.Group {...args}>
318
363
  <a href="/#" className="ui small statistic">
319
- <div className="value secondary" id="counter"></div>
364
+ <div className="value secondary">{value}</div>
320
365
  <div className="label tertiary">Count up label</div>
321
366
  </a>
322
367
  </Statistic.Group>
323
368
  <br />
324
- <Button secondary onClick={start}>
369
+ <Button
370
+ secondary
371
+ onClick={() => {
372
+ reset();
373
+ setRun(true);
374
+ }}
375
+ >
325
376
  Start
326
377
  </Button>
327
- <Button primary onClick={reset}>
378
+ <Button
379
+ primary
380
+ onClick={() => {
381
+ reset();
382
+ setRun(false);
383
+ }}
384
+ >
328
385
  Reset
329
386
  </Button>
330
- <Button primary inverted onClick={pauseResume}>
387
+ <Button
388
+ primary
389
+ inverted
390
+ onClick={() => {
391
+ setRun(!run);
392
+ }}
393
+ >
331
394
  Pause/Resume
332
395
  </Button>
333
396
  </Container>
@@ -335,10 +398,10 @@ const AnimationTemplate = (args) => {
335
398
  };
336
399
 
337
400
  export const Animation = AnimationTemplate.bind({});
401
+
338
402
  Animation.args = {
339
403
  start: 0,
340
404
  end: 5000,
341
- delay: 0,
342
405
  duration: 5,
343
406
  decimals: 0,
344
407
  prefix: '',
@@ -347,9 +410,17 @@ Animation.args = {
347
410
  size: 'small',
348
411
  horizontal: false,
349
412
  };
413
+ Animation.argTypes = {
414
+ decimal: {
415
+ name: 'decimal',
416
+ defaultValue: '.',
417
+ options: ['.', ','],
418
+ control: { type: 'select' },
419
+ },
420
+ };
350
421
  Animation.parameters = { controls: { exclude: ['Background when inverted'] } };
351
422
 
352
- const CountupStatistics = (args) => (
423
+ const CountUpStatistics = (args) => (
353
424
  <div
354
425
  className={`full-width color-bg-${
355
426
  args.inverted ? args.backgroundVariant : ''
@@ -358,10 +429,10 @@ const CountupStatistics = (args) => (
358
429
  <Container>
359
430
  <Statistic.Group id="counter" {...args}>
360
431
  {args.elements &&
361
- args.elements.map((element, index) => (
432
+ args.elements.map((element) => (
362
433
  <a href={element.href} className="ui small statistic">
363
434
  <div className={`value ${args.valueVariation}`}>
364
- <CountUp end={element.value} />
435
+ <CountUp end={element.value} isCounting={true} />
365
436
  </div>
366
437
  <div className={`label ${args.labelVariation}`}>
367
438
  {element.label}
@@ -375,27 +446,27 @@ const CountupStatistics = (args) => (
375
446
  </Container>
376
447
  </div>
377
448
  );
378
- export const AnimationGroup = CountupStatistics.bind({});
449
+ export const AnimationGroup = CountUpStatistics.bind({});
379
450
  AnimationGroup.args = {
380
451
  elements: [
381
452
  {
382
453
  ...Default.args,
383
454
  label: 'label 1',
384
- value: '50',
455
+ value: 50,
385
456
  slate: 'Text from slate',
386
457
  href: '/#',
387
458
  },
388
459
  {
389
460
  ...Default.args,
390
461
  label: 'label 2',
391
- value: '500',
462
+ value: 500,
392
463
  slate: 'Text from slate',
393
464
  href: '/#',
394
465
  },
395
466
  {
396
467
  ...Default.args,
397
468
  label: 'label 3',
398
- value: '5000',
469
+ value: 5000,
399
470
  slate: 'Text from slate',
400
471
  href: '/#',
401
472
  },
@@ -409,56 +480,3 @@ AnimationGroup.args = {
409
480
  inverted: false,
410
481
  backgroundVariant: 'primary',
411
482
  };
412
- AnimationGroup.argTypes = {
413
- widths: {
414
- control: {
415
- type: 'select',
416
- options: ['one', 'two', 'three', 'four', 'five'],
417
- },
418
- description: 'statistic column size',
419
- table: {
420
- type: {
421
- summary: 'string',
422
- },
423
- defaultValue: {
424
- summary: ' "" ',
425
- },
426
- },
427
- },
428
- valueVariation: {
429
- name: 'Value variation',
430
- defaultValue: 'tertiary',
431
- options: ['primary', 'secondary', 'tertiary'],
432
- control: { type: 'select' },
433
- description: 'Text color variation',
434
- table: {
435
- category: 'Color variations',
436
- defaultValue: { summary: 'tertiary' },
437
- type: { summary: 'string' },
438
- },
439
- },
440
- labelVariation: {
441
- name: 'Value variation',
442
- defaultValue: 'tertiary',
443
- options: ['primary', 'secondary', 'tertiary'],
444
- control: { type: 'select' },
445
- description: 'Text color variation',
446
- table: {
447
- category: 'Color variations',
448
- defaultValue: { summary: 'tertiary' },
449
- type: { summary: 'string' },
450
- },
451
- },
452
- extraVariation: {
453
- name: 'Extra info variation',
454
- defaultValue: 'tertiary',
455
- options: ['primary', 'secondary', 'tertiary'],
456
- control: { type: 'select' },
457
- description: 'Text color variation',
458
- table: {
459
- category: 'Color variations',
460
- defaultValue: { summary: 'tertiary' },
461
- type: { summary: 'string' },
462
- },
463
- },
464
- };
package/theme/plugins.js CHANGED
@@ -1,5 +1,187 @@
1
+ function toHSL(color) {
2
+ if (color.toHSL) {
3
+ return color.toHSL();
4
+ } else {
5
+ throw new Error('Argument cannot be evaluated to a color');
6
+ }
7
+ }
8
+
1
9
  module.exports = {
2
10
  install(less, pluginManager, functions) {
11
+ const darken = less.functions.functionRegistry.get('darken');
12
+ const lighten = less.functions.functionRegistry.get('lighten');
13
+ const saturate = less.functions.functionRegistry.get('saturate');
14
+ const desaturate = less.functions.functionRegistry.get('desaturate');
15
+
16
+ functions.add('darken', function (
17
+ color,
18
+ amount = new less.tree.Dimension(0),
19
+ method,
20
+ ) {
21
+ try {
22
+ const hsl = toHSL(color);
23
+
24
+ if (hsl) {
25
+ return darken(color, amount, method);
26
+ }
27
+ } catch (err) {
28
+ if (['hsl', 'hsla'].includes(color.name)) {
29
+ if (amount?.value) {
30
+ color.args[2] = new less.tree.Call('calc', [
31
+ new less.tree.Operation(
32
+ '-',
33
+ [
34
+ color.args[2],
35
+ new less.tree.Dimension(
36
+ amount.value,
37
+ new less.tree.Unit(null, null, '%'),
38
+ ),
39
+ ],
40
+ true,
41
+ ),
42
+ ]);
43
+ }
44
+
45
+ return color;
46
+ } else if (color.name === 'var') {
47
+ if (color.args[1]) {
48
+ color.args[1] = functions.get('darken')(
49
+ color.args[1],
50
+ amount,
51
+ method,
52
+ );
53
+ }
54
+ return color;
55
+ } else {
56
+ throw err;
57
+ }
58
+ }
59
+ });
60
+
61
+ functions.add('lighten', function (color, amount, method) {
62
+ try {
63
+ const hsl = toHSL(color);
64
+
65
+ if (hsl) {
66
+ return lighten(color, amount, method);
67
+ }
68
+ } catch (err) {
69
+ if (['hsl', 'hsla'].includes(color.name)) {
70
+ if (amount?.value) {
71
+ color.args[2] = new less.tree.Call('calc', [
72
+ new less.tree.Operation(
73
+ '+',
74
+ [
75
+ color.args[2],
76
+ new less.tree.Dimension(
77
+ amount.value,
78
+ new less.tree.Unit(null, null, '%'),
79
+ ),
80
+ ],
81
+ true,
82
+ ),
83
+ ]);
84
+ }
85
+
86
+ return color;
87
+ } else if (color.name === 'var') {
88
+ if (color.args[1]) {
89
+ color.args[1] = functions.get('lighten')(
90
+ color.args[1],
91
+ amount,
92
+ method,
93
+ );
94
+ }
95
+ return color;
96
+ } else {
97
+ throw err;
98
+ }
99
+ }
100
+ });
101
+
102
+ functions.add('saturate', function (color, amount, method) {
103
+ try {
104
+ const hsl = toHSL(color);
105
+
106
+ if (hsl) {
107
+ return saturate(color, amount, method);
108
+ }
109
+ } catch (err) {
110
+ if (['hsl', 'hsla'].includes(color.name)) {
111
+ if (amount?.value) {
112
+ color.args[1] = new less.tree.Call('calc', [
113
+ new less.tree.Operation(
114
+ '+',
115
+ [
116
+ color.args[1],
117
+ new less.tree.Dimension(
118
+ amount.value,
119
+ new less.tree.Unit(null, null, '%'),
120
+ ),
121
+ ],
122
+ true,
123
+ ),
124
+ ]);
125
+ }
126
+
127
+ return color;
128
+ } else if (!color.rgb || color.name === 'var') {
129
+ if (color.name === 'var' && color.args[1]) {
130
+ color.args[1] = functions.get('saturate')(
131
+ color.args[1],
132
+ amount,
133
+ method,
134
+ );
135
+ return color;
136
+ }
137
+ return null;
138
+ } else {
139
+ throw err;
140
+ }
141
+ }
142
+ });
143
+
144
+ functions.add('desaturate', function (color, amount, method) {
145
+ try {
146
+ const hsl = toHSL(color);
147
+
148
+ if (hsl) {
149
+ return desaturate(color, amount, method);
150
+ }
151
+ } catch (err) {
152
+ if (['hsl', 'hsla'].includes(color.name)) {
153
+ if (amount?.value) {
154
+ color.args[1] = new less.tree.Call('calc', [
155
+ new less.tree.Operation(
156
+ '-',
157
+ [
158
+ color.args[1],
159
+ new less.tree.Dimension(
160
+ amount.value,
161
+ new less.tree.Unit(null, null, '%'),
162
+ ),
163
+ ],
164
+ true,
165
+ ),
166
+ ]);
167
+ }
168
+
169
+ return color;
170
+ } else if (color.name === 'var') {
171
+ if (color.args[1]) {
172
+ color.args[1] = functions.get('desaturate')(
173
+ color.args[1],
174
+ amount,
175
+ method,
176
+ );
177
+ }
178
+ return color;
179
+ } else {
180
+ throw err;
181
+ }
182
+ }
183
+ });
184
+
3
185
  functions.add('vw', function (percentage) {
4
186
  return new less.tree.Call('calc', [
5
187
  new less.tree.Operation(
@@ -81,13 +81,14 @@
81
81
  .accordion-title:not(.active) .ui.input input {
82
82
  color: @textColorCSSVar;
83
83
  }
84
+
84
85
  .ui.input input {
85
86
  border: @border;
86
87
 
87
88
  &:active,
88
89
  &:focus {
89
90
  border: @borderWidth solid @secondaryColor;
90
- color: @textColor;
91
+ color: @textColorCSSVar;
91
92
  }
92
93
  }
93
94
 
@@ -121,7 +122,19 @@ textarea.fluid {
121
122
  font-weight: @bold;
122
123
  }
123
124
 
124
- i.icon {
125
+ .icon {
126
+ position: absolute;
127
+ top: 0;
128
+ right: 0;
129
+ height: 100%;
130
+ margin: 0;
131
+ background-color: transparent !important;
132
+ box-shadow: none !important;
133
+ line-height: 1;
134
+ text-align: center;
135
+ }
136
+
137
+ .icon:before {
125
138
  color: @white;
126
139
  font-size: 16px;
127
140
  opacity: 1;
@@ -129,18 +142,18 @@ textarea.fluid {
129
142
  }
130
143
 
131
144
  .ui.fluid.icon.input.search > input::-webkit-input-placeholder {
132
- opacity: 0.9;
133
145
  color: rgb(255, 255, 255);
146
+ opacity: 0.9;
134
147
  }
135
148
 
136
149
  .ui.fluid.icon.input.search > input::-moz-placeholder {
137
- opacity: 0.9;
138
150
  color: rgb(255, 255, 255);
151
+ opacity: 0.9;
139
152
  }
140
153
 
141
154
  .ui.fluid.icon.input.search > input::-ms-input-placeholder {
142
- opacity: 0.9;
143
155
  color: rgb(255, 255, 255);
156
+ opacity: 0.9;
144
157
  }
145
158
 
146
159
  @media only screen and (min-width: @tabletBreakpoint) {
@@ -150,7 +163,7 @@ textarea.fluid {
150
163
  font-size: 18px;
151
164
  }
152
165
 
153
- i.icon {
166
+ .icon:before {
154
167
  font-size: 18px;
155
168
  }
156
169
  }
@@ -164,7 +177,7 @@ textarea.fluid {
164
177
  font-size: 40px;
165
178
  }
166
179
 
167
- i.icon {
180
+ .icon:before {
168
181
  font-size: 38px;
169
182
  }
170
183
  }
@@ -110,7 +110,6 @@
110
110
  /*Share Popup*/
111
111
 
112
112
  .ui.popup.share-popup {
113
- position: initial; // without position initial popper cannot correctly place popup
114
113
  min-width: @sharePopupMinWidth;
115
114
  padding: @sharePopupPadding;
116
115
  filter: @sharePopupFilter;
@@ -127,6 +127,11 @@
127
127
  color: inherit;
128
128
  }
129
129
 
130
+ .quanta-block-editor-teaserGrid .teaserGrid .toolbar {
131
+ top: 0px;
132
+ margin: 5px;
133
+ }
134
+
130
135
  // Tabs block border left/top
131
136
  .tabs-block {
132
137
  .border-left {
@@ -747,6 +747,7 @@
747
747
 
748
748
  #mega-menu .ui.list {
749
749
  margin: 0;
750
+ gap: @megaMenuListGap;
750
751
  }
751
752
 
752
753
  #mega-menu .item {
@@ -770,7 +771,7 @@
770
771
  }
771
772
  }
772
773
 
773
- #at-a-glance {
774
+ .at-a-glance {
774
775
  .item {
775
776
  margin: @megaMenuGlanceListItemMargin;
776
777
  font-size: @megaMenuGlanceListItemFontSize;
@@ -782,30 +783,10 @@
782
783
  }
783
784
  }
784
785
 
785
- // add negative margin to the first column subtitle from nested grid
786
- // so that the subtitle lines up with the subtitle from the left column
787
- #mega-menu .nested-grid > .column:first-of-type .sub-title {
788
- margin-top: @megaMenuSubTitleCountriesNestedGridMarginTop;
789
- }
790
-
791
- #topics-right-column {
786
+ .topics-right-column {
792
787
  padding-left: @topicsRightColumnPaddingLeft;
793
788
  }
794
789
 
795
- .ui.grid > .column > .ui.grid {
796
- margin-top: 0;
797
- }
798
-
799
- #mega-menu .ui.grid {
800
- div.column:first-child {
801
- padding-left: 0.625rem;
802
- }
803
-
804
- div.column:last-child {
805
- padding-right: 0.625rem;
806
- }
807
- }
808
-
809
790
  #mega-menu .active:not(.title-link):not(.button) > span {
810
791
  padding-left: @megaMenuListItemActivePadding;
811
792
  border-left: @megaMenuListItemActiveBorder;
@@ -182,9 +182,9 @@
182
182
  @megaMenuSubTitleFontWeight: @font-weight-7;
183
183
  @megaMenuSubTitlePadding: 0.5rem 0;
184
184
  @megaMenuSubTitleDisplay: block;
185
- @megaMenuSubTitleCountriesNestedGridMarginTop: -1rem;
186
185
 
187
186
  /* List Item */
187
+ @megaMenuListGap: 0 2rem;
188
188
  @megaMenuListItemFontSize: @font-size-1;
189
189
  @megaMenuListItemFontWeight: @font-weight-4;
190
190
  @megaMenuListItemPadding: @rem-space-2 0;
@@ -38,3 +38,9 @@
38
38
  #main main {
39
39
  overflow: inherit;
40
40
  }
41
+
42
+ // with z-index: -1 you don't get the hover and focused border for block child section
43
+ // TODO: to be removed if https://github.com/plone/volto/pull/5029 merged
44
+ .block .block:not(.inner)::before {
45
+ z-index: auto;
46
+ }
@@ -34,7 +34,7 @@
34
34
 
35
35
  .tags-content {
36
36
  gap: @tagsContentGap;
37
- display: flex;
37
+ display: flex !important;
38
38
  flex-wrap: wrap;
39
39
  }
40
40