@ons/design-system 67.0.5 → 67.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/components/access-code/example-access-code-error.njk +6 -9
  2. package/components/access-code/example-access-code.njk +7 -10
  3. package/components/date-field-input/_macro.njk +86 -0
  4. package/components/date-input/_macro.njk +79 -115
  5. package/components/{metadata/_metadata.scss → description-list/_description-list.scss} +2 -2
  6. package/components/description-list/_macro.njk +14 -0
  7. package/components/{metadata → description-list}/_macro.spec.js +26 -26
  8. package/components/{metadata/example-metadata.njk → description-list/example-description-list.njk} +3 -3
  9. package/components/duration/_macro.njk +60 -85
  10. package/components/header/_header.scss +8 -0
  11. package/components/header/_macro.njk +59 -35
  12. package/components/header/_macro.spec.js +115 -0
  13. package/components/header/example-header-multiple-logos.njk +110 -0
  14. package/components/metadata/_macro.njk +12 -12
  15. package/components/navigation/_navigation.scss +4 -2
  16. package/components/summary/_summary.scss +1 -1
  17. package/css/main.css +1 -1
  18. package/css/print.css +1 -1
  19. package/package.json +2 -5
  20. package/scss/main.scss +1 -1
  21. package/scss/utilities/_margin.scss +1 -0
  22. /package/{scss/fonts → fonts}/opensans-bold.woff +0 -0
  23. /package/{scss/fonts → fonts}/opensans-bold.woff2 +0 -0
  24. /package/{scss/fonts → fonts}/opensans-regular.woff +0 -0
  25. /package/{scss/fonts → fonts}/opensans-regular.woff2 +0 -0
  26. /package/{scss/fonts → fonts}/robotomono-bold.woff +0 -0
  27. /package/{scss/fonts → fonts}/robotomono-bold.woff2 +0 -0
  28. /package/{scss/fonts → fonts}/robotomono-regular.woff +0 -0
  29. /package/{scss/fonts → fonts}/robotomono-regular.woff2 +0 -0
@@ -1,12 +1,7 @@
1
-
2
- {% from "components/mutually-exclusive/_macro.njk" import onsMutuallyExclusive %}
3
- {% from "components/fieldset/_macro.njk" import onsFieldset %}
4
- {% from "components/field/_macro.njk" import onsField %}
5
- {% from "components/input/_macro.njk" import onsInput %}
1
+ {% from "components/date-field-input/_macro.njk" import onsDateFieldInput %}
6
2
 
7
3
  {% macro onsDuration(params) %}
8
4
  {% set numberOfFields = 0 %}
9
-
10
5
  {% if params.field1 %}
11
6
  {% set numberOfFields = numberOfFields + 1 %}
12
7
  {% endif %}
@@ -15,85 +10,65 @@
15
10
  {% set numberOfFields = numberOfFields + 1 %}
16
11
  {% endif %}
17
12
 
18
- {% set fields %}
19
- {% if params.field1 %}
20
- {{ onsInput({
21
- "id": params.field1.id,
22
- "classes": (" ons-input--error" if (params.error and params.field1.error) or (numberOfFields > 1 and params.error and not params.field1.error and not params.field2.error) else "") + (" ons-js-exclusive-group-item" if params.mutuallyExclusive else ""),
23
- "width": "2",
24
- "type": "number",
25
- "name": params.field1.name,
26
- "value": params.field1.value,
27
- "suffix": {
28
- "text": params.field1.suffix.text,
29
- "title": params.field1.suffix.title,
30
- "id": params.field1.suffix.id
31
- },
32
- "label": {
33
- "text": params.legendOrLabel if numberOfFields < 2,
34
- "description": params.description if numberOfFields < 2
35
- },
36
- "attributes": params.field1.attributes,
37
- "fieldId": params.id if numberOfFields < 2,
38
- "error": params.error if numberOfFields < 2
39
- }) }}
40
- {% endif %}
41
-
42
- {% if params.field2 %}
43
- {{ onsInput({
44
- "id": params.field2.id,
45
- "classes": (" ons-input--error" if (params.error and params.field2.error) or (numberOfFields > 1 and params.error and not params.field1.error and not params.field2.error) else "") + (" ons-js-exclusive-group-item" if params.mutuallyExclusive else ""),
46
- "width": "2",
47
- "type": "number",
48
- "name": params.field2.name,
49
- "value": params.field2.value,
50
- "suffix": {
51
- "text": params.field2.suffix.text,
52
- "title": params.field2.suffix.title,
53
- "id": params.field2.suffix.id
54
- },
55
- "label": {
56
- "text": params.legendOrLabel if numberOfFields < 2,
57
- "description": params.description if numberOfFields < 2
58
- },
59
- "attributes": params.field2.attributes,
60
- "fieldId": params.id if numberOfFields < 2,
61
- "error": params.error if numberOfFields < 2
62
- }) }}
63
- {% endif %}
64
- {% endset %}
65
-
66
- {% if params.mutuallyExclusive %}
67
- {% set mutuallyExclusive = params.mutuallyExclusive | setAttributes({
68
- "id": params.id,
69
- "legend": params.legendOrLabel,
70
- "legendClasses": params.legendClasses,
71
- "description": params.description,
72
- "error": params.error,
73
- "legendIsQuestionTitle": params.legendIsQuestionTitle,
74
- "dontWrap": params.dontWrap
75
- }) %}
13
+ {% set fields = [] %}
14
+ {% if params.field1 %}
15
+ {% set field1 = {
16
+ "id": params.field1.id,
17
+ "name": params.field1.name,
18
+ "attributes": params.field1.attributes,
19
+ "label": {
20
+ "text": params.legendOrLabel if numberOfFields < 2,
21
+ "description": params.description if numberOfFields < 2
22
+ },
23
+ "suffix": {
24
+ "text": params.field1.suffix.text,
25
+ "title": params.field1.suffix.title,
26
+ "id": params.field1.suffix.id
27
+ },
28
+ "width": "2",
29
+ "fieldId": params.id if numberOfFields < 2,
30
+ "value": params.field1.value,
31
+ "error": params.error if numberOfFields < 2,
32
+ "classes": (" ons-input--error" if (params.error and params.field1.error) or (params.error and not params.field1.error and not params.field2.error) else "") + (" ons-js-exclusive-group-item" if params.mutuallyExclusive else "")
33
+ } %}
34
+ {% set fields = (fields.push(field1), fields) %}
35
+ {% endif %}
76
36
 
77
- {% call onsMutuallyExclusive(mutuallyExclusive) %}
78
- <div class="ons-field-group">
79
- {{ fields | safe }}
80
- </div>
81
- {% endcall %}
82
- {% elif numberOfFields > 1 %}
83
- {% call onsFieldset({
84
- "id": params.id,
85
- "legend": params.legendOrLabel,
86
- "description": params.description,
87
- "legendClasses": params.legendClasses,
88
- "error": params.error,
89
- "legendIsQuestionTitle": params.legendIsQuestionTitle,
90
- "dontWrap": params.dontWrap
91
- }) %}
92
- <div class="ons-field-group">
93
- {{ fields | safe }}
94
- </div>
95
- {% endcall %}
96
- {% else %}
97
- {{ fields | safe }}
37
+ {% if params.field2 %}
38
+ {% set field2 = {
39
+ "id": params.field2.id,
40
+ "name": params.field2.name,
41
+ "attributes": params.field2.attributes,
42
+ "width": "2",
43
+ "label": {
44
+ "text": params.legendOrLabel if numberOfFields < 2,
45
+ "description": params.description if numberOfFields < 2
46
+ },
47
+ "suffix": {
48
+ "text": params.field2.suffix.text,
49
+ "title": params.field2.suffix.title,
50
+ "id": params.field2.suffix.id
51
+ },
52
+ "value": params.field2.value,
53
+ "error": params.error if numberOfFields < 2,
54
+ "fieldId": params.id if numberOfFields < 2,
55
+ "classes": (" ons-input--error" if (params.error and params.field2.error) or (params.error and not params.field1.error and not params.field2.error) else "") + (" ons-js-exclusive-group-item" if params.mutuallyExclusive else "")
56
+ } %}
57
+ {% set fields = (fields.push(field2), fields) %}
98
58
  {% endif %}
59
+
60
+ {{ onsDateFieldInput({
61
+ "id": params.id,
62
+ "legendOrLabel": params.legendOrLabel,
63
+ "description": params.description,
64
+ "mutuallyExclusive": params.mutuallyExclusive,
65
+ "numberOfFields": numberOfFields,
66
+ "fields": fields,
67
+ "error": params.error,
68
+ "legend": params.legendOrLabel,
69
+ "dontWrap": params.dontWrap,
70
+ "classes": params.classes,
71
+ "legendClasses": params.legendClasses,
72
+ "legendIsQuestionTitle": params.legendIsQuestionTitle
73
+ }) }}
99
74
  {% endmacro %}
@@ -13,6 +13,7 @@
13
13
  }
14
14
  &__grid-top {
15
15
  padding: 1rem 0;
16
+ row-gap: 0.5rem;
16
17
 
17
18
  @include mq(xs) {
18
19
  padding: 0.75rem 0;
@@ -142,6 +143,7 @@
142
143
 
143
144
  .ons-icon--logo {
144
145
  display: block;
146
+ width: 100%;
145
147
  }
146
148
 
147
149
  &__org-logo-link,
@@ -176,6 +178,12 @@
176
178
  }
177
179
  }
178
180
 
181
+ &__org-logo--multi {
182
+ display: inline-flex;
183
+ column-gap: 1rem;
184
+ align-items: center;
185
+ }
186
+
179
187
  &-service-nav {
180
188
  display: inline-block;
181
189
 
@@ -32,45 +32,69 @@
32
32
  {% endif %}
33
33
  <div class="ons-header__top">
34
34
  <div class="ons-container{{ ' ons-container--full-width' if params.fullWidth }}{{ ' ons-container--wide' if params.wide }}">
35
- <div class="ons-header__grid-top ons-grid ons-grid--gutterless ons-grid--flex ons-grid--between ons-grid--vertical-center ons-grid--no-wrap{% if params.mastheadLogo.classes %} {{ params.mastheadLogo.classes }}{% endif %}">
35
+ <div class="ons-header__grid-top ons-grid ons-grid--flex ons-grid--between ons-grid--vertical-center{% if params.mastheadLogo.classes %} {{ params.mastheadLogo.classes }}{% endif %}{% if not params.mastheadLogo.multipleLogos %} ons-grid--no-wrap ons-grid--gutterless{% endif%}">
36
36
  <div class="ons-grid__col ons-col-auto">
37
- {%-if params.mastheadLogoUrl %}
38
- <a class="ons-header__org-logo-link" href="{{ params.mastheadLogoUrl }}">
39
- {% endif -%}
40
- <div class="ons-header__org-logo ons-header__org-logo--large">
41
- {% if params.mastheadLogo.large %}
42
- {{ params.mastheadLogo.large | safe }}
43
- {% else %}
44
- {{-
45
- onsIcon({
46
- "iconType": 'ons-logo-' + currentLanguageISOCode,
47
- "altText": 'Office for National Statistics logo'
48
- })
49
- -}}
50
- {% endif %}
51
- </div>
52
- <div class="ons-header__org-logo ons-header__org-logo--small">
53
- {% if params.mastheadLogo.small %}
54
- {{ params.mastheadLogo.small | safe }}
55
- {% elif params.mastheadLogo.large %}
56
- {{ params.mastheadLogo.large | safe }}
57
- {% else %}
58
- {{-
59
- onsIcon({
60
- "iconType": 'ons-logo-stacked-' + currentLanguageISOCode,
61
- "altText": 'Office for National Statistics logo'
62
- })
63
- -}}
37
+ {%- if not params.mastheadLogo.multipleLogos %}
38
+ {%-if params.mastheadLogoUrl %}
39
+ <a class="ons-header__org-logo-link" href="{{ params.mastheadLogoUrl }}">
40
+ {% endif -%}
41
+ <div class="ons-header__org-logo ons-header__org-logo--large">
42
+ {% if params.mastheadLogo.large %}
43
+ {{ params.mastheadLogo.large | safe }}
44
+ {% else %}
45
+ {{-
46
+ onsIcon({
47
+ "iconType": 'ons-logo-' + currentLanguageISOCode,
48
+ "altText": 'Office for National Statistics logo'
49
+ })
50
+ -}}
51
+ {% endif %}
52
+ </div>
53
+ <div class="ons-header__org-logo ons-header__org-logo--small">
54
+ {% if params.mastheadLogo.small %}
55
+ {{ params.mastheadLogo.small | safe }}
56
+ {% elif params.mastheadLogo.large %}
57
+ {{ params.mastheadLogo.large | safe }}
58
+ {% else %}
59
+ {{-
60
+ onsIcon({
61
+ "iconType": 'ons-logo-stacked-' + currentLanguageISOCode,
62
+ "altText": 'Office for National Statistics logo'
63
+ })
64
+ -}}
65
+ {% endif %}
66
+ </div>
67
+ {% if params.mastheadLogoUrl %}
68
+ </a>
64
69
  {% endif %}
65
- </div>
66
- {% if params.mastheadLogoUrl %}
67
- </a>
68
- {% endif %}
70
+ {% else %}
71
+ <div class="ons-header__org-logo ons-header__org-logo--multi">
72
+ {% set logos = [params.mastheadLogo.multipleLogos.logo1, params.mastheadLogo.multipleLogos.logo2, params.mastheadLogo.multipleLogos.logo3] %}
73
+ {% for logo in logos %}
74
+ {% if logo.logoURL %}
75
+ <a class="ons-header__org-logo-link" href="{{ logo.logoURL }}">
76
+ {% endif %}
77
+ {% if logo.logoImage != "ONS Logo" %}
78
+ {{ logo.logoImage | safe }}
79
+ {% else %}
80
+ {{-
81
+ onsIcon({
82
+ "iconType": 'ons-logo-stacked-' + currentLanguageISOCode,
83
+ "altText": 'Office for National Statistics logo'
84
+ })
85
+ -}}
86
+ {% endif %}
87
+ {% if logo.logoURL %}
88
+ </a>
89
+ {% endif %}
90
+ {% endfor %}
91
+ </div>
92
+ {% endif -%}
69
93
  </div>
70
94
  {% if params.language or params.serviceLinks %}
71
- <div class="ons-header__links ons-grid__col ons-col-auto">
95
+ <div class="ons-header__links ons-grid__col ons-u-ml-auto">
72
96
  {% if params.language %}
73
- <div class="ons-grid__col ons-col-auto {{ ' ons-u-mr-s ons-u-d-no@xxs@xs' if params.serviceLinks else '' }}">
97
+ <div class="ons-grid__col ons-col-auto{{ ' ons-u-mr-s ons-u-d-no@xxs@xs' if params.serviceLinks else '' }}">
74
98
  {% from "components/language-selector/_macro.njk" import onsLanguageSelector %}
75
99
  {{ onsLanguageSelector(params.language) }}
76
100
  </div>
@@ -169,7 +193,7 @@
169
193
  </div>
170
194
  <div class="ons-header__main">
171
195
  <div class="ons-container{{ ' ons-container--full-width' if params.fullWidth }}{{ ' ons-container--wide' if params.wide }}">
172
- <div class="ons-grid ons-grid--gutterless ons-grid--flex ons-grid--between ons-grid--vertical-center ons-grid--no-wrap">
196
+ <div class="ons-grid{{ ' ons-grid--gutterless' if not params.button }} ons-grid--flex ons-grid--between ons-grid--vertical-center ons-grid--no-wrap">
173
197
  <div class="ons-grid__col ons-col-auto ons-u-flex-shrink">
174
198
  {% if params.titleLogo.large %}
175
199
  {% if params.titleUrl %}
@@ -318,6 +318,93 @@ describe('macro: header', () => {
318
318
  expect($('.ons-header__org-logo--small img').attr('src')).toBe('another-logo-small.svg');
319
319
  });
320
320
 
321
+ describe('mode: with multiple logos', () => {
322
+ it('has the default ONS icon when requested', () => {
323
+ const faker = templateFaker();
324
+ const iconsSpy = faker.spy('icon');
325
+
326
+ faker.renderComponent('header', {
327
+ ...EXAMPLE_HEADER_BASIC,
328
+ mastheadLogo: {
329
+ multipleLogos: {
330
+ logo1: {
331
+ logoImage: 'ONS Logo',
332
+ },
333
+ },
334
+ },
335
+ });
336
+ expect(iconsSpy.occurrences[0].iconType).toBe('ons-logo-stacked-en');
337
+ });
338
+
339
+ it('has the provided link', () => {
340
+ const $ = cheerio.load(
341
+ renderComponent('header', {
342
+ ...EXAMPLE_HEADER_BASIC,
343
+ mastheadLogo: {
344
+ multipleLogos: {
345
+ logo1: {
346
+ logoImage: '<img src="a-logo.svg">',
347
+ logoURL: '#0',
348
+ },
349
+ },
350
+ },
351
+ }),
352
+ );
353
+
354
+ expect($('.ons-header__org-logo-link').attr('href')).toBe('#0');
355
+ });
356
+
357
+ it('when multiple images are provided all show', () => {
358
+ const $ = cheerio.load(
359
+ renderComponent('header', {
360
+ ...EXAMPLE_HEADER_BASIC,
361
+ mastheadLogo: {
362
+ multipleLogos: {
363
+ logo1: {
364
+ logoImage: '<img src="a-logo.svg">',
365
+ },
366
+ logo2: {
367
+ logoImage: '<img src="a-second-logo.svg">',
368
+ },
369
+ logo3: {
370
+ logoImage: '<img src="a-third-logo.svg">',
371
+ },
372
+ },
373
+ },
374
+ }),
375
+ );
376
+
377
+ expect($('.ons-header__org-logo--multi img').attr('src')).toBe('a-logo.svg');
378
+ expect($('.ons-header__org-logo--multi img:nth-of-type(2)').attr('src')).toBe('a-second-logo.svg');
379
+ expect($('.ons-header__org-logo--multi img:nth-of-type(3)').attr('src')).toBe('a-third-logo.svg');
380
+ });
381
+
382
+ it('renders multiple logos even when small/large parameters are used', () => {
383
+ const $ = cheerio.load(
384
+ renderComponent('header', {
385
+ ...EXAMPLE_HEADER_BASIC,
386
+ mastheadLogo: {
387
+ small: '<img src="small-logo.svg">',
388
+ large: '<img src="big-logo.svg">',
389
+ multipleLogos: {
390
+ logo1: {
391
+ logoImage: '<img src="a-logo.svg">',
392
+ },
393
+ logo2: {
394
+ logoImage: '<img src="a-second-logo.svg">',
395
+ },
396
+ logo3: {
397
+ logoImage: '<img src="a-third-logo.svg">',
398
+ },
399
+ },
400
+ },
401
+ }),
402
+ );
403
+ expect($('.ons-header__org-logo--large').attr('src')).toBe(undefined);
404
+ expect($('.ons-header__org-logo--multi img').attr('src')).toBe('a-logo.svg');
405
+ });
406
+ });
407
+
321
408
  it('displays the `title` text', () => {
322
409
  const $ = cheerio.load(renderComponent('header', EXAMPLE_HEADER_BASIC));
323
410
 
@@ -407,6 +494,34 @@ describe('macro: header', () => {
407
494
  });
408
495
  });
409
496
 
497
+ it('has gutterless class if there is no button present', () => {
498
+ const $ = cheerio.load(
499
+ renderComponent('header', {
500
+ ...EXAMPLE_HEADER_BASIC,
501
+ }),
502
+ );
503
+
504
+ const titleGridDiv = $('.ons-header__main .ons-container .ons-grid');
505
+ expect($(titleGridDiv).hasClass('ons-grid--gutterless')).toBe(true);
506
+ });
507
+
508
+ it('has does not have gutterless class if there is a button present', () => {
509
+ const $ = cheerio.load(
510
+ renderComponent('header', {
511
+ ...EXAMPLE_HEADER_BASIC,
512
+ button: {
513
+ text: 'Save and sign out',
514
+ url: '#0',
515
+ iconType: 'exit',
516
+ iconPosition: 'after',
517
+ },
518
+ }),
519
+ );
520
+
521
+ const titleGridDiv = $('.ons-header__main .ons-container .ons-grid');
522
+ expect($(titleGridDiv).hasClass('ons-grid--gutterless')).toBe(false);
523
+ });
524
+
410
525
  it('renders the phase banner with expected parameters', () => {
411
526
  const faker = templateFaker();
412
527
  const phaseSpy = faker.spy('phase-banner');