@ons/design-system 73.2.0 → 73.3.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.
@@ -254,6 +254,8 @@
254
254
 
255
255
  #{$root}__menu-links {
256
256
  width: 100%;
257
+ display: flex;
258
+ align-items: center;
257
259
 
258
260
  #{$root}__language {
259
261
  display: block;
@@ -327,13 +329,11 @@
327
329
 
328
330
  // updates styles when js is enabled
329
331
  .ons-js-enabled & {
330
- position: absolute;
331
- top: 100%;
332
+ position: relative;
332
333
  left: 50%;
333
334
  width: 100vw;
334
335
  transform: translateX(-50%);
335
336
  border-top: 0;
336
- z-index: 500;
337
337
  }
338
338
  }
339
339
 
@@ -135,87 +135,6 @@
135
135
  </div>
136
136
  {% endif %}
137
137
 
138
- {% if params.variants == "basic" and params.menuLinks %}
139
- <nav
140
- class="ons-js-nav-menu ons-header-nav-menu ons-u-pt-2xl"
141
- id="{{ params.menuLinks.id }}"
142
- aria-label="{{ params.menuLinks.ariaLabel | default("Menu navigation") }}"
143
- aria-hidden="false"
144
- >
145
- {% if params.menuLinks.keyLinks %}
146
- <div class="ons-container">
147
- <ul class="ons-grid ons-header-nav-menu__key-list">
148
- {% for keyLink in params.menuLinks.keyLinks %}
149
- {% if keyLink.heading %}
150
- <li class="ons-grid__col ons-col-4@m ons-header-nav-menu__col">
151
- <h2 class="ons-u-fs-s--b ons-u-mb-no ons-header-nav-menu__heading">
152
- {% if keyLink.url %}
153
- <a href="{{ keyLink.url }}" class="ons-header-nav-menu__link"
154
- >{{ keyLink.heading }}</a
155
- >
156
- {% else %}
157
- {{ keyLink.heading }}
158
- {% endif %}
159
- </h2>
160
- {% if keyLink.description %}
161
- <p class="ons-u-fs-s ons-u-mb-no ons-header-nav-menu__description">
162
- {{ keyLink.description }}
163
- </p>
164
- {% endif %}
165
- </li>
166
- {% endif %}
167
- {% endfor %}
168
- </ul>
169
- </div>
170
- {% endif %}
171
- {% if params.menuLinks.columns %}
172
- <div class="ons-container">
173
- <ul class="ons-grid ons-list ons-list--bare">
174
- {% for column in params.menuLinks.columns %}
175
- <li class="ons-grid__col ons-col-4@m ons-u-mb-no ons-header-nav-menu__col">
176
- {% for group in column.groups %}
177
- {% if group.heading %}
178
- <h2 class="ons-u-fs-s--b ons-header-nav-menu__heading">
179
- {% if group.url %}
180
- <a href="{{ group.url }}" class="ons-header-nav-menu__link"
181
- >{{ group.heading }}</a
182
- >
183
- {% else %}
184
- {{ group.heading }}
185
- {% endif %}
186
- </h2>
187
- {% endif %}
188
- {% if group.groupItems %}
189
- <ul class="ons-list ons-list--bare ons-header-nav-menu__groupItem-list">
190
- {% for groupItem in group.groupItems %}
191
- {% if groupItem.text %}
192
- <li class="ons-u-mb-no">
193
- <p class="ons-u-fs-s ons-header-nav-menu_text">
194
- {% if groupItem.url %}
195
- <a
196
- href="{{ groupItem.url }}"
197
- class="ons-header-nav-menu__link"
198
- >
199
- {{ groupItem.text }}
200
- </a>
201
- {% else %}
202
- {{ groupItem.text }}
203
- {% endif %}
204
- </p>
205
- </li>
206
- {% endif %}
207
- {% endfor %}
208
- </ul>
209
- {% endif %}
210
- {% endfor %}
211
- </li>
212
- {% endfor %}
213
- </ul>
214
- </div>
215
- {% endif %}
216
- </nav>
217
- {% endif %}
218
-
219
138
  {% if params.search or params.searchLinks %}
220
139
  <div class="ons-header__links ons-grid__col ons-header__menu-link">
221
140
  {{
@@ -234,95 +153,6 @@
234
153
  }}
235
154
  </div>
236
155
  {% endif %}
237
-
238
- {% if params.variants == "basic" and (params.searchLinks or params.search) %}
239
- <nav
240
- class="ons-js-header-search ons-header-nav-search {{ params.searchLinks.classes if params.searchLinks and params.searchLinks.classes else '' }}{{ params.search.classes if params.search and params.search.classes else '' }}"
241
- id="{{ params.search.id if params.search else params.searchLinks.id }}"
242
- aria-label="{{ (params.search.navAriaLabel if params.search else params.searchLinks.searchNavigationAriaLabel) | default('Search navigation') }}"
243
- aria-hidden="false"
244
- >
245
- <div class="ons-container">
246
- <form
247
- class="ons-header-nav-search__input"
248
- method="get"
249
- action="{{ params.search.form.action | default('') }}"
250
- >
251
- {% from "components/input/_macro.njk" import onsInput %}
252
- {{
253
- onsInput({
254
- "id": 'search-field',
255
- "name": params.search.form.inputName | default('q'),
256
- "width": 'full',
257
- "label": {
258
- "text": (params.search.form.inputLabel if params.search.form else params.searchLinks.searchNavigationInputLabel) | default('Search the ONS'),
259
- "id": "header-search-input-label"
260
- },
261
- "searchButton": {
262
- "visuallyHideButtonText": true,
263
- "text": (params.search.form.buttonText if params.search.form else params.searchLinks.searchNavigationButtonText) | default('Search'),
264
- "iconType": 'search',
265
- 'variant': 'header'
266
- }
267
- })
268
- }}
269
- </form>
270
- </div>
271
- {% if params.search or params.searchLinks %}
272
- <div class="ons-container">
273
- <h2 class="ons-u-fs-r--b ons-u-mb-s ons-header-nav-search__heading">
274
- {{ params.search.links.heading if params.search.links else params.searchLinks.heading }}
275
- </h2>
276
- <ul class="ons-list ons-list--bare ons-list--inline">
277
- {% if params.searchLinks %}
278
- {% for item in params.searchLinks.itemsList %}
279
- {# Limiting the popular searches to 5 #}
280
- {% if loop.index <= 5 %}
281
- <li class="ons-list__item">
282
- {% if item.text %}
283
- {% if item.url %}
284
- <a
285
- href="{{ item.url }}"
286
- class="ons-u-fs-r ons-header-nav-search__text"
287
- >{{ item.text }}
288
- </a>
289
- {% else %}
290
- <p class="ons-u-fs-r ons-header-nav-search__text">
291
- {{ item.text }}
292
- </p>
293
- {% endif %}
294
- {% endif %}
295
- </li>
296
- {% endif %}
297
- {% endfor %}
298
- {% endif %}
299
- {% if params.search.links %}
300
- {% for item in params.search.links.itemsList %}
301
- {# Limiting the popular searches to 5 #}
302
- {% if loop.index <= 5 %}
303
- <li class="ons-list__item">
304
- {% if item.text %}
305
- {% if item.url %}
306
- <a
307
- href="{{ item.url }}"
308
- class="ons-u-fs-r ons-header-nav-search__text"
309
- >{{ item.text }}
310
- </a>
311
- {% else %}
312
- <p class="ons-u-fs-r ons-header-nav-search__text">
313
- {{ item.text }}
314
- </p>
315
- {% endif %}
316
- {% endif %}
317
- </li>
318
- {% endif %}
319
- {% endfor %}
320
- {% endif %}
321
- </ul>
322
- </div>
323
- {% endif %}
324
- </nav>
325
- {% endif %}
326
156
  </div>
327
157
  {% endif %}
328
158
  {% if params.language or params.serviceLinks %}
@@ -446,6 +276,153 @@
446
276
  </nav>
447
277
  {% endif %}
448
278
  </div>
279
+ {% if params.variants == "basic" and params.menuLinks %}
280
+ <nav
281
+ class="ons-js-nav-menu ons-header-nav-menu ons-u-pt-2xl ons-u-d-no"
282
+ id="{{ params.menuLinks.id }}"
283
+ aria-label="{{ params.menuLinks.ariaLabel | default("Menu navigation") }}"
284
+ aria-hidden="true"
285
+ >
286
+ {% if params.menuLinks.keyLinks %}
287
+ <div class="ons-container">
288
+ <ul class="ons-grid ons-header-nav-menu__key-list">
289
+ {% for keyLink in params.menuLinks.keyLinks %}
290
+ {% if keyLink.heading %}
291
+ <li class="ons-grid__col ons-col-4@m ons-header-nav-menu__col">
292
+ <h2 class="ons-u-fs-s--b ons-u-mb-no ons-header-nav-menu__heading">
293
+ {% if keyLink.url %}
294
+ <a href="{{ keyLink.url }}" class="ons-header-nav-menu__link">{{ keyLink.heading }}</a>
295
+ {% else %}
296
+ {{ keyLink.heading }}
297
+ {% endif %}
298
+ </h2>
299
+ {% if keyLink.description %}
300
+ <p class="ons-u-fs-s ons-u-mb-no ons-header-nav-menu__description">{{ keyLink.description }}</p>
301
+ {% endif %}
302
+ </li>
303
+ {% endif %}
304
+ {% endfor %}
305
+ </ul>
306
+ </div>
307
+ {% endif %}
308
+ {% if params.menuLinks.columns %}
309
+ <div class="ons-container">
310
+ <ul class="ons-grid ons-list ons-list--bare">
311
+ {% for column in params.menuLinks.columns %}
312
+ <li class="ons-grid__col ons-col-4@m ons-u-mb-no ons-header-nav-menu__col">
313
+ {% for group in column.groups %}
314
+ {% if group.heading %}
315
+ <h2 class="ons-u-fs-s--b ons-header-nav-menu__heading">
316
+ {% if group.url %}
317
+ <a href="{{ group.url }}" class="ons-header-nav-menu__link">{{ group.heading }}</a>
318
+ {% else %}
319
+ {{ group.heading }}
320
+ {% endif %}
321
+ </h2>
322
+ {% endif %}
323
+ {% if group.groupItems %}
324
+ <ul class="ons-list ons-list--bare ons-header-nav-menu__groupItem-list">
325
+ {% for groupItem in group.groupItems %}
326
+ {% if groupItem.text %}
327
+ <li class="ons-u-mb-no">
328
+ <p class="ons-u-fs-s ons-header-nav-menu_text">
329
+ {% if groupItem.url %}
330
+ <a href="{{ groupItem.url }}" class="ons-header-nav-menu__link">
331
+ {{ groupItem.text }}
332
+ </a>
333
+ {% else %}
334
+ {{ groupItem.text }}
335
+ {% endif %}
336
+ </p>
337
+ </li>
338
+ {% endif %}
339
+ {% endfor %}
340
+ </ul>
341
+ {% endif %}
342
+ {% endfor %}
343
+ </li>
344
+ {% endfor %}
345
+ </ul>
346
+ </div>
347
+ {% endif %}
348
+ </nav>
349
+ {% endif %}
350
+ {% if params.variants == "basic" and (params.searchLinks or params.search) %}
351
+ <nav
352
+ class="ons-js-header-search ons-header-nav-search {{ params.searchLinks.classes if params.searchLinks and params.searchLinks.classes else '' }}{{ params.search.classes if params.search and params.search.classes else '' }}"
353
+ id="{{ params.search.id if params.search else params.searchLinks.id }}"
354
+ aria-label="{{ (params.search.navAriaLabel if params.search else params.searchLinks.searchNavigationAriaLabel) | default('Search navigation') }}"
355
+ aria-hidden="false"
356
+ >
357
+ <div class="ons-container">
358
+ <form class="ons-header-nav-search__input" method="get" action="{{ params.search.form.action | default('') }}">
359
+ {% from "components/input/_macro.njk" import onsInput %}
360
+ {{
361
+ onsInput({
362
+ "id": 'search-field',
363
+ "name": params.search.form.inputName | default('q'),
364
+ "width": 'full',
365
+ "label": {
366
+ "text": (params.search.form.inputLabel if params.search.form else params.searchLinks.searchNavigationInputLabel) | default('Search the ONS'),
367
+ "id": "header-search-input-label"
368
+ },
369
+ "searchButton": {
370
+ "visuallyHideButtonText": true,
371
+ "text": (params.search.form.buttonText if params.search.form else params.searchLinks.searchNavigationButtonText) | default('Search'),
372
+ "iconType": 'search',
373
+ 'variant': 'header'
374
+ }
375
+ })
376
+ }}
377
+ </form>
378
+ </div>
379
+ {% if params.search or params.searchLinks %}
380
+ <div class="ons-container">
381
+ <h2 class="ons-u-fs-r--b ons-u-mb-s ons-header-nav-search__heading">
382
+ {{ params.search.links.heading if params.search.links else params.searchLinks.heading }}
383
+ </h2>
384
+ <ul class="ons-list ons-list--bare ons-list--inline">
385
+ {% if params.searchLinks %}
386
+ {% for item in params.searchLinks.itemsList %}
387
+ {# Limiting the popular searches to 5 #}
388
+ {% if loop.index <= 5 %}
389
+ <li class="ons-list__item">
390
+ {% if item.text %}
391
+ {% if item.url %}
392
+ <a href="{{ item.url }}" class="ons-u-fs-r ons-header-nav-search__text"
393
+ >{{ item.text }}
394
+ </a>
395
+ {% else %}
396
+ <p class="ons-u-fs-r ons-header-nav-search__text">{{ item.text }}</p>
397
+ {% endif %}
398
+ {% endif %}
399
+ </li>
400
+ {% endif %}
401
+ {% endfor %}
402
+ {% endif %}
403
+ {% if params.search.links %}
404
+ {% for item in params.search.links.itemsList %}
405
+ {# Limiting the popular searches to 5 #}
406
+ {% if loop.index <= 5 %}
407
+ <li class="ons-list__item">
408
+ {% if item.text %}
409
+ {% if item.url %}
410
+ <a href="{{ item.url }}" class="ons-u-fs-r ons-header-nav-search__text"
411
+ >{{ item.text }}
412
+ </a>
413
+ {% else %}
414
+ <p class="ons-u-fs-r ons-header-nav-search__text">{{ item.text }}</p>
415
+ {% endif %}
416
+ {% endif %}
417
+ </li>
418
+ {% endif %}
419
+ {% endfor %}
420
+ {% endif %}
421
+ </ul>
422
+ </div>
423
+ {% endif %}
424
+ </nav>
425
+ {% endif %}
449
426
  {% if params.variants != "basic" %}
450
427
  <div class="ons-header__main">
451
428
  <div class="ons-container{{ ' ons-container--full-width' if params.fullWidth }}{{ ' ons-container--wide' if params.wide }}">
@@ -8,7 +8,16 @@
8
8
  </div>
9
9
  {% endif %}
10
10
  <div class="ons-grid__col ons-col-auto ons-u-flex-shrink">
11
- <p class="ons-phase-banner__desc ons-u-fs-s ons-u-mb-no">{{ params.html | safe }}</p>
11
+ <p class="ons-phase-banner__desc ons-u-fs-s ons-u-mb-no">
12
+ {% if params.html %}
13
+ {{ params.html | safe }}
14
+ {% else %}
15
+ {{ params.text }}
16
+ {% if params.feedbackLink %}
17
+ {{ params.feedbackLink | safe }}
18
+ {% endif %}
19
+ {% endif %}
20
+ </p>
12
21
  </div>
13
22
  </div>
14
23
  </div>
@@ -24,6 +24,33 @@ describe('macro: phase-banner', () => {
24
24
  expect(htmlContent).toBe('Example content with a <a href="#">link</a>');
25
25
  });
26
26
 
27
+ it('renders text content when `text` is provided', () => {
28
+ const $ = cheerio.load(
29
+ renderComponent('phase-banner', {
30
+ text: 'Example text content',
31
+ }),
32
+ );
33
+
34
+ const textContent = $('.ons-phase-banner__desc').text().trim();
35
+ expect(textContent).toBe('Example text content');
36
+ });
37
+
38
+ it('renders feedbackLink when provided with text', () => {
39
+ const $ = cheerio.load(
40
+ renderComponent('phase-banner', {
41
+ text: 'Example text content',
42
+ feedbackLink: '<a href="#">give feedback</a>',
43
+ }),
44
+ );
45
+
46
+ const textContent = $('.ons-phase-banner__desc').text().replace(/\s+/g, ' ').trim();
47
+ expect(textContent).toBe('Example text content give feedback');
48
+
49
+ const link = $('.ons-phase-banner__desc a');
50
+ expect(link.length).toBe(1);
51
+ expect(link.text()).toBe('give feedback');
52
+ });
53
+
27
54
  it('has the "Beta" badge by default', () => {
28
55
  const $ = cheerio.load(renderComponent('phase-banner', EXAMPLE_PHASE_BANNER_MINIMAL));
29
56
 
@@ -0,0 +1,18 @@
1
+ {% from "components/phase-banner/_macro.njk" import onsPhaseBanner %}
2
+ {% from "components/external-link/_macro.njk" import onsExternalLink %}
3
+
4
+ {% set feedbackLink %}
5
+ {{
6
+ onsExternalLink({
7
+ "url": "#0",
8
+ "text": "give feedback"
9
+ })
10
+ }}
11
+ {% endset %}
12
+
13
+ {{
14
+ onsPhaseBanner({
15
+ "text": "This is a new service. To help us improve it,",
16
+ "feedbackLink": feedbackLink
17
+ })
18
+ }}
@@ -0,0 +1,7 @@
1
+ {% from "components/phase-banner/_macro.njk" import onsPhaseBanner %}
2
+
3
+ {{
4
+ onsPhaseBanner({
5
+ "text": "This is a new service"
6
+ })
7
+ }}
@@ -7,6 +7,7 @@
7
7
  mark,
8
8
  .ons-instruction {
9
9
  background-color: var(--ons-color-instruction);
10
+ background-image: none;
10
11
  color: var(--ons-color-text-inverse);
11
12
  margin-right: 0.5rem;
12
13
  padding: 0 0.5rem;
@@ -35,7 +35,7 @@
35
35
  {% for th in headerCols.ths %}
36
36
  <th
37
37
  scope="col"
38
- class="ons-table__header{{ ' ' + th.thClasses if th.thClasses else '' }}{{ ' ons-table__header--numeric' if th.numeric }}"
38
+ class="ons-table__header ons-table__header--{{ th.valign | default('top') }}{{ ' ' + th.thClasses if th.thClasses else '' }}{{ ' ons-table__header--numeric' if th.numeric }}"
39
39
  {% if th.colspan %}colspan="{{ th.colspan }}"{% endif %}
40
40
  {% if th.rowspan %}rowspan="{{ th.rowspan }}"{% endif %}
41
41
  {% if 'sortable' in variants %}aria-sort="{{ th.ariaSort | default('none') }}"{% endif %}
@@ -73,7 +73,8 @@
73
73
  {% set isFirstRow = loop.index == 0 and td.rowspan %}
74
74
  {% set rowSpan = isFirstRow and loop.index0 == rowspanCount %}
75
75
  {{ openingTag | safe }}
76
- class="ons-table__cell{{ ' ' + td.tdClasses if td.tdClasses else '' }}{{ ' ons-table__cell--numeric' if td.numeric }}"
76
+ class="ons-table__cell
77
+ ons-table__cell--{{ td.valign | default('top') }}{{ ' ' + td.tdClasses if td.tdClasses else '' }}{{ ' ons-table__cell--numeric' if td.numeric }}"
77
78
  {% if td.id %}id="{{ td.id }}"{% endif %}
78
79
  {% if td.data %}{{ ' ' }}data-th="{{ td.data }}"{% endif %}
79
80
  {% if td.colspan %}colspan="{{ td.colspan }}"{% endif %}
@@ -107,7 +108,9 @@
107
108
  <tfoot class="ons-table__foot">
108
109
  <tr class="ons-table__row">
109
110
  {% for tfootCell in params.tfoot %}
110
- <td class="ons-table__cell ons-u-fs-s">{{ tfootCell.value }}</td>
111
+ <td class="ons-table__cell ons-table__cell--{{ tfootCell.valign | default('top') }} ons-u-fs-s">
112
+ {{ tfootCell.value }}
113
+ </td>
111
114
  {% endfor %}
112
115
  </tr>
113
116
  </tfoot>
@@ -90,6 +90,51 @@ describe('macro: table', () => {
90
90
  expect($('.ons-table-scrollable__content').attr('aria-label')).toBe('Example table caption. Special table');
91
91
  });
92
92
 
93
+ describe('Vertical Alignment', () => {
94
+ it('adds "ons-table__header--middle" class to column header when valign is set', () => {
95
+ const $ = cheerio.load(
96
+ renderComponent('table', {
97
+ ...EXAMPLE_TABLE,
98
+ ths: [
99
+ {
100
+ value: 'Column 1',
101
+ valign: 'middle',
102
+ },
103
+ ],
104
+ }),
105
+ );
106
+
107
+ expect($('.ons-table__header').hasClass('ons-table__header--middle')).toBe(true);
108
+ });
109
+
110
+ it('adds "ons-table__header--top" class to column header when valign is not set', () => {
111
+ const $ = cheerio.load(renderComponent('table', EXAMPLE_TABLE));
112
+
113
+ expect($('.ons-table__header').hasClass('ons-table__header--top')).toBe(true);
114
+ });
115
+
116
+ it('adds "ons-table__cell--middle" class to row when valign is middle', () => {
117
+ const $ = cheerio.load(
118
+ renderComponent('table', {
119
+ ...EXAMPLE_TABLE,
120
+ trs: [
121
+ {
122
+ tds: [{ value: 'Row 1 Cell 1', valign: 'middle' }],
123
+ },
124
+ ],
125
+ }),
126
+ );
127
+
128
+ expect($('.ons-table__cell').hasClass('ons-table__cell--middle')).toBe(true);
129
+ });
130
+
131
+ it('adds "ons-table__cell--top" class to row when valign is not set', () => {
132
+ const $ = cheerio.load(renderComponent('table', EXAMPLE_TABLE));
133
+
134
+ expect($('.ons-table__cell').hasClass('ons-table__cell--top')).toBe(true);
135
+ });
136
+ });
137
+
93
138
  describe('header row', () => {
94
139
  it('renders header cells with expected text', () => {
95
140
  const $ = cheerio.load(renderComponent('table', EXAMPLE_TABLE));
@@ -529,6 +574,19 @@ describe('macro: table', () => {
529
574
  const footerCellValues = mapAll($('.ons-table__foot .ons-table__cell'), (node) => node.text().trim());
530
575
  expect(footerCellValues).toEqual(['Footer Cell 1', 'Footer Cell 2', 'Footer Cell 3']);
531
576
  });
577
+ it('adds "ons-table__cell--middle" class to row when valign is middle', () => {
578
+ const $ = cheerio.load(
579
+ renderComponent('table', {
580
+ ...EXAMPLE_TABLE,
581
+ tfoot: [
582
+ { value: 'Footer Cell 1', valign: 'middle' },
583
+ { value: 'Footer Cell 2', valign: 'middle' },
584
+ ],
585
+ }),
586
+ );
587
+
588
+ expect($('.ons-table__cell').hasClass('ons-table__cell--middle')).toBe(true);
589
+ });
532
590
  });
533
591
 
534
592
  describe('sortable variant', () => {
@@ -26,10 +26,18 @@
26
26
  overflow: hidden;
27
27
  padding: 0.5rem 0 0.5rem 1rem;
28
28
  text-align: left;
29
- vertical-align: top;
30
29
  &--numeric {
31
30
  text-align: right;
32
31
  }
32
+ &--top {
33
+ vertical-align: top;
34
+ }
35
+ &--bottom {
36
+ vertical-align: bottom;
37
+ }
38
+ &--center {
39
+ vertical-align: middle;
40
+ }
33
41
  }
34
42
 
35
43
  &--has-rowspan {