@ons/design-system 72.9.1 → 72.10.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 (56) hide show
  1. package/components/button/_button.scss +10 -0
  2. package/components/card/_macro.njk +3 -3
  3. package/components/card/_macro.spec.js +109 -252
  4. package/components/card/_test_examples.js +56 -0
  5. package/components/chart/_chart.scss +74 -1
  6. package/components/chart/_macro.njk +64 -5
  7. package/components/chart/_macro.spec.js +405 -0
  8. package/components/chart/bar-chart.js +2 -2
  9. package/components/chart/boxplot.js +37 -0
  10. package/components/chart/chart-constants.js +13 -0
  11. package/components/chart/chart.js +98 -50
  12. package/components/chart/columnrange-chart.js +94 -0
  13. package/components/chart/common-chart-options.js +28 -19
  14. package/components/chart/example-bar-chart-with-annotations.njk +1 -1
  15. package/components/chart/example-bar-chart-with-point-range-and-reference-line-annotations.njk +95 -0
  16. package/components/chart/example-bar-with-confidence-levels.njk +71 -0
  17. package/components/chart/example-clustered-column-chart.njk +1 -3
  18. package/components/chart/example-column-chart-with-annotations.njk +1 -1
  19. package/components/chart/example-column-chart-with-range-annotations.njk +64 -0
  20. package/components/chart/example-column-chart-with-reference-line-annotations.njk +64 -0
  21. package/components/chart/example-column-with-confidence-levels.njk +61 -0
  22. package/components/chart/example-line-chart-with-annotations.njk +3 -3
  23. package/components/chart/example-line-chart-with-markers.njk +1 -1
  24. package/components/chart/example-line-chart-with-range-annotations-inside.njk +238 -0
  25. package/components/chart/example-line-chart-with-range-annotations-outside-left-right.njk +240 -0
  26. package/components/chart/example-line-chart-with-range-annotations-outside-top-bottom.njk +239 -0
  27. package/components/chart/example-line-chart-with-reference-line-annotations.njk +236 -0
  28. package/components/chart/example-scatter-chart.njk +1 -1
  29. package/components/chart/range-annotations-options.js +216 -0
  30. package/components/chart/reference-line-annotations-options.js +93 -0
  31. package/components/chart/scatter-chart.js +15 -0
  32. package/components/chart/specific-chart-options.js +1 -1
  33. package/components/chart/utilities.js +96 -0
  34. package/components/details-panel/_macro.njk +5 -1
  35. package/components/details-panel/_macro.spec.js +22 -0
  36. package/components/document-list/_document-list.scss +5 -13
  37. package/components/document-list/_macro.njk +14 -17
  38. package/components/document-list/_macro.spec.js +3 -3
  39. package/components/fieldset/_macro.spec.js +200 -120
  40. package/components/fieldset/_test_examples.js +15 -0
  41. package/components/header/_header.scss +11 -0
  42. package/components/header/_macro.njk +11 -6
  43. package/components/header/_macro.spec.js +113 -3
  44. package/components/hero/_macro.spec.js +1 -1
  45. package/components/icon/_macro.njk +14 -24
  46. package/components/language-selector/_macro.njk +6 -3
  47. package/components/navigation/navigation.js +57 -58
  48. package/components/navigation/navigation.spec.js +6 -10
  49. package/components/summary/_macro.njk +4 -1
  50. package/components/table-of-contents/_macro.njk +1 -1
  51. package/components/table-of-contents/_macro.spec.js +7 -0
  52. package/components/table-of-contents/table-of-contents.js +43 -26
  53. package/css/main.css +1 -1
  54. package/package.json +1 -1
  55. package/scripts/main.es5.js +1 -1
  56. package/scripts/main.js +1 -1
@@ -1,6 +1,7 @@
1
1
  import Highcharts from 'highcharts';
2
2
  import 'highcharts/modules/accessibility';
3
3
  import 'highcharts/modules/annotations';
4
+ import 'highcharts/highcharts-more';
4
5
 
5
6
  import CommonChartOptions from './common-chart-options';
6
7
  import SpecificChartOptions from './specific-chart-options';
@@ -8,8 +9,13 @@ import LineChart from './line-chart';
8
9
  import BarChart from './bar-chart';
9
10
  import ColumnChart from './column-chart';
10
11
  import ScatterChart from './scatter-chart';
12
+ import Boxplot from './boxplot';
11
13
  import AnnotationsOptions from './annotations-options';
14
+ import RangeAnnotationsOptions from './range-annotations-options';
15
+ import ReferenceLineAnnotationsOptions from './reference-line-annotations-options';
16
+ import { preparePlotLinesAndBands, mergeConfigs } from './utilities';
12
17
  import AreaChart from './area-chart';
18
+ import ColumnRangeChart from './columnrange-chart';
13
19
 
14
20
  class HighchartsBaseChart {
15
21
  static selector() {
@@ -29,23 +35,46 @@ class HighchartsBaseChart {
29
35
  this.useStackedLayout = this.node.hasAttribute('data-highcharts-use-stacked-layout');
30
36
  this.config = JSON.parse(this.node.querySelector(`[data-highcharts-config--${this.id}]`).textContent);
31
37
  if (this.node.querySelector(`[data-highcharts-annotations--${this.id}]`)) {
32
- const annotations = JSON.parse(this.node.querySelector(`[data-highcharts-annotations--${this.id}]`).textContent);
33
- this.annotationsOptions = new AnnotationsOptions(annotations);
38
+ this.annotations = JSON.parse(this.node.querySelector(`[data-highcharts-annotations--${this.id}]`).textContent);
39
+ this.annotationsOptions = new AnnotationsOptions(this.annotations);
40
+ }
41
+ if (this.node.querySelector(`[data-highcharts-range-annotations--${this.id}]`)) {
42
+ this.rangeAnnotations = JSON.parse(this.node.querySelector(`[data-highcharts-range-annotations--${this.id}]`).textContent);
43
+ this.rangeAnnotationsOptions = new RangeAnnotationsOptions(this.rangeAnnotations);
44
+ }
45
+ if (this.node.querySelector(`[data-highcharts-reference-line-annotations--${this.id}]`)) {
46
+ this.referenceLineAnnotations = JSON.parse(
47
+ this.node.querySelector(`[data-highcharts-reference-line-annotations--${this.id}]`).textContent,
48
+ );
49
+ this.referenceLineAnnotationsOptions = new ReferenceLineAnnotationsOptions(this.referenceLineAnnotations);
34
50
  }
35
51
  this.percentageHeightDesktop = this.node.dataset.highchartsPercentageHeightDesktop;
36
52
  this.percentageHeightMobile = this.node.dataset.highchartsPercentageHeightMobile;
37
- this.xAxisTickIntervalMobile = parseInt(this.node.dataset.highchartsXAxisTickIntervalMobile);
38
- this.xAxisTickIntervalDesktop = parseInt(this.node.dataset.highchartsXAxisTickIntervalDesktop);
39
- this.yAxisTickIntervalMobile = parseInt(this.node.dataset.highchartsYAxisTickIntervalMobile);
40
- this.yAxisTickIntervalDesktop = parseInt(this.node.dataset.highchartsYAxisTickIntervalDesktop);
53
+ this.xAxisTickIntervalMobile = this.node.dataset.highchartsXAxisTickIntervalMobile
54
+ ? parseInt(this.node.dataset.highchartsXAxisTickIntervalMobile)
55
+ : undefined;
56
+ this.xAxisTickIntervalDesktop = this.node.dataset.highchartsXAxisTickIntervalDesktop
57
+ ? parseInt(this.node.dataset.highchartsXAxisTickIntervalDesktop)
58
+ : undefined;
59
+ this.yAxisTickIntervalMobile = this.node.dataset.highchartsYAxisTickIntervalMobile
60
+ ? parseInt(this.node.dataset.highchartsYAxisTickIntervalMobile)
61
+ : undefined;
62
+ this.yAxisTickIntervalDesktop = this.node.dataset.highchartsYAxisTickIntervalDesktop
63
+ ? parseInt(this.node.dataset.highchartsYAxisTickIntervalDesktop)
64
+ : undefined;
41
65
  this.commonChartOptions = new CommonChartOptions(this.xAxisTickIntervalDesktop, this.yAxisTickIntervalDesktop);
66
+ this.estimateLineLabel = this.node.dataset.highchartsEstimateLineLabel;
67
+ this.uncertainyRangeLabel = this.node.dataset.highchartsUncertaintyRangeLabel;
42
68
  this.specificChartOptions = new SpecificChartOptions(this.theme, this.chartType, this.config);
43
69
  this.lineChart = new LineChart();
44
70
  this.barChart = new BarChart();
45
71
  this.columnChart = new ColumnChart();
46
72
  this.areaChart = new AreaChart();
47
73
  this.scatterChart = new ScatterChart();
74
+ this.columnRangeChart = new ColumnRangeChart();
75
+ this.boxplot = new Boxplot();
48
76
  this.extraLines = this.checkForExtraLines();
77
+ this.extraScatter = this.checkForExtraScatter();
49
78
  if (window.isCommonChartOptionsDefined === undefined) {
50
79
  this.setCommonChartOptions();
51
80
  window.isCommonChartOptionsDefined = true;
@@ -54,6 +83,7 @@ class HighchartsBaseChart {
54
83
  this.setSpecificChartOptions();
55
84
  this.setResponsiveOptions();
56
85
  this.setLoadEvent();
86
+ this.setRenderEvent();
57
87
  this.setWindowResizeEvent();
58
88
  this.chart = Highcharts.chart(chartNode, this.config);
59
89
  }
@@ -63,83 +93,69 @@ class HighchartsBaseChart {
63
93
  return this.chartType === 'line' ? 0 : this.config.series.filter((series) => series.type === 'line').length;
64
94
  };
65
95
 
96
+ // Check for the number of extra line series in the config
97
+ checkForExtraScatter = () => {
98
+ return this.chartType === 'scatter' ? 0 : this.config.series.filter((series) => series.type === 'scatter').length;
99
+ };
100
+
66
101
  // Set up the global Highcharts options which are used for all charts
67
102
  setCommonChartOptions = () => {
68
103
  const chartOptions = this.commonChartOptions.getOptions();
69
104
  Highcharts.setOptions(chartOptions);
70
105
  };
71
106
 
72
- // Utility function to merge two configs together
73
- mergeConfigs = (baseConfig, newConfig) => {
74
- // If newConfig is null/undefined, return baseConfig
75
- if (!newConfig) return baseConfig;
76
-
77
- // Create a new object to store the merged result
78
- const merged = { ...baseConfig };
79
-
80
- // Iterate through all keys in newConfig
81
- Object.keys(newConfig).forEach((key) => {
82
- // Get values from both configs for this key
83
- const baseValue = merged[key];
84
- const newValue = newConfig[key];
85
-
86
- // If both values are objects (and not null), recursively merge them
87
- if (
88
- baseValue &&
89
- newValue &&
90
- typeof baseValue === 'object' &&
91
- typeof newValue === 'object' &&
92
- !Array.isArray(baseValue) &&
93
- !Array.isArray(newValue)
94
- ) {
95
- merged[key] = this.mergeConfigs(baseValue, newValue);
96
- } else {
97
- // For non-objects and arrays use the new value
98
- // If the new value is null/undefined, use the base value
99
- merged[key] = newValue ?? baseValue;
100
- }
101
- });
102
-
103
- return merged;
104
- };
105
-
106
107
  // Set up options for specific charts and chart types
107
108
  setSpecificChartOptions = () => {
108
109
  const specificChartOptions = this.specificChartOptions.getOptions();
109
110
  const lineChartOptions = this.lineChart.getLineChartOptions();
110
111
  const barChartOptions = this.barChart.getBarChartOptions(this.useStackedLayout);
112
+ const columnRangeChartOptions = this.columnRangeChart.getColumnRangeChartOptions();
111
113
  const columnChartOptions = this.columnChart.getColumnChartOptions(this.config, this.useStackedLayout, this.extraLines);
112
114
  const areaChartOptions = this.areaChart.getAreaChartOptions();
113
115
  const scatterChartOptions = this.scatterChart.getScatterChartOptions();
116
+ const boxplotOptions = this.boxplot.getBoxplotOptions(this.config, this.useStackedLayout, this.extraLines);
114
117
  // Merge specificChartOptions with the existing config
115
- this.config = this.mergeConfigs(this.config, specificChartOptions);
118
+ this.config = mergeConfigs(this.config, specificChartOptions);
116
119
 
117
120
  if (this.chartType === 'line') {
118
121
  // Merge the line chart options with the existing config
119
- this.config = this.mergeConfigs(this.config, lineChartOptions);
122
+ this.config = mergeConfigs(this.config, lineChartOptions);
120
123
  }
121
124
 
122
125
  if (this.chartType === 'bar') {
123
126
  // Merge the bar chart options with the existing config
124
- this.config = this.mergeConfigs(this.config, barChartOptions);
127
+ this.config = mergeConfigs(this.config, barChartOptions);
128
+ }
129
+ if (this.chartType === 'columnrange') {
130
+ // Merge the bar chart options with the existing config
131
+ this.config = mergeConfigs(this.config, columnRangeChartOptions);
125
132
  }
126
133
  if (this.chartType === 'column') {
127
134
  // Merge the column chart options with the existing config
128
- this.config = this.mergeConfigs(this.config, columnChartOptions);
135
+ this.config = mergeConfigs(this.config, columnChartOptions);
129
136
  }
130
137
  if (this.chartType === 'area') {
131
138
  // Merge the area chart options with the existing config
132
- this.config = this.mergeConfigs(this.config, areaChartOptions);
139
+ this.config = mergeConfigs(this.config, areaChartOptions);
133
140
  }
134
141
  if (this.chartType === 'scatter') {
135
142
  // Merge the scatter chart options with the existing config
136
- this.config = this.mergeConfigs(this.config, scatterChartOptions);
143
+ this.config = mergeConfigs(this.config, scatterChartOptions);
144
+ }
145
+ if (this.chartType === 'boxplot') {
146
+ // Merge the boxplot chart options with the existing config
147
+ this.config = mergeConfigs(this.config, boxplotOptions);
137
148
  }
138
149
 
139
150
  if (this.extraLines > 0) {
140
- this.config = this.mergeConfigs(this.config, this.lineChart.getLineChartOptions());
151
+ this.config = mergeConfigs(this.config, this.lineChart.getLineChartOptions());
141
152
  if (this.chartType === 'column') {
142
- this.config = this.mergeConfigs(this.config, columnChartOptions);
153
+ this.config = mergeConfigs(this.config, columnChartOptions);
154
+ }
155
+ }
156
+ if (this.extraScatter > 0) {
157
+ if (this.chartType === 'columnrange') {
158
+ this.config = mergeConfigs(this.config, columnRangeChartOptions);
143
159
  }
144
160
  }
145
161
 
@@ -158,19 +174,28 @@ class HighchartsBaseChart {
158
174
  // All responsive rules should be defined here to avoid overriding existing rules
159
175
  setResponsiveOptions = () => {
160
176
  let mobileChartOptions = this.commonChartOptions.getMobileOptions(this.xAxisTickIntervalMobile, this.yAxisTickIntervalMobile);
161
- if (this.chartType === 'column') {
177
+ if (this.chartType === 'column' || this.chartType === 'boxplot') {
162
178
  const mobileColumnChartOptions = this.columnChart.getColumnChartMobileOptions(
163
179
  this.config,
164
180
  this.useStackedLayout,
165
181
  this.extraLines,
166
182
  );
167
- mobileChartOptions = this.mergeConfigs(mobileChartOptions, mobileColumnChartOptions);
183
+ mobileChartOptions = mergeConfigs(mobileChartOptions, mobileColumnChartOptions);
168
184
  }
169
185
 
170
186
  if (!this.config.responsive) {
171
187
  this.config.responsive = {};
172
188
  }
173
189
 
190
+ const { desktopAllPlotLinesAndBands, mobileAllPlotLinesAndBands } = preparePlotLinesAndBands(
191
+ this.annotations,
192
+ this.rangeAnnotations,
193
+ this.rangeAnnotationsOptions,
194
+ this.referenceLineAnnotationsOptions,
195
+ this.commonChartOptions,
196
+ this.chartType,
197
+ );
198
+
174
199
  let rules = [
175
200
  {
176
201
  condition: {
@@ -190,6 +215,7 @@ class HighchartsBaseChart {
190
215
  },
191
216
  chartOptions: {
192
217
  annotations: this.annotationsOptions ? this.annotationsOptions.getAnnotationsOptionsMobile() : undefined,
218
+ ...(mobileAllPlotLinesAndBands != {} ? mobileAllPlotLinesAndBands : null),
193
219
  },
194
220
  },
195
221
  {
@@ -198,6 +224,7 @@ class HighchartsBaseChart {
198
224
  },
199
225
  chartOptions: {
200
226
  annotations: this.annotationsOptions ? this.annotationsOptions.getAnnotationsOptionsDesktop() : undefined,
227
+ ...(desktopAllPlotLinesAndBands != {} ? desktopAllPlotLinesAndBands : null),
201
228
  },
202
229
  },
203
230
  ];
@@ -230,6 +257,15 @@ class HighchartsBaseChart {
230
257
  if (this.chartType === 'scatter') {
231
258
  this.scatterChart.updateMarkers(currentChart);
232
259
  }
260
+ if (this.chartType === 'columnrange') {
261
+ this.columnRangeChart.updateColumnRangeChartHeight(this.config, currentChart);
262
+ this.commonChartOptions.hideDataLabels(currentChart.series);
263
+
264
+ if (this.extraScatter > 0) {
265
+ const scatterSeries = currentChart.series.filter((series) => series.type === 'scatter');
266
+ this.scatterChart.updateMarkersForConfidenceLevels(scatterSeries);
267
+ }
268
+ }
233
269
  if (this.chartType != 'bar') {
234
270
  this.commonChartOptions.adjustChartHeight(currentChart, this.percentageHeightDesktop, this.percentageHeightMobile);
235
271
  }
@@ -249,6 +285,18 @@ class HighchartsBaseChart {
249
285
  };
250
286
  };
251
287
 
288
+ setRenderEvent = () => {
289
+ if (!this.config.chart.events) {
290
+ this.config.chart.events = {};
291
+ }
292
+ this.config.chart.events.render = (event) => {
293
+ const currentChart = event.target;
294
+ if (this.rangeAnnotationsOptions) {
295
+ this.rangeAnnotationsOptions.addLine(currentChart);
296
+ }
297
+ };
298
+ };
299
+
252
300
  // Set resize events - throttled to 50ms
253
301
  // All resize events should be defined here to avoid overriding existing events
254
302
  setWindowResizeEvent = () => {
@@ -0,0 +1,94 @@
1
+ import ChartConstants from './chart-constants';
2
+
3
+ class ColumnRangeChart {
4
+ constructor() {
5
+ this.constants = ChartConstants.constants();
6
+ }
7
+
8
+ getColumnRangeChartOptions = () => {
9
+ return {
10
+ plotOptions: {
11
+ columnrange: {
12
+ color: this.constants.uncertaintyRangeColor, // Set the default color for the column range
13
+ pointWidth: 20, // Fixed bar height
14
+ pointPadding: 0,
15
+ groupPadding: 0,
16
+ borderWidth: 0,
17
+ borderRadius: 0,
18
+ dataLabels: {
19
+ enabled: false,
20
+ },
21
+ },
22
+ },
23
+ xAxis: {
24
+ // Update the category label colours for bar charts
25
+ labels: {
26
+ style: {
27
+ color: this.constants.categoryLabelColor,
28
+ },
29
+ useHTML: false,
30
+ },
31
+ // remove the tick marks for bar charts
32
+ tickWidth: 0,
33
+ tickLength: 0,
34
+ gridlineWidth: 0,
35
+ tickColor: 'transparent',
36
+ title: { align: 'high', textAlign: 'middle', reserveSpace: false, rotation: 0, y: -25, useHTML: true },
37
+ },
38
+ yAxis: {
39
+ labels: {
40
+ rotation: 0,
41
+ useHTML: true,
42
+ style: {
43
+ whiteSpace: 'nowrap',
44
+ color: this.constants.categoryLabelColor,
45
+ },
46
+ },
47
+ tickLength: 0,
48
+ tickWidth: 0,
49
+ tickColor: 'transparent',
50
+ gridlineWidth: 0,
51
+ title: {
52
+ // Override the y Axis title settings for bar charts where the y axis is horizontal
53
+ textAlign: 'right',
54
+ offset: undefined,
55
+ y: 0,
56
+ reserveSpace: true,
57
+ useHTML: false,
58
+ },
59
+ },
60
+ legend: {
61
+ symbolRadius: 0,
62
+ itemStyle: {
63
+ fontSize: this.constants.defaultFontSize,
64
+ color: this.constants.legendLabelColor,
65
+ },
66
+ },
67
+ };
68
+ };
69
+
70
+ // This updates the height of the vertical axis and overall chart to fit the number of categories
71
+ // Note that the vertical axis on a bar chart is the x axis
72
+ updateColumnRangeChartHeight = (config, currentChart) => {
73
+ const numberOfCategories = config.xAxis.categories.length;
74
+ let barHeight = 20; // Height of each individual bar - set in bar-chart-plot-options
75
+ let groupSpacing = 0; // Space we want between category groups, or between series groups for cluster charts
76
+ let categoriesTotalHeight = 0;
77
+ let totalSpaceHeight = 0;
78
+
79
+ groupSpacing = 14;
80
+ categoriesTotalHeight = numberOfCategories * barHeight;
81
+
82
+ totalSpaceHeight = numberOfCategories * groupSpacing;
83
+
84
+ config.xAxis.height = categoriesTotalHeight + totalSpaceHeight;
85
+ const totalHeight = currentChart.plotTop + config.xAxis.height + currentChart.marginBottom;
86
+ if (totalHeight !== currentChart.chartHeight) {
87
+ currentChart.setSize(null, totalHeight, false);
88
+ }
89
+
90
+ currentChart.redraw();
91
+ };
92
+ }
93
+
94
+ export default ColumnRangeChart;
@@ -81,15 +81,6 @@ class CommonChartOptions {
81
81
  },
82
82
  lineColor: this.constants.gridLineColor,
83
83
  gridLineColor: this.constants.gridLineColor,
84
- // Add zero line
85
- plotLines: [
86
- {
87
- color: this.constants.zeroLineColor,
88
- width: 1.5,
89
- value: 0,
90
- zIndex: 2,
91
- },
92
- ],
93
84
  // Add tick marks
94
85
  tickWidth: 1,
95
86
  tickLength: 6,
@@ -143,6 +134,25 @@ class CommonChartOptions {
143
134
 
144
135
  getOptions = () => this.options;
145
136
 
137
+ // TODO: A future ticket will add support for other plot lines which are not
138
+ // reference line annotations, and will be styled like the zero line
139
+ // See ticket https://jira.ons.gov.uk/browse/CCB-63
140
+ getPlotLines = () => {
141
+ // Add zero line
142
+ return {
143
+ yAxis: {
144
+ plotLines: [
145
+ {
146
+ color: this.constants.zeroLineColor,
147
+ width: 1.5,
148
+ value: 0,
149
+ zIndex: 2,
150
+ },
151
+ ],
152
+ },
153
+ };
154
+ };
155
+
146
156
  getMobileOptions = (xAxisTickInterval, yAxisTickInterval) => {
147
157
  return {
148
158
  xAxis: {
@@ -165,7 +175,7 @@ class CommonChartOptions {
165
175
  };
166
176
 
167
177
  disableLegendForSingleSeries = (config) => {
168
- if (config.series.length === 1) {
178
+ if (config.chart.type != 'boxplot' && config.series.length === 1) {
169
179
  config.legend = {
170
180
  enabled: false,
171
181
  };
@@ -183,20 +193,19 @@ class CommonChartOptions {
183
193
  const { label, symbol } = legendItem || {};
184
194
 
185
195
  if (seriesType === 'line') {
186
- symbol?.attr({
187
- x: 16, // Position the marker to the right of the line
188
- });
189
-
190
196
  label?.attr({
191
197
  x: 30, // Adjust label position to account for longer line
192
198
  });
193
199
  } else {
200
+ if (!symbol) return;
194
201
  // Set the symbol size for bar / column series
195
- symbol.attr({
196
- width: 12,
197
- height: 12,
198
- y: 8,
199
- });
202
+ else {
203
+ symbol.attr({
204
+ width: 12,
205
+ height: 12,
206
+ y: 8,
207
+ });
208
+ }
200
209
  }
201
210
  });
202
211
  }
@@ -52,7 +52,7 @@
52
52
  ],
53
53
  "annotations": [
54
54
  {
55
- "text": "A test annotation",
55
+ "text": "A test point annotation",
56
56
  "point": {"x": 2, "y": 3},
57
57
  "labelOffsetX": 40,
58
58
  "labelOffsetY": -30
@@ -0,0 +1,95 @@
1
+ {% from "components/chart/_macro.njk" import onsChart %}
2
+
3
+ {{
4
+ onsChart({
5
+ "chartType": "bar",
6
+ "description": "Volume sales, seasonally adjusted, Great Britain, January 2022 to January 2025",
7
+ "theme": "primary",
8
+ "title": "Food stores showed a strong rise on the month, while non-food stores fell",
9
+ "subtitle": "Figure 6: Upward contribution from housing and household services (including energy) saw the annual CPIH inflation rate rise",
10
+ "id": "uuid",
11
+ "caption": "Source: Monthly Business Survey, Retail Sales Inquiry from the Office for National Statistics",
12
+ "download": {
13
+ 'title': 'Download Figure 1 data',
14
+ 'itemsList': [
15
+ {
16
+ "text": "Excel spreadsheet (XLSX format, 18KB)",
17
+ "url": "#"
18
+ },
19
+ {
20
+ "text": "Simple text file (CSV format, 25KB)",
21
+ "url": "#"
22
+ },
23
+ {
24
+ "text": "Image (PNG format, 25KB)",
25
+ "url": "#"
26
+ }
27
+ ]
28
+ },
29
+ "xAxis": {
30
+ "categories": [
31
+ "All retailing",
32
+ "All retailing excluding Automotive fuel",
33
+ "Food stores",
34
+ "Department stores",
35
+ "Other non-food stores",
36
+ "Textile clothing \u0026 footwear stores",
37
+ "Household goods stores",
38
+ "Non-store retailing",
39
+ "Automotive fuel"
40
+ ],
41
+ "type": "linear"
42
+ },
43
+ "yAxis": {
44
+ "title": "Percent (%)"
45
+ },
46
+ "series": [
47
+ {
48
+ "data": [1.7, 2.1, 5.6, 0, -0.6, -2.7, -1.7, 2.4, -1.2],
49
+ "dataLabels": false,
50
+ "name": "Jan-25"
51
+ }
52
+ ],
53
+ "annotations": [
54
+ {
55
+ "text": "A test point annotation",
56
+ "point": {"x": 2, "y": 3},
57
+ "labelOffsetX": 40,
58
+ "labelOffsetY": -30
59
+ }
60
+ ],
61
+ "rangeAnnotations": [
62
+ {
63
+ "text": "A test x axis range annotation",
64
+ "range": {"axisValue1": 1, "axisValue2": 2},
65
+ "axis": "x",
66
+ "labelOffsetX": 10,
67
+ "labelOffsetY": -60
68
+ },
69
+ {
70
+ "text": "A test y axis range annotation with a width of 80px",
71
+ "range": {"axisValue1": 5, "axisValue2": 6},
72
+ "axis": "y",
73
+ "labelOffsetX": -80,
74
+ "labelOffsetY": 220,
75
+ "labelWidth": 80
76
+ }
77
+ ],
78
+ "referenceLineAnnotations": [
79
+ {
80
+ "text": "A test x axis reference line annotation",
81
+ "value": 8,
82
+ "axis": "x",
83
+ "labelOffsetY": -30
84
+ },
85
+ {
86
+ "text": "A test y axis reference line annotation",
87
+ "value": 1.5,
88
+ "axis": "y",
89
+ "labelWidth": 100,
90
+ "labelOffsetX": 10,
91
+ "labelOffsetY": 140
92
+ }
93
+ ]
94
+ })
95
+ }}
@@ -0,0 +1,71 @@
1
+ {% from "components/chart/_macro.njk" import onsChart %}
2
+
3
+ {{
4
+ onsChart({
5
+ "chartType": "columnrange",
6
+ "isChartInverted": true,
7
+ "description": "Volume sales, seasonally adjusted, Great Britain, January 2022 to January 2025",
8
+ "theme": "primary",
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
+ "legend": true,
31
+ "xAxis": {
32
+ "categories": [
33
+ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
34
+ 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
35
+ ],
36
+ "type": "linear",
37
+ "title": "Categories"
38
+ },
39
+ "yAxis": {
40
+ "title": "Temperature ( °C )"
41
+ },
42
+ "series": [
43
+ {
44
+ "data": [
45
+ [-9.5, 8.0],
46
+ [-7.8, 8.3],
47
+ [-13.1, 9.2],
48
+ [-4.4, 15.7],
49
+ [-1.0, 20.8],
50
+ [3.1, 28.4],
51
+ [5.9, 27.0],
52
+ [4.6, 23.0],
53
+ [4.9, 19.3],
54
+ [-5.2, 11.6],
55
+ [],
56
+ [-10.5, 12.0],
57
+ [-12.1, 18.5]
58
+ ],
59
+ "dataLabels": true,
60
+ "name": "Values"
61
+ },
62
+ {
63
+ "data": [1,2,3,4,5,6,7,8,9,10,3,11,12],
64
+ "marker": true,
65
+ "dataLabels": false,
66
+ "name": "Another test data source",
67
+ "type": "scatter"
68
+ }
69
+ ]
70
+ })
71
+ }}
@@ -26,9 +26,7 @@
26
26
  }
27
27
  ]
28
28
  },
29
- "legend": {
30
- "enabled": true
31
- },
29
+ "legend": true,
32
30
  "series": [
33
31
  {
34
32
  "data": [6.2, 1.5, 15.9, 1.7],
@@ -53,7 +53,7 @@
53
53
  "percentageHeightMobile": 90,
54
54
  "annotations": [
55
55
  {
56
- "text": "A test annotation",
56
+ "text": "A test point annotation",
57
57
  "point": {"x": 11, "y": 31.8},
58
58
  "labelOffsetX": 10,
59
59
  "labelOffsetY": -50