@ons/design-system 72.10.8 → 72.10.9

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 (34) hide show
  1. package/components/accordion/accordion.js +3 -2
  2. package/components/autosuggest/autosuggest.spec.js +2 -0
  3. package/components/autosuggest/autosuggest.ui.js +12 -7
  4. package/components/breadcrumbs/_breadcrumbs.scss +53 -0
  5. package/components/breadcrumbs/_macro.njk +33 -24
  6. package/components/breadcrumbs/_macro.spec.js +25 -0
  7. package/components/chart/_chart.scss +85 -0
  8. package/components/chart/_macro.njk +15 -2
  9. package/components/chart/_macro.spec.js +41 -11
  10. package/components/chart/bar-chart.js +8 -1
  11. package/components/chart/common-chart-options.js +9 -0
  12. package/components/chart/example-bar-chart-with-axis-min-and-max-values.njk +0 -1
  13. package/components/chart/example-bar-chart-with-point-range-and-reference-line-annotations.njk +4 -4
  14. package/components/chart/example-bar-chart.njk +0 -1
  15. package/components/chart/range-annotations-options.js +1 -1
  16. package/components/download-resources/download-resources.spec.js +2 -0
  17. package/components/hero/_hero.scss +17 -22
  18. package/components/hero/_macro.njk +1 -1
  19. package/components/hero/_macro.spec.js +1 -1
  20. package/components/hero/example-hero-dark-with-external-breadcrumbs.njk +194 -0
  21. package/components/hero/example-hero-default-with-external-breadcrumbs.njk +201 -0
  22. package/components/hero/example-hero-grey-with-external-breadcrumbs.njk +243 -0
  23. package/components/hero/example-hero-navy-blue-with-external-breadcrumbs.njk +200 -0
  24. package/components/hero/example-hero-pale-blue-with-external-breadcrumbs.njk +201 -0
  25. package/components/icon/_macro.njk +1 -1
  26. package/components/mutually-exclusive/mutually-exclusive.js +3 -1
  27. package/components/radios/clear-radios.js +4 -2
  28. package/components/relationships/relationships.js +4 -2
  29. package/components/video/video.js +2 -0
  30. package/css/main.css +1 -1
  31. package/js/timeout.js +9 -6
  32. package/package.json +4 -4
  33. package/scripts/main.es5.js +4 -2
  34. package/scripts/main.js +4 -2
@@ -1,3 +1,4 @@
1
+ import DOMPurify from 'dompurify';
1
2
  export default class Accordion {
2
3
  constructor(button, detailsEls) {
3
4
  this.openDetailsEls = 0;
@@ -52,11 +53,11 @@ export default class Accordion {
52
53
 
53
54
  setButton() {
54
55
  if (this.canClose()) {
55
- this.buttonInner.innerHTML = this.closeButton;
56
+ this.buttonInner.innerHTML = DOMPurify.sanitize(this.closeButton);
56
57
  this.button.setAttribute('data-ga-label', this.buttonOpen);
57
58
  this.button.setAttribute('aria-expanded', 'true');
58
59
  } else {
59
- this.buttonInner.innerHTML = this.buttonOpen;
60
+ this.buttonInner.innerHTML = DOMPurify.sanitize(this.buttonOpen);
60
61
  this.button.setAttribute('data-ga-label', this.closeButton);
61
62
  this.button.setAttribute('aria-expanded', 'false');
62
63
  }
@@ -386,9 +386,11 @@ describe('script: autosuggest', () => {
386
386
  describe('when the mouse moves over a result and a suggestion is focused', () => {
387
387
  it('removes the focused class', async () => {
388
388
  await setTestPage('/test', renderComponent('autosuggest', EXAMPLE_AUTOSUGGEST));
389
+ await page.mouse.move(0, 0); // move out of the component
389
390
 
390
391
  await page.type('.ons-js-autosuggest-input', 'state', { delay: 20 });
391
392
  await page.keyboard.press('ArrowDown');
393
+
392
394
  await page.hover('.ons-autosuggest__option:nth-child(2)');
393
395
 
394
396
  const focusedClassCount = await page.$$eval('.ons-autosuggest__option--focused', (nodes) => nodes.length);
@@ -1,6 +1,7 @@
1
1
  import abortableFetch from '../../js/abortable-fetch';
2
2
  import { sanitiseAutosuggestText } from './autosuggest.helpers';
3
3
  import runFuse from './fuse-config';
4
+ import DOMPurify from 'dompurify';
4
5
 
5
6
  export const baseClass = 'ons-js-autosuggest';
6
7
 
@@ -398,7 +399,7 @@ export default class AutosuggestUI {
398
399
  const listElement = document.createElement('li');
399
400
  listElement.className = `${classAutosuggestOption} ${classAutosuggestOptionMoreResults}`;
400
401
  listElement.setAttribute('aria-hidden', 'true');
401
- listElement.innerHTML = this.moreResults;
402
+ listElement.innerHTML = DOMPurify.sanitize(this.moreResults);
402
403
  this.listbox.appendChild(listElement);
403
404
  }
404
405
 
@@ -436,10 +437,12 @@ export default class AutosuggestUI {
436
437
  if (status === 400 || status === false) {
437
438
  message = this.typeMore;
438
439
  this.setAriaStatus(message);
439
- this.listbox.innerHTML = `<li class="${classAutosuggestOption} ${classAutosuggestOptionNoResults}">${message}</li>`;
440
+ this.listbox.innerHTML = DOMPurify.sanitize(
441
+ `<li class="${classAutosuggestOption} ${classAutosuggestOptionNoResults}">${message}</li>`,
442
+ );
440
443
  } else if (status > 400 || status === '') {
441
- message =
442
- this.errorAPI + (this.errorAPILinkText ? ' <a href="' + window.location.href + '">' + this.errorAPILinkText + '</a>.' : '');
444
+ const sanitizedHref = DOMPurify.sanitize(window.location.href);
445
+ message = this.errorAPI + (this.errorAPILinkText ? ' <a href="' + sanitizedHref + '">' + this.errorAPILinkText + '</a>.' : '');
443
446
  let ariaMessage = this.errorAPI + (this.errorAPILinkText ? ' ' + this.errorAPILinkText : '');
444
447
 
445
448
  this.input.setAttribute('disabled', true);
@@ -453,7 +456,9 @@ export default class AutosuggestUI {
453
456
  this.resultsTitleContainer.remove();
454
457
  } else {
455
458
  message = this.noResults;
456
- this.listbox.innerHTML = `<li class="${classAutosuggestOption} ${classAutosuggestOptionNoResults}">${message}</li>`;
459
+ this.listbox.innerHTML = DOMPurify.sanitize(
460
+ `<li class="${classAutosuggestOption} ${classAutosuggestOptionNoResults}">${message}</li>`,
461
+ );
457
462
  }
458
463
  }
459
464
 
@@ -503,7 +508,7 @@ export default class AutosuggestUI {
503
508
  }
504
509
  }
505
510
  }
506
- this.ariaStatus.innerHTML = content;
511
+ this.ariaStatus.innerHTML = DOMPurify.sanitize(content);
507
512
  }
508
513
 
509
514
  selectResult(index) {
@@ -548,7 +553,7 @@ export default class AutosuggestUI {
548
553
  warningSpanElement.innerHTML = '!';
549
554
 
550
555
  warningBodyElement.className = 'ons-panel__body';
551
- warningBodyElement.innerHTML = content;
556
+ warningBodyElement.innerHTML = DOMPurify.sanitize(content);
552
557
 
553
558
  warningElement.appendChild(warningSpanElement);
554
559
  warningElement.appendChild(warningBodyElement);
@@ -1,5 +1,58 @@
1
1
  $breadcrumb-chevron-height: 0.65rem;
2
2
 
3
+ .ons-breadcrumbs-wrapper {
4
+ position: relative;
5
+ z-index: 10;
6
+ margin-bottom: -2rem;
7
+ &--grey {
8
+ background-color: var(--ons-color-banner-bg);
9
+ }
10
+
11
+ &--dark {
12
+ background-color: var(--ons-color-hero-bg-dark);
13
+ }
14
+
15
+ &--navy-blue {
16
+ background-color: var(--ons-color-navy-blue-light);
17
+ margin-bottom: -1.75rem;
18
+ @include mq(l) {
19
+ margin-bottom: -3.25rem;
20
+ }
21
+ }
22
+
23
+ &--dark,
24
+ &--navy-blue {
25
+ .ons-icon {
26
+ color: var(--ons-color-text-inverse);
27
+ }
28
+
29
+ .ons-breadcrumbs__link {
30
+ color: var(--ons-color-text-inverse);
31
+ text-decoration: underline;
32
+
33
+ &:hover {
34
+ color: var(--ons-color-text-inverse);
35
+ text-decoration: underline solid var(--ons-color-text-inverse) 2px;
36
+ }
37
+
38
+ &:focus {
39
+ color: var(--ons-color-text);
40
+ }
41
+
42
+ &:focus:hover {
43
+ text-decoration: none;
44
+ }
45
+ }
46
+ }
47
+
48
+ &--pale-blue {
49
+ background-color: var(--ons-color-pale-blue);
50
+ }
51
+ .ons-breadcrumbs {
52
+ padding: 1rem;
53
+ }
54
+ }
55
+
3
56
  .ons-breadcrumbs {
4
57
  align-items: center;
5
58
  display: flex;
@@ -1,28 +1,37 @@
1
1
  {% from "components/icon/_macro.njk" import onsIcon %}
2
-
3
2
  {% macro onsBreadcrumbs(params) %}
4
- <nav
5
- class="ons-breadcrumbs{{ ' ' + params.classes if params.classes else '' }}"
6
- aria-label="{{ params.ariaLabel | default('Breadcrumbs') }}"
7
- {% if params.id %}id="{{ params.id }}"{% endif %}
8
- >
9
- <ol class="ons-breadcrumbs__items ons-u-fs-s">
10
- {%- for item in params.itemsList -%}
11
- <li class="ons-breadcrumbs__item{{ ' ' + item.itemClasses if item.itemClasses else '' }}" id="breadcrumb-{{ loop.index }}">
12
- <a
13
- class="ons-breadcrumbs__link{{ ' ' + item.linkClasses if item.linkClasses else '' }}"
14
- href="{% if not isDesignSystemExample %}{{ item.url }}{% else %}#0{% endif %}"
15
- {% if item.id %}{{ ' ' }}id='{{ item.id }}'{% endif %}
16
- {% if item.attributes %}{% for attribute, value in (item.attributes.items() if item.attributes is mapping and item.attributes.items else item.attributes) %}{{ ' ' }}{{ attribute }}="{{ value }}"{% endfor %}{% endif %}
17
- >{{ item.text }}</a
3
+ {% set breadcrumbs %}
4
+ <nav
5
+ class="ons-breadcrumbs{{ ' ons-container' if params.variant }}{{ ' ' + params.classes if params.classes else '' }}"
6
+ aria-label="{{ params.ariaLabel | default('Breadcrumbs') }}"
7
+ {% if params.id %}id="{{ params.id }}"{% endif %}
8
+ >
9
+ <ol class="ons-breadcrumbs__items ons-u-fs-s">
10
+ {%- for item in params.itemsList -%}
11
+ <li
12
+ class="ons-breadcrumbs__item{{ ' ' + item.itemClasses if item.itemClasses else '' }}"
13
+ id="breadcrumb-{{ loop.index }}"
18
14
  >
19
- {{-
20
- onsIcon({
21
- "iconType": "chevron"
22
- })
23
- -}}
24
- </li>
25
- {%- endfor -%}
26
- </ol>
27
- </nav>
15
+ <a
16
+ class="ons-breadcrumbs__link{{ ' ' + item.linkClasses if item.linkClasses else '' }}"
17
+ href="{% if not isDesignSystemExample %}{{ item.url }}{% else %}#0{% endif %}"
18
+ {% if item.id %}{{ ' ' }}id='{{ item.id }}'{% endif %}
19
+ {% if item.attributes %}{% for attribute, value in (item.attributes.items() if item.attributes is mapping and item.attributes.items else item.attributes) %}{{ ' ' }}{{ attribute }}="{{ value }}"{% endfor %}{% endif %}
20
+ >{{ item.text }}</a
21
+ >
22
+ {{-
23
+ onsIcon({
24
+ "iconType": "chevron"
25
+ })
26
+ -}}
27
+ </li>
28
+ {%- endfor -%}
29
+ </ol>
30
+ </nav>
31
+ {% endset %}
32
+ {% if params.variant %}
33
+ <div class="ons-breadcrumbs-wrapper ons-breadcrumbs-wrapper--{{ params.variant }}">{{ breadcrumbs | safe }}</div>
34
+ {% else %}
35
+ {{ breadcrumbs | safe }}
36
+ {% endif %}
28
37
  {% endmacro %}
@@ -132,4 +132,29 @@ describe('FOR: Macro: Breadcrumbs', () => {
132
132
  });
133
133
  });
134
134
  });
135
+
136
+ describe('GIVEN: Params: variant', () => {
137
+ describe('WHEN: variant is provided', () => {
138
+ const $ = cheerio.load(
139
+ renderComponent('breadcrumbs', {
140
+ ...EXAMPLE_BREADCRUMBS_REQUIRED_PARAMS,
141
+ variant: 'grey',
142
+ }),
143
+ );
144
+ test('THEN: renders breadcrumbs in a breadcrumbs-wrapper with correct modifier class', () => {
145
+ expect($('.ons-breadcrumbs-wrapper').hasClass('ons-breadcrumbs-wrapper--grey')).toBe(true);
146
+ });
147
+ });
148
+
149
+ describe('WHEN: variant is not provided', () => {
150
+ const $ = cheerio.load(
151
+ renderComponent('breadcrumbs', {
152
+ ...EXAMPLE_BREADCRUMBS_REQUIRED_PARAMS,
153
+ }),
154
+ );
155
+ test('THEN: does not render breadcrumbs-wrapper', () => {
156
+ expect($('.ons-breadcrumbs-wrapper').length).toBe(0);
157
+ });
158
+ });
159
+ });
135
160
  });
@@ -7,6 +7,28 @@
7
7
  overflow: visible !important;
8
8
  }
9
9
 
10
+ @media (forced-colors: active) {
11
+ .highcharts-plot-band {
12
+ fill: var(--ons-color-grey-75); /* Forces the color used for text in high contrast mode */
13
+ }
14
+ .highcharts-annotation-label text,
15
+ .highcharts-plot-line-label,
16
+ .highcharts-plot-band-label {
17
+ fill: CanvasText !important; /* Forces the color used for text in high contrast mode */
18
+ }
19
+
20
+ .highcharts-annotation-label-box {
21
+ fill: Canvas; /* Sets the background to match system background */
22
+ stroke: CanvasText; /* Ensures border is visible in contrast mode */
23
+ }
24
+ }
25
+
26
+ &__container:focus {
27
+ box-shadow: 0 0 0 3px var(--ons-color-black);
28
+ outline: 4px solid var(--ons-color-focus);
29
+ outline-offset: 2px;
30
+ }
31
+
10
32
  &__download-title {
11
33
  @extend .ons-u-pt-l;
12
34
  @extend .ons-u-fs-r--b;
@@ -170,6 +192,69 @@
170
192
  border-left: 1px solid var(--ons-color-grey-100);
171
193
  }
172
194
 
195
+ @media (forced-colors: active) {
196
+ .ons-chart__boxplot-legend-item--uncertainty,
197
+ .highcharts-boxplot-box {
198
+ background-color: SelectedItem;
199
+ fill: SelectedItem;
200
+ }
201
+
202
+ .ons-chart__boxplot-legend-item--estimate,
203
+ .highcharts-boxplot-median {
204
+ background-color: WindowText;
205
+ stroke: WindowText;
206
+ }
207
+ .highcharts-color-0,
208
+ .highcharts-color-0 .highcharts-area,
209
+ .highcharts-legend-item.highcharts-color-0 rect {
210
+ fill: #007faa;
211
+ }
212
+ .highcharts-color-1,
213
+ .highcharts-color-1 .highcharts-area,
214
+ .highcharts-legend-item.highcharts-color-1 rect {
215
+ fill: #a6f0ff;
216
+ }
217
+ .highcharts-color-2,
218
+ .highcharts-color-2 .highcharts-area,
219
+ .highcharts-legend-item.highcharts-color-2 rect {
220
+ fill: #70d49e;
221
+ }
222
+ .highcharts-color-3,
223
+ .highcharts-color-3 .highcharts-area,
224
+ .highcharts-legend-item.highcharts-color-3 rect {
225
+ fill: #e898a5;
226
+ }
227
+ .highcharts-color-4,
228
+ .highcharts-color-4 .highcharts-area,
229
+ .highcharts-legend-item.highcharts-color-4 rect {
230
+ fill: #dadfe1;
231
+ }
232
+ .highcharts-color-5,
233
+ .highcharts-color-5 .highcharts-area,
234
+ .highcharts-legend-item.highcharts-color-5 rect {
235
+ fill: #f9db72;
236
+ }
237
+ .highcharts-color-6,
238
+ .highcharts-color-6 .highcharts-area,
239
+ .highcharts-legend-item.highcharts-color-6 rect {
240
+ fill: #f45b5b;
241
+ }
242
+ .highcharts-color-7,
243
+ .highcharts-color-7 .highcharts-area,
244
+ .highcharts-legend-item.highcharts-color-7 rect {
245
+ fill: #1e824c;
246
+ }
247
+ .highcharts-color-8,
248
+ .highcharts-color-8 .highcharts-area,
249
+ .highcharts-legend-item.highcharts-color-8 rect {
250
+ fill: #e7934c;
251
+ }
252
+ .highcharts-color-9,
253
+ .highcharts-color-9 .highcharts-area,
254
+ .highcharts-legend-item.highcharts-color-9 rect {
255
+ fill: #a0618b;
256
+ }
257
+ }
173
258
  // Allow last label to overflow
174
259
  .highcharts-container {
175
260
  overflow: visible !important;
@@ -15,6 +15,9 @@
15
15
  {% set openingDownloadTitleTag = "<h" ~ (headingLevel + 2) %}
16
16
  {% set closingDownloadTitleTag = "</h" ~ (headingLevel + 2) ~ ">" %}
17
17
  {% set audioDescriptionId = "chart-audio-description-" ~ params.id %}
18
+ {% set instructionsId = "chart-instructions-" ~ params.id %}
19
+ {% set instructions = params.instructions | default('Use the Tab key to move focus into the chart. Once inside, use the arrow keys to navigate between data points. As you move, tooltips will be announced to describe each point. Touch device users, explore by touch or with swipe gestures.') %}
20
+
18
21
  <div
19
22
  {% if not params.iframeUrl %}
20
23
  data-highcharts-base-chart data-highcharts-type="{{ params.chartType }}" data-highcharts-theme="{{ params.theme }}"
@@ -60,7 +63,7 @@
60
63
 
61
64
  {% if params.iframeUrl %}
62
65
  <div
63
- class="ons-chart__iframe-wrapper{% if params.fallbackImageUrl %} ons-chart__non-js-hide{% endif %}"
66
+ class="ons-chart__iframe-wrapper{{ ' ons-chart__non-js-hide' if params.fallbackImageUrl else '' }}"
64
67
  id="{{ params.id }}"
65
68
  data-url="{{ params.iframeUrl }}"
66
69
  data-title="{{ params.title }}"
@@ -85,7 +88,17 @@
85
88
  </div>
86
89
  {% endif %}
87
90
  {% if params.chartType in supportedChartTypes %}
88
- <div data-highcharts-chart class="ons-chart__chart"></div>
91
+ <div
92
+ data-highcharts-chart-container
93
+ class="ons-chart__container"
94
+ tabindex="0"
95
+ role="region"
96
+ aria-label="chart container"
97
+ aria-describedby="{{ instructionsId }}"
98
+ >
99
+ <div id="{{ instructionsId }}" class="ons-u-vh">{{ instructions }}</div>
100
+ <div data-highcharts-chart class="ons-chart__chart"></div>
101
+ </div>
89
102
  {% else %}
90
103
  <p data-invalid-chart-type data-unsupported-chart-text>
91
104
  <b>{{ '"' + params.chartType + '" - ' + (params.unsupportedChartText or 'chart type is not supported') }}</b>
@@ -63,6 +63,36 @@ describe('Macro: Chart', () => {
63
63
  expect($('figcaption').length).toBe(0);
64
64
  expect($('.ons-chart__download-title').length).toBe(0);
65
65
  });
66
+
67
+ test('THEN: it renders the chart container with the correct aria attributes', () => {
68
+ expect($('.ons-chart__container').attr('aria-label')).toBe('chart container');
69
+ });
70
+ });
71
+ });
72
+
73
+ describe('GIVEN: Params: Instructions', () => {
74
+ describe('WHEN: instructions is provided', () => {
75
+ const $ = cheerio.load(
76
+ renderComponent('chart', {
77
+ ...EXAMPLE_LINE_CHART_REQUIRED_PARAMS,
78
+ instructions: 'Some custom instructions for the chart.',
79
+ }),
80
+ );
81
+
82
+ test('THEN: it renders the chart with the correct instructions text', () => {
83
+ const expectedText = 'Some custom instructions for the chart.';
84
+ expect($('#chart-instructions-chart-123').text().trim()).toBe(expectedText);
85
+ });
86
+ });
87
+
88
+ describe('WHEN: instructions is not provided', () => {
89
+ const $ = cheerio.load(renderComponent('chart', EXAMPLE_LINE_CHART_REQUIRED_PARAMS));
90
+
91
+ test('THEN: it renders the chart with the default instructions text', () => {
92
+ const expectedText =
93
+ 'Use the Tab key to move focus into the chart. Once inside, use the arrow keys to navigate between data points. As you move, tooltips will be announced to describe each point. Touch device users, explore by touch or with swipe gestures.';
94
+ expect($('#chart-instructions-chart-123').text().trim()).toBe(expectedText);
95
+ });
66
96
  });
67
97
  });
68
98
 
@@ -288,7 +318,7 @@ describe('Macro: Chart', () => {
288
318
  );
289
319
 
290
320
  test('THEN: it renders the description for accessibility', () => {
291
- expect($('.ons-u-vh').text()).toBe('An accessible description for screen readers.');
321
+ expect($('#chart-audio-description-chart-123').text()).toBe('An accessible description for screen readers.');
292
322
  });
293
323
  });
294
324
  });
@@ -465,7 +495,7 @@ describe('Macro: Chart', () => {
465
495
  );
466
496
 
467
497
  test('THEN: it renders the description for accessibility', () => {
468
- expect($('.ons-u-vh').text()).toBe('An accessible description for screen readers.');
498
+ expect($('#chart-audio-description-bar-chart-123').text()).toBe('An accessible description for screen readers.');
469
499
  });
470
500
  });
471
501
  });
@@ -612,7 +642,7 @@ describe('Macro: Chart', () => {
612
642
  );
613
643
 
614
644
  test('THEN: it renders the description for accessibility', () => {
615
- expect($('.ons-u-vh').text()).toBe('An accessible description for screen readers.');
645
+ expect($('#chart-audio-description-column-chart-123').text()).toBe('An accessible description for screen readers.');
616
646
  });
617
647
  });
618
648
  });
@@ -837,7 +867,7 @@ describe('Macro: Chart', () => {
837
867
  );
838
868
 
839
869
  test('THEN: it renders the description for accessibility', () => {
840
- expect($('.ons-u-vh').text()).toBe('An accessible description for screen readers.');
870
+ expect($('#chart-audio-description-column-chart-123').text()).toBe('An accessible description for screen readers.');
841
871
  });
842
872
  });
843
873
  });
@@ -993,7 +1023,7 @@ describe('Macro: Chart', () => {
993
1023
  );
994
1024
 
995
1025
  test('THEN: it renders the description for accessibility', () => {
996
- expect($('.ons-u-vh').text()).toBe('An accessible description for screen readers.');
1026
+ expect($('#chart-audio-description-area-chart-123').text()).toBe('An accessible description for screen readers.');
997
1027
  });
998
1028
  });
999
1029
  });
@@ -1050,7 +1080,7 @@ describe('Macro: Chart', () => {
1050
1080
  describe('GIVEN: Params: required', () => {
1051
1081
  describe('WHEN: required params are provided', () => {
1052
1082
  const $ = cheerio.load(renderComponent('chart', EXAMPLE_BOXPLOT_CHART_PARAMS));
1053
- const configScript = $(`script[data-highcharts-config--uuid]`).html();
1083
+ const configScript = $(`script[data-highcharts-config--boxplot-chart-123]`).html();
1054
1084
 
1055
1085
  test('THEN: it passes jest-axe checks', async () => {
1056
1086
  const results = await axe($.html());
@@ -1066,7 +1096,7 @@ describe('Macro: Chart', () => {
1066
1096
  expect(chartContainer.attr('data-highcharts-type')).toBe('boxplot');
1067
1097
  expect(chartContainer.attr('data-highcharts-theme')).toBe('primary');
1068
1098
  expect(chartContainer.attr('data-highcharts-title')).toBe('Example Boxplot Chart');
1069
- expect(chartContainer.attr('data-highcharts-id')).toBe('uuid');
1099
+ expect(chartContainer.attr('data-highcharts-id')).toBe('boxplot-chart-123');
1070
1100
  });
1071
1101
 
1072
1102
  test('THEN: it includes the Highcharts JSON config', () => {
@@ -1170,7 +1200,7 @@ describe('Macro: Chart', () => {
1170
1200
  );
1171
1201
 
1172
1202
  test('THEN: it renders the description for accessibility', () => {
1173
- expect($('.ons-u-vh').text()).toBe(accessibleDescription);
1203
+ expect($('#chart-audio-description-boxplot-chart-123').text()).toBe(accessibleDescription);
1174
1204
  });
1175
1205
  });
1176
1206
  });
@@ -1202,7 +1232,7 @@ describe('Macro: Chart', () => {
1202
1232
  describe('GIVEN: Params: Required', () => {
1203
1233
  describe('WHEN: required params are provided', () => {
1204
1234
  const $ = cheerio.load(renderComponent('chart', EXAMPLE_COLUMN_RANGE_CHART_PARAMS));
1205
- const configScript = $(`script[data-highcharts-config--uuid]`).html();
1235
+ const configScript = $(`script[data-highcharts-config--column-range-chart-123]`).html();
1206
1236
 
1207
1237
  test('THEN: it passes jest-axe accessibility checks', async () => {
1208
1238
  const results = await axe($.html());
@@ -1216,7 +1246,7 @@ describe('Macro: Chart', () => {
1216
1246
  expect(baseChart.attr('data-highcharts-title')).toBe(
1217
1247
  'Food stores showed a strong rise on the month, while non-food stores fell',
1218
1248
  );
1219
- expect(baseChart.attr('data-highcharts-id')).toBe('uuid');
1249
+ expect(baseChart.attr('data-highcharts-id')).toBe('column-range-chart-123');
1220
1250
  });
1221
1251
 
1222
1252
  test('THEN: it includes columnrange and scatter series types', () => {
@@ -1254,7 +1284,7 @@ describe('Macro: Chart', () => {
1254
1284
  });
1255
1285
 
1256
1286
  test('THEN: it still renders the description', () => {
1257
- expect($('.ons-u-vh').text()).toBe('A detailed description');
1287
+ expect($('#chart-audio-description-invalid-chart-123').text()).toBe('A detailed description');
1258
1288
  });
1259
1289
 
1260
1290
  test('THEN: it still renders the caption', () => {
@@ -47,7 +47,14 @@ class BarChart {
47
47
  tickWidth: 0,
48
48
  tickLength: 0,
49
49
  tickColor: 'transparent',
50
- title: { align: 'high', textAlign: 'middle', reserveSpace: false, rotation: 0, y: -25, useHTML: true },
50
+ title: {
51
+ text: '', // Set to an empty string to hide the x-axis title for bar charts
52
+ textAlign: 'middle',
53
+ reserveSpace: false,
54
+ rotation: 0,
55
+ y: -25,
56
+ useHTML: true,
57
+ },
51
58
  },
52
59
  yAxis: {
53
60
  labels: {
@@ -57,6 +57,15 @@ class CommonChartOptions {
57
57
  },
58
58
  accessibility: {
59
59
  enabled: true,
60
+ keyboardNavigation: {
61
+ focusBorder: {
62
+ enabled: false,
63
+ },
64
+ enabled: true,
65
+ seriesNavigation: {
66
+ mode: 'serialize',
67
+ },
68
+ },
60
69
  },
61
70
  yAxis: {
62
71
  labels: {
@@ -38,7 +38,6 @@
38
38
  "Non-store retailing",
39
39
  "Automotive fuel"
40
40
  ],
41
- "title": "Retailing",
42
41
  "type": "linear"
43
42
  },
44
43
  "yAxis": {
@@ -54,8 +54,8 @@
54
54
  {
55
55
  "text": "A test point annotation",
56
56
  "point": {"x": 2, "y": 3},
57
- "labelOffsetX": 40,
58
- "labelOffsetY": -30
57
+ "labelOffsetX": 50,
58
+ "labelOffsetY": 60
59
59
  }
60
60
  ],
61
61
  "rangeAnnotations": [
@@ -71,7 +71,7 @@
71
71
  "range": {"axisValue1": 5, "axisValue2": 6},
72
72
  "axis": "y",
73
73
  "labelOffsetX": -80,
74
- "labelOffsetY": 220,
74
+ "labelOffsetY": 230,
75
75
  "labelWidth": 80
76
76
  }
77
77
  ],
@@ -88,7 +88,7 @@
88
88
  "axis": "y",
89
89
  "labelWidth": 100,
90
90
  "labelOffsetX": 10,
91
- "labelOffsetY": 140
91
+ "labelOffsetY": 170
92
92
  }
93
93
  ]
94
94
  })
@@ -42,7 +42,6 @@
42
42
  "Non-store retailing",
43
43
  "Automotive fuel"
44
44
  ],
45
- "title": "Retailing",
46
45
  "type": "linear"
47
46
  },
48
47
  "yAxis": {
@@ -160,7 +160,7 @@ class RangeAnnotationsOptions {
160
160
  }
161
161
 
162
162
  // Create and add the connecting line
163
- const line = document.createElement('div');
163
+ const line = document.createElement('tspan');
164
164
  line.classList.add('ons-chart__connector-line');
165
165
  line.setAttribute('data-range-annotation-line', true);
166
166
  labelElement.appendChild(line);
@@ -432,11 +432,13 @@ describe('script: download-resources', () => {
432
432
  });
433
433
 
434
434
  describe('"Reset all filters" button', () => {
435
+ const { setTimeout } = require('node:timers/promises');
435
436
  beforeEach(async () => {
436
437
  await setTestPage('/test', RENDERED_EXAMPLE_PAGE);
437
438
  await page.click('#general-public');
438
439
  await page.click('#logo');
439
440
  await page.click('.ons-js-adv-filter__reset');
441
+ await setTimeout(50);
440
442
  });
441
443
 
442
444
  it('resets state of all filter checkboxes ', async () => {