@ons/design-system 72.10.6 → 72.10.8

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 (38) hide show
  1. package/components/char-check-limit/_macro.njk +5 -4
  2. package/components/char-check-limit/_macro.spec.js +167 -7
  3. package/components/char-check-limit/character-check.js +23 -17
  4. package/components/char-check-limit/character-check.spec.js +106 -1
  5. package/components/chart/_chart.scss +39 -5
  6. package/components/chart/_macro.njk +190 -152
  7. package/components/chart/_macro.spec.js +274 -21
  8. package/components/chart/annotations-options.js +1 -1
  9. package/components/chart/bar-chart.js +2 -0
  10. package/components/chart/chart-iframe-resize.dom.js +8 -0
  11. package/components/chart/chart-iframe-resize.js +16 -0
  12. package/components/chart/chart.dom.js +5 -3
  13. package/components/chart/chart.js +13 -2
  14. package/components/chart/example-area-chart.njk +2 -1
  15. package/components/chart/example-bar-chart.njk +4 -0
  16. package/components/chart/example-iframe-chart.njk +33 -0
  17. package/components/chart/example-line-chart-with-annotations.njk +3 -1
  18. package/components/chart/example-line-chart.njk +6 -1
  19. package/components/chart/example-scatter-chart.njk +4 -0
  20. package/components/chart/range-annotations-options.js +1 -1
  21. package/components/chart/reference-line-annotations-options.js +1 -1
  22. package/components/checkboxes/_macro.spec.js +3 -3
  23. package/components/input/_macro.njk +1 -2
  24. package/components/input/_macro.spec.js +2 -22
  25. package/components/input/example-input-search-with-character-check.njk +0 -1
  26. package/components/tabs/tabs.js +2 -2
  27. package/components/textarea/_macro.njk +19 -3
  28. package/components/textarea/_macro.spec.js +76 -3
  29. package/components/textarea/example-textarea-with-word-limit.njk +20 -0
  30. package/css/main.css +1 -1
  31. package/img/small/area-chart-screenshot.png +0 -0
  32. package/img/small/line-chart-screenshot.png +0 -0
  33. package/js/main.js +2 -0
  34. package/layout/_template.njk +4 -1
  35. package/package.json +6 -3
  36. package/scripts/main.es5.js +3 -1
  37. package/scripts/main.js +3 -1
  38. package/scss/objects/_page.scss +1 -1
@@ -25,6 +25,7 @@ import {
25
25
  EXAMPLE_LINE_CHART_WITH_RANGE_ANNOTATION_WITH_LABEL_INSIDE_PARAMS,
26
26
  EXAMPLE_LINE_CHART_WITH_REFERENCE_LINE_ANNOTATIONS_PARAMS,
27
27
  EXAMPLE_LINE_CHART_WITH_MIXED_ANNOTATION_TYPES_PARAMS,
28
+ EXAMPLE_IFRAME_CHART_PARAMS,
28
29
  } from './_test-examples';
29
30
 
30
31
  describe('Macro: Chart', () => {
@@ -192,6 +193,52 @@ describe('Macro: Chart', () => {
192
193
  });
193
194
  });
194
195
 
196
+ describe('GIVEN: Params: fallbackImageUrl', () => {
197
+ describe('WHEN: fallbackImageUrl is provided', () => {
198
+ const $ = cheerio.load(
199
+ renderComponent('chart', {
200
+ ...EXAMPLE_LINE_CHART_WITH_CONFIG_PARAMS,
201
+ fallbackImageUrl: '/img/small/line-chart-screenshot.png',
202
+ }),
203
+ );
204
+ const noScriptFallbackImage = $(`#fallback-image--chart-456`).html();
205
+ test('THEN: it renders the fallback image', () => {
206
+ expect(noScriptFallbackImage).toContain('/img/small/line-chart-screenshot.png');
207
+ });
208
+ });
209
+ });
210
+
211
+ describe('GIVEN: Params: fallbackImageAlt', () => {
212
+ describe('WHEN: fallbackImageAlt is provided', () => {
213
+ const $ = cheerio.load(
214
+ renderComponent('chart', {
215
+ ...EXAMPLE_LINE_CHART_WITH_CONFIG_PARAMS,
216
+ fallbackImageUrl: '/img/small/line-chart-screenshot.png',
217
+ fallbackImageAlt: 'A description of the fallback image for screen readers',
218
+ }),
219
+ );
220
+ const noScriptFallbackImage = $(`#fallback-image--chart-456`).html();
221
+ test('THEN: it renders the customised fallback image alt text', () => {
222
+ expect(noScriptFallbackImage).toContain('alt="A description of the fallback image for screen readers"');
223
+ });
224
+ });
225
+ });
226
+
227
+ describe('GIVEN: Params: no fallbackImageAlt', () => {
228
+ describe('WHEN: fallbackImageAlt is not provided', () => {
229
+ const $ = cheerio.load(
230
+ renderComponent('chart', {
231
+ ...EXAMPLE_LINE_CHART_WITH_CONFIG_PARAMS,
232
+ fallbackImageUrl: '/img/small/line-chart-screenshot.png',
233
+ }),
234
+ );
235
+ const noScriptFallbackImage = $(`#fallback-image--chart-456`).html();
236
+ test('THEN: it renders the default fallback image alt text', () => {
237
+ expect(noScriptFallbackImage).toContain('alt="Fallback image for the chart as JavaScript is disabled"');
238
+ });
239
+ });
240
+ });
241
+
195
242
  describe('GIVEN: Params: Caption', () => {
196
243
  describe('WHEN: caption is provided', () => {
197
244
  const $ = cheerio.load(
@@ -628,14 +675,14 @@ describe('Macro: Chart', () => {
628
675
  });
629
676
 
630
677
  test('THEN: it renders the footnotes', () => {
631
- expect($('.ons-chart__footnotes').text()).toContain('1');
632
- expect($('.ons-chart__footnotes').text()).toContain('A test annotation');
633
- expect($('.ons-chart__footnotes').text()).toContain('2');
634
- expect($('.ons-chart__footnotes').text()).toContain('Another test annotation');
678
+ expect($('.ons-chart__annotations-footnotes').text()).toContain('1');
679
+ expect($('.ons-chart__annotations-footnotes').text()).toContain('A test annotation');
680
+ expect($('.ons-chart__annotations-footnotes').text()).toContain('2');
681
+ expect($('.ons-chart__annotations-footnotes').text()).toContain('Another test annotation');
635
682
  });
636
683
 
637
684
  test('THEN: the footnotes are hidden from screen readers', () => {
638
- expect($('.ons-chart__footnotes').attr('aria-hidden')).toBe('true');
685
+ expect($('.ons-chart__annotations-footnotes').attr('aria-hidden')).toBe('true');
639
686
  });
640
687
 
641
688
  test('THEN: it includes the Annotations JSON config', () => {
@@ -658,12 +705,12 @@ describe('Macro: Chart', () => {
658
705
  });
659
706
 
660
707
  test('THEN: it renders the footnotes', () => {
661
- expect($('.ons-chart__footnotes').text()).toContain('1');
662
- expect($('.ons-chart__footnotes').text()).toContain('A test annotation');
708
+ expect($('.ons-chart__annotations-footnotes').text()).toContain('1');
709
+ expect($('.ons-chart__annotations-footnotes').text()).toContain('A test annotation');
663
710
  });
664
711
 
665
712
  test('THEN: the footnotes are hidden from screen readers', () => {
666
- expect($('.ons-chart__footnotes').attr('aria-hidden')).toBe('true');
713
+ expect($('.ons-chart__annotations-footnotes').attr('aria-hidden')).toBe('true');
667
714
  });
668
715
 
669
716
  test('THEN: it includes the Annotations JSON config', () => {
@@ -687,12 +734,12 @@ describe('Macro: Chart', () => {
687
734
  });
688
735
 
689
736
  test('THEN: it renders the footnotes', () => {
690
- expect($('.ons-chart__footnotes').text()).toContain('1');
691
- expect($('.ons-chart__footnotes').text()).toContain('A test annotation');
737
+ expect($('.ons-chart__annotations-footnotes').text()).toContain('1');
738
+ expect($('.ons-chart__annotations-footnotes').text()).toContain('A test annotation');
692
739
  });
693
740
 
694
741
  test('THEN: the footnotes are hidden from screen readers', () => {
695
- expect($('.ons-chart__footnotes').attr('aria-hidden')).toBe('true');
742
+ expect($('.ons-chart__annotations-footnotes').attr('aria-hidden')).toBe('true');
696
743
  });
697
744
 
698
745
  test('THEN: it includes the Annotations JSON config', () => {
@@ -977,6 +1024,26 @@ describe('Macro: Chart', () => {
977
1024
  });
978
1025
  });
979
1026
  });
1027
+
1028
+ describe('GIVEN: Params: Footnotes', () => {
1029
+ describe('WHEN: footnotes are provided', () => {
1030
+ const $ = cheerio.load(
1031
+ renderComponent('chart', {
1032
+ ...EXAMPLE_AREA_CHART_PARAMS,
1033
+ footnotes: {
1034
+ title: 'Footnotes',
1035
+ content:
1036
+ '<ol><li>Non-store retailing refers to retailers that do not have a store presence. While the majority is made up of online retailers, it also includes other retailers, such as stalls and markets.</li><li>More data are available in our Retail Sales Index datasets.</li></ol>',
1037
+ },
1038
+ }),
1039
+ );
1040
+ test('THEN: it renders the footnotes', () => {
1041
+ expect($('#footnotes--area-chart-123').length).toBe(1);
1042
+ expect($('#footnotes--area-chart-123').find('ol').length).toBe(1);
1043
+ expect($('#footnotes--area-chart-123').text()).toContain('Footnotes');
1044
+ });
1045
+ });
1046
+ });
980
1047
  });
981
1048
 
982
1049
  describe('FOR: Boxplot Chart', () => {
@@ -1304,16 +1371,16 @@ describe('Macro: Chart', () => {
1304
1371
  });
1305
1372
 
1306
1373
  test('THEN: it renders the footnotes sequentially', () => {
1307
- expect($('.ons-chart__footnotes').text()).toContain('1');
1308
- expect($('.ons-chart__footnotes').text()).toContain('A test point annotation');
1309
- expect($('.ons-chart__footnotes').text()).toContain('2');
1310
- expect($('.ons-chart__footnotes').text()).toContain('A test x axis range annotation');
1311
- expect($('.ons-chart__footnotes').text()).toContain('3');
1312
- expect($('.ons-chart__footnotes').text()).toContain('A test y axis range annotation with the label inside');
1313
- expect($('.ons-chart__footnotes').text()).toContain('4');
1314
- expect($('.ons-chart__footnotes').text()).toContain('A test x axis reference line annotation');
1315
- expect($('.ons-chart__footnotes').text()).toContain('5');
1316
- expect($('.ons-chart__footnotes').text()).toContain('A test y axis reference line annotation');
1374
+ expect($('.ons-chart__annotations-footnotes').text()).toContain('1');
1375
+ expect($('.ons-chart__annotations-footnotes').text()).toContain('A test point annotation');
1376
+ expect($('.ons-chart__annotations-footnotes').text()).toContain('2');
1377
+ expect($('.ons-chart__annotations-footnotes').text()).toContain('A test x axis range annotation');
1378
+ expect($('.ons-chart__annotations-footnotes').text()).toContain('3');
1379
+ expect($('.ons-chart__annotations-footnotes').text()).toContain('A test y axis range annotation with the label inside');
1380
+ expect($('.ons-chart__annotations-footnotes').text()).toContain('4');
1381
+ expect($('.ons-chart__annotations-footnotes').text()).toContain('A test x axis reference line annotation');
1382
+ expect($('.ons-chart__annotations-footnotes').text()).toContain('5');
1383
+ expect($('.ons-chart__annotations-footnotes').text()).toContain('A test y axis reference line annotation');
1317
1384
  });
1318
1385
  });
1319
1386
  });
@@ -1456,4 +1523,190 @@ describe('Macro: Chart', () => {
1456
1523
  });
1457
1524
  });
1458
1525
  });
1526
+
1527
+ describe('FOR: Iframe chart', () => {
1528
+ describe('GIVEN: Params: Iframe chart', () => {
1529
+ describe('WHEN: an iframe url param is provided', () => {
1530
+ const $ = cheerio.load(renderComponent('chart', EXAMPLE_IFRAME_CHART_PARAMS));
1531
+
1532
+ test('THEN: it passes jest-axe checks', async () => {
1533
+ const results = await axe($.html());
1534
+ expect(results).toHaveNoViolations();
1535
+ });
1536
+
1537
+ test('THEN: it renders the iframe', () => {
1538
+ expect($('.ons-chart__iframe-wrapper').length).toBe(1);
1539
+ });
1540
+
1541
+ test('THEN: it includes the iframe title as a data attribute', () => {
1542
+ const iframe = $('.ons-chart__iframe-wrapper');
1543
+ expect(iframe.attr('data-title')).toBe(EXAMPLE_IFRAME_CHART_PARAMS.title);
1544
+ });
1545
+
1546
+ test('THEN: the theme parameter is ignored', () => {
1547
+ const $ = cheerio.load(
1548
+ renderComponent('chart', {
1549
+ ...EXAMPLE_IFRAME_CHART_PARAMS,
1550
+ theme: 'secondary',
1551
+ }),
1552
+ );
1553
+
1554
+ expect($('[data-highcharts-theme]').length).toBe(0);
1555
+ });
1556
+
1557
+ test('THEN: the percentageHeightDesktop and percentageHeightMobile parameters are ignored', () => {
1558
+ const $ = cheerio.load(
1559
+ renderComponent('chart', {
1560
+ ...EXAMPLE_IFRAME_CHART_PARAMS,
1561
+ percentageHeightDesktop: 50,
1562
+ percentageHeightMobile: 10,
1563
+ }),
1564
+ );
1565
+
1566
+ expect($('[data-highcharts-percentage-height-desktop]').length).toBe(0);
1567
+ expect($('[data-highcharts-percentage-height-mobile]').length).toBe(0);
1568
+ });
1569
+
1570
+ test('THEN: the tickIntervalDesktop and tickIntervalMobile parameters are ignored', () => {
1571
+ const $ = cheerio.load(
1572
+ renderComponent('chart', {
1573
+ ...EXAMPLE_IFRAME_CHART_PARAMS,
1574
+ xAxis: {
1575
+ tickIntervalDesktop: 10,
1576
+ tickIntervalMobile: 5,
1577
+ },
1578
+ yAxis: {
1579
+ tickIntervalDesktop: 10,
1580
+ tickIntervalMobile: 5,
1581
+ },
1582
+ }),
1583
+ );
1584
+
1585
+ expect($('[data-highcharts-x-axis-tick-interval-desktop]').length).toBe(0);
1586
+ expect($('[data-highcharts-x-axis-tick-interval-mobile]').length).toBe(0);
1587
+ expect($('[data-highcharts-y-axis-tick-interval-desktop]').length).toBe(0);
1588
+ expect($('[data-highcharts-y-axis-tick-interval-mobile]').length).toBe(0);
1589
+ });
1590
+
1591
+ test('THEN: the tickIntervalDesktop and tickIntervalMobile parameters are ignored', () => {
1592
+ const $ = cheerio.load(
1593
+ renderComponent('chart', {
1594
+ ...EXAMPLE_IFRAME_CHART_PARAMS,
1595
+ estimateLineLabel: 'Estimated value',
1596
+ uncertaintyRangeLabel: '95% Confidence Interval',
1597
+ }),
1598
+ );
1599
+
1600
+ expect($('[data-highcharts-estimate-line-label]').length).toBe(0);
1601
+ expect($('[data-highcharts-uncertainty-range-label]').length).toBe(0);
1602
+ });
1603
+
1604
+ test('THEN: the customReferenceLineValue parameter is ignored', () => {
1605
+ const $ = cheerio.load(
1606
+ renderComponent('chart', {
1607
+ ...EXAMPLE_IFRAME_CHART_PARAMS,
1608
+ yAxis: {
1609
+ customReferenceLineValue: 10,
1610
+ },
1611
+ }),
1612
+ );
1613
+
1614
+ expect($('[data-highcharts-custom-reference-line-value]').length).toBe(0);
1615
+ });
1616
+
1617
+ test('THEN: the legend for boxplot charts is not rendered', () => {
1618
+ const $ = cheerio.load(
1619
+ renderComponent('chart', {
1620
+ ...EXAMPLE_IFRAME_CHART_PARAMS,
1621
+ chartType: 'boxplot',
1622
+ legend: true,
1623
+ estimateLineLabel: 'Estimated value',
1624
+ uncertaintyRangeLabel: '95% Confidence Interval',
1625
+ }),
1626
+ );
1627
+
1628
+ expect($('.ons-chart__boxplot-legend').length).toBe(0);
1629
+ });
1630
+
1631
+ test('THEN: the Highcharts config is not included', () => {
1632
+ const configScript = $(`script[data-highcharts-config--iframe-chart-123]`).html();
1633
+ expect(configScript).toBeNull();
1634
+ });
1635
+
1636
+ test('THEN: the annotations footnotes and scripts are not rendered', () => {
1637
+ const $ = cheerio.load(
1638
+ renderComponent('chart', {
1639
+ ...EXAMPLE_IFRAME_CHART_PARAMS,
1640
+ annotations: [
1641
+ {
1642
+ text: 'A test point annotation',
1643
+ point: { x: 2, y: 3 },
1644
+ labelOffsetX: 10,
1645
+ labelOffsetY: -50,
1646
+ },
1647
+ ],
1648
+ rangeAnnotations: [
1649
+ {
1650
+ text: 'A test x axis range annotation',
1651
+ range: { axisValue1: 10, axisValue2: 15 },
1652
+ axis: 'x',
1653
+ labelOffsetX: 150,
1654
+ labelOffsetY: 0,
1655
+ },
1656
+ {
1657
+ text: 'A test y axis range annotation with the label inside',
1658
+ range: { axisValue1: 5, axisValue2: 10 },
1659
+ axis: 'y',
1660
+ labelInside: true,
1661
+ labelWidth: 250,
1662
+ },
1663
+ ],
1664
+ referenceLineAnnotations: [
1665
+ {
1666
+ text: 'A test x axis reference line annotation',
1667
+ value: 34,
1668
+ axis: 'x',
1669
+ },
1670
+ {
1671
+ text: 'A test y axis reference line annotation',
1672
+ value: 12,
1673
+ axis: 'y',
1674
+ labelWidth: 100,
1675
+ },
1676
+ ],
1677
+ }),
1678
+ );
1679
+
1680
+ expect($('[data-annotations-footnotes]').length).toBe(0);
1681
+ expect($('[data-highcharts-annotations--iframe-chart-123]').length).toBe(0);
1682
+ expect($('[data-highcharts-range-annotations--iframe-chart-123]').length).toBe(0);
1683
+ expect($('[data-highcharts-reference-line-annotations--iframe-chart-123]').length).toBe(0);
1684
+ });
1685
+
1686
+ test('THEN: invalid chart type is ignored', () => {
1687
+ const $ = cheerio.load(
1688
+ renderComponent('chart', {
1689
+ ...EXAMPLE_IFRAME_CHART_PARAMS,
1690
+ chartType: 'foobar',
1691
+ }),
1692
+ );
1693
+
1694
+ expect($('[data-invalid-chart-type]').length).toBe(0);
1695
+ });
1696
+ });
1697
+
1698
+ describe('WHEN: Params: fallbackImageUrl is set', () => {
1699
+ const $ = cheerio.load(
1700
+ renderComponent('chart', {
1701
+ ...EXAMPLE_IFRAME_CHART_PARAMS,
1702
+ fallbackImageUrl: '/img/small/line-chart-screenshot.png',
1703
+ }),
1704
+ );
1705
+ const iframe = $(`.ons-chart__iframe-wrapper`);
1706
+ test('THEN: the iframe is hidden when JavaScript is disabled', () => {
1707
+ expect(iframe.attr('class')).toContain('ons-chart__non-js-hide');
1708
+ });
1709
+ });
1710
+ });
1711
+ });
1459
1712
  });
@@ -49,7 +49,7 @@ class AnnotationsOptions {
49
49
  borderColor: 'transparent',
50
50
  // We use css styling for the rounded number annotation at mobile
51
51
  useHTML: true,
52
- className: 'ons-chart__footnote-number',
52
+ className: 'ons-chart__annotations-footnotes-number',
53
53
  },
54
54
  draggable: '',
55
55
  },
@@ -38,6 +38,7 @@ class BarChart {
38
38
  // Update the category label colours for bar charts
39
39
  labels: {
40
40
  style: {
41
+ textOverflow: 'ellipsis',
41
42
  color: this.constants.categoryLabelColor,
42
43
  },
43
44
  useHTML: false,
@@ -70,6 +71,7 @@ class BarChart {
70
71
  };
71
72
 
72
73
  // Updates the config to move the data labels inside the bars, but only if the bar is wide enough
74
+ // See the checkHideDataLabels function in chart.js for more details about when this function is run
73
75
  // This also runs when the chart is resized
74
76
  postLoadDataLabels = (currentChart) => {
75
77
  const insideOptions = this.getBarChartLabelsInsideOptions();
@@ -0,0 +1,8 @@
1
+ import ChartIframeResize from './chart-iframe-resize';
2
+ import domready from '../../js/domready';
3
+
4
+ domready(async () => {
5
+ [ChartIframeResize].forEach((Component) => {
6
+ document.querySelectorAll(Component.selector()).forEach((el) => new Component(el));
7
+ });
8
+ });
@@ -0,0 +1,16 @@
1
+ import pym from 'pym.js';
2
+
3
+ class ChartIframeResize {
4
+ static selector() {
5
+ return '.ons-chart__iframe-wrapper';
6
+ }
7
+
8
+ constructor(node) {
9
+ this.node = node;
10
+ new pym.Parent(this.node.getAttribute('id'), this.node.dataset.url, {
11
+ title: this.node.dataset.title,
12
+ });
13
+ }
14
+ }
15
+
16
+ export default ChartIframeResize;
@@ -1,8 +1,10 @@
1
1
  import HighchartsBaseChart from './chart';
2
2
  import domready from '../../js/domready';
3
3
 
4
- domready(async () => {
5
- [HighchartsBaseChart].forEach((Component) => {
6
- document.querySelectorAll(Component.selector()).forEach((el) => new Component(el));
4
+ document.fonts.ready.then(() => {
5
+ domready(async () => {
6
+ [HighchartsBaseChart].forEach((Component) => {
7
+ document.querySelectorAll(Component.selector()).forEach((el) => new Component(el));
8
+ });
7
9
  });
8
10
  });
@@ -31,6 +31,11 @@ class HighchartsBaseChart {
31
31
  console.error('No chart node found');
32
32
  return;
33
33
  }
34
+
35
+ // Add a CSS class to the chart based on the chart type (e.g., 'bar-chart-container', 'line-chart-container')
36
+ // This allows type-specific styling in CSS.
37
+ chartNode.classList.add(`${this.chartType}-chart-container`);
38
+
34
39
  this.id = this.node.dataset.highchartsId;
35
40
  this.useStackedLayout = this.node.hasAttribute('data-highcharts-use-stacked-layout');
36
41
  this.config = JSON.parse(this.node.querySelector(`[data-highcharts-config--${this.id}]`).textContent);
@@ -187,9 +192,15 @@ class HighchartsBaseChart {
187
192
  };
188
193
 
189
194
  // Check if the data labels should be hidden
190
- // They should be hidden for clustered bar charts with more than 2 series, and also for stacked bar charts
195
+ // They should be hidden where there are more than 20 data points in a series, for clustered bar charts with more than 2 series, and also for stacked bar charts
191
196
  checkHideDataLabels = () => {
192
- return (this.chartType === 'bar' && this.config.series.length > 2) || this.useStackedLayout === true;
197
+ let hideDataLabels = (this.chartType === 'bar' && this.config.series.length > 2) || this.useStackedLayout === true;
198
+ this.config.series.forEach((series) => {
199
+ if (series.data.length > 20) {
200
+ hideDataLabels = true;
201
+ }
202
+ });
203
+ return hideDataLabels;
193
204
  };
194
205
 
195
206
  // Adjust font size and annotations for smaller width of chart
@@ -63,6 +63,7 @@
63
63
  "title": "Y axis title"
64
64
  },
65
65
  "percentageHeightDesktop": 50,
66
- "percentageHeightMobile": 120
66
+ "percentageHeightMobile": 120,
67
+ "fallbackImageUrl": '/img/small/area-chart-screenshot.png'
67
68
  })
68
69
  }}
@@ -26,6 +26,10 @@
26
26
  }
27
27
  ]
28
28
  },
29
+ "footnotes": {
30
+ "title": "Footnotes",
31
+ "content": "<ol><li>Non-store retailing refers to retailers that do not have a store presence. While the majority is made up of online retailers, it also includes other retailers, such as stalls and markets.</li><li>More data are available in our Retail Sales Index datasets.</li></ol>"
32
+ },
29
33
  "xAxis": {
30
34
  "categories": [
31
35
  "All retailing",
@@ -0,0 +1,33 @@
1
+ {% from "components/chart/_macro.njk" import onsChart %}
2
+
3
+ {# Important note: the example visualisation used here by the iframeUrl parameter
4
+ may not be available in the future once Florence is decommissioned. #}
5
+
6
+ {{
7
+ onsChart({
8
+ "description": "Volume sales, seasonally adjusted, Great Britain, January 2022 to January 2025",
9
+ "title": "Food stores showed a strong rise on the month, while non-food stores fell",
10
+ "subtitle": "Figure 6: Upward contribution from housing and household services (including energy) saw the annual CPIH inflation rate rise",
11
+ "id": "uuid",
12
+ "caption": "Source: Monthly Business Survey, Retail Sales Inquiry from the Office for National Statistics",
13
+ "download": {
14
+ 'title': 'Download Figure 1 data',
15
+ 'itemsList': [
16
+ {
17
+ "text": "Excel spreadsheet (XLSX format, 18KB)",
18
+ "url": "#"
19
+ },
20
+ {
21
+ "text": "Simple text file (CSV format, 25KB)",
22
+ "url": "#"
23
+ },
24
+ {
25
+ "text": "Image (PNG format, 25KB)",
26
+ "url": "#"
27
+ }
28
+ ]
29
+ },
30
+ "iframeUrl": "https://www.ons.gov.uk/visualisations/dvc3294/fig01/index.html",
31
+ "fallbackImageUrl": "/img/small/line-chart-screenshot.png"
32
+ })
33
+ }}
@@ -154,7 +154,9 @@
154
154
  'Aug 2024',
155
155
  'Sep 2024',
156
156
  'Oct 2024'
157
- ]
157
+ ],
158
+ "tickIntervalDesktop": 10,
159
+ "tickIntervalMobile": 30
158
160
  },
159
161
  "yAxis": {
160
162
  "title": "Sales",
@@ -27,6 +27,10 @@
27
27
  "url": "#"
28
28
  }
29
29
  ]},
30
+ "footnotes": {
31
+ "title": "Footnotes",
32
+ "content": "<ol><li>Non-store retailing refers to retailers that do not have a store presence. While the majority is made up of online retailers, it also includes other retailers, such as stalls and markets.</li><li>More data are available in our Retail Sales Index datasets.</li></ol>"
33
+ },
30
34
  "legend": true,
31
35
  "xAxis": {
32
36
  "title": "Year",
@@ -218,6 +222,7 @@
218
222
  }
219
223
  ],
220
224
  "percentageHeightDesktop": 35,
221
- "percentageHeightMobile": 90
225
+ "percentageHeightMobile": 90,
226
+ "fallbackImageUrl": '/img/small/line-chart-screenshot.png'
222
227
  })
223
228
  }}
@@ -27,6 +27,10 @@
27
27
  "url": "#"
28
28
  }
29
29
  ]},
30
+ "footnotes": {
31
+ "title": "Footnotes",
32
+ "content": "<ol><li>Non-store retailing refers to retailers that do not have a store presence. While the majority is made up of online retailers, it also includes other retailers, such as stalls and markets.</li><li>More data are available in our Retail Sales Index datasets.</li></ol>"
33
+ },
30
34
  "xAxis": {
31
35
  "title": "Height"
32
36
  },
@@ -65,7 +65,7 @@ class RangeAnnotationsOptions {
65
65
  // So that if we have both types of annotations, the numbers will be sequential
66
66
  text: `${annotationsLength + index + 1}`,
67
67
  useHTML: true,
68
- className: 'ons-chart__footnote-number',
68
+ className: 'ons-chart__annotations-footnotes-number',
69
69
  allowOverlap: true,
70
70
  style: {
71
71
  color: this.constants.labelColor,
@@ -58,7 +58,7 @@ class ReferenceLineAnnotationsOptions {
58
58
  // So that if we have more than one type of annotations, the numbers will be sequential
59
59
  text: `${annotationsLength + index + 1}`,
60
60
  useHTML: true,
61
- className: 'ons-chart__footnote-number',
61
+ className: 'ons-chart__annotations-footnotes-number',
62
62
  allowOverlap: true,
63
63
  style: {
64
64
  color: this.constants.labelColor,
@@ -164,9 +164,9 @@ describe('macro: checkboxes', () => {
164
164
  it('renders the text area with expected parameters', () => {
165
165
  const $ = cheerio.load(renderComponent('checkboxes', EXAMPLE_CHECKBOX_ITEM_CHECKBOXES_WITH_TEXTAREA));
166
166
  expect($('.ons-input--textarea').attr('name')).toBe('other answer');
167
- expect($('.ons-input--textarea').attr('data-char-check-num')).toBe('300');
168
- expect($('.ons-input__limit').attr('data-charcount-singular')).toBe('You have {x} character remaining');
169
- expect($('.ons-input__limit').attr('data-charcount-plural')).toBe('You have {x} characters remaining');
167
+ expect($('.ons-input--textarea').attr('data-message-check-num')).toBe('300');
168
+ expect($('.ons-input__limit').attr('data-message-singular')).toBe('You have {x} character remaining');
169
+ expect($('.ons-input__limit').attr('data-message-plural')).toBe('You have {x} characters remaining');
170
170
  });
171
171
  });
172
172
 
@@ -44,10 +44,9 @@
44
44
  {% if params.autocomplete %}autocomplete="{{ params.autocomplete }}"{% endif %}
45
45
  {% if params.accessiblePlaceholder %}placeholder="{{ params.label.text }}"{% endif %}
46
46
  {% if params.charCheckLimit %}
47
- data-char-check-ref="{{ params.id }}-check" data-char-check-num="{{ params.charCheckLimit.limit }}"
47
+ data-message-check-ref="{{ params.id }}-check" data-message-check-num="{{ params.charCheckLimit.limit }}"
48
48
  aria-describedby="{{ params.id }}-check"
49
49
  {% endif %}
50
- {% if params.charCheckLimit and params.charCheckLimit.charcheckCountdown %}data-char-check-countdown="true"{% endif %}
51
50
  {% if params.attributes %}{% for attribute, value in (params.attributes.items() if params.attributes is mapping and params.attributes.items else params.attributes) %}{{ ' ' }}{{ attribute }}{% if value %}="{{ value }}"{% endif %}{% endfor %}{% endif %}
52
51
  {% if params.label and params.label.description %}{% if params.label.id %}aria-describedby="{{ params.label.id }}-description-hint"{% else %}aria-describedby="description-hint"{% endif %}{% endif %}
53
52
  />
@@ -570,36 +570,16 @@ describe('macro: input', () => {
570
570
  expect($('.ons-input').attr('maxlength')).toBe('200');
571
571
  });
572
572
 
573
- it('does not have `data-char-check-countdown` attribute when `charcheckCountdown` is not provided', () => {
574
- const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_CHARACTER_LIMIT));
575
-
576
- expect($('.ons-input').attr('data-char-check-countdown')).toBe(undefined);
577
- });
578
-
579
- it('has `data-char-check-countdown` attribute when `charcheckCountdown` is true', () => {
580
- const $ = cheerio.load(
581
- renderComponent('input', {
582
- ...EXAMPLE_INPUT_WITH_CHARACTER_LIMIT,
583
- charCheckLimit: {
584
- ...EXAMPLE_INPUT_WITH_CHARACTER_LIMIT.charCheckLimit,
585
- charcheckCountdown: true,
586
- },
587
- }),
588
- );
589
-
590
- expect($('.ons-input').attr('data-char-check-countdown')).toBe('true');
591
- });
592
-
593
573
  it('has data attribute which references the character limit component', () => {
594
574
  const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_CHARACTER_LIMIT));
595
575
 
596
- expect($('.ons-input').attr('data-char-check-ref')).toBe('example-id-check');
576
+ expect($('.ons-input').attr('data-message-check-ref')).toBe('example-id-check');
597
577
  });
598
578
 
599
579
  it('has data attribute which defines limit for character check', () => {
600
580
  const $ = cheerio.load(renderComponent('input', EXAMPLE_INPUT_WITH_CHARACTER_LIMIT));
601
581
 
602
- expect($('.ons-input').attr('data-char-check-num')).toBe('200');
582
+ expect($('.ons-input').attr('data-message-check-num')).toBe('200');
603
583
  });
604
584
 
605
585
  it('has `aria-describedby` attribute which references the character limit component', () => {