@ons/design-system 73.12.0 → 74.0.0-gutters.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.
- package/components/autosuggest/autosuggest.spec.js +1 -0
- package/components/back-to-top/back-to-top.js +9 -1
- package/components/back-to-top/back-to-top.spec.js +46 -0
- package/components/card/example-card-set-with-headline-figures.njk +1 -1
- package/components/chart/_macro.njk +3 -0
- package/components/chart/_macro.spec.js +49 -0
- package/components/chart/bar-chart.js +18 -12
- package/components/chart/chart.js +4 -1
- package/components/chart/common-chart-options.js +1 -0
- package/components/chart/example-stacked-column-with-line-chart.njk +64 -0
- package/components/download-resources/download-resources.spec.js +1 -4
- package/components/message/_message.scss +3 -3
- package/components/tabs/tabs.spec.js +1 -4
- package/css/main.css +1 -1
- package/package.json +42 -43
- package/scripts/chart.es5.js +1 -1
- package/scripts/chart.js +1 -1
- package/scripts/main.es5.js +3 -3
- package/scripts/main.js +3 -3
- package/scss/objects/_container.scss +15 -3
- package/scss/utilities/_grid.scss +10 -25
- package/scss/vars/_grid.scss +20 -3
|
@@ -657,6 +657,7 @@ describe('script: autosuggest', () => {
|
|
|
657
657
|
);
|
|
658
658
|
|
|
659
659
|
await page.type('.ons-js-autosuggest-input', 'England', { delay: 20 });
|
|
660
|
+
await page.waitForSelector('.ons-autosuggest__option');
|
|
660
661
|
await page.keyboard.press('ArrowUp');
|
|
661
662
|
await page.keyboard.press('Enter');
|
|
662
663
|
// Unfocus the autosuggest input
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
export default class BackToTop {
|
|
2
2
|
constructor(component) {
|
|
3
3
|
this.component = component;
|
|
4
|
-
|
|
4
|
+
let el = this.component;
|
|
5
|
+
while (el && !el.previousElementSibling) {
|
|
6
|
+
el = el.parentElement;
|
|
7
|
+
}
|
|
8
|
+
this.content = el ? el.previousElementSibling : null;
|
|
5
9
|
this.target = document.getElementById(this.component.firstElementChild.href.split('#')[1]);
|
|
6
10
|
this.contentleft;
|
|
7
11
|
this.updateContentDetails();
|
|
@@ -27,6 +31,10 @@ export default class BackToTop {
|
|
|
27
31
|
scrollPosition = -this.target.getBoundingClientRect().top + window.innerHeight;
|
|
28
32
|
}
|
|
29
33
|
|
|
34
|
+
// In the extremely unlikely situation where there is no content at all above the back to top component, exit early
|
|
35
|
+
if (!this.content) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
30
38
|
const contentRect = this.content.getBoundingClientRect();
|
|
31
39
|
const windowHeight = window.innerHeight;
|
|
32
40
|
const contentBottom = contentRect.bottom;
|
|
@@ -117,3 +117,49 @@ describe('script: back-to-top', () => {
|
|
|
117
117
|
expect(previousWidth).not.toEqual(newWidth);
|
|
118
118
|
});
|
|
119
119
|
});
|
|
120
|
+
|
|
121
|
+
describe('script: back-to-top without an adjacent previous sibling', () => {
|
|
122
|
+
it('does not throw errors when the component is nested several levels deep with no immediate previous sibling', async () => {
|
|
123
|
+
const pageErrors = [];
|
|
124
|
+
const handler = (err) => pageErrors.push(err.message);
|
|
125
|
+
page.on('pageerror', handler);
|
|
126
|
+
|
|
127
|
+
await setTestPage(
|
|
128
|
+
'/test',
|
|
129
|
+
`
|
|
130
|
+
<div>
|
|
131
|
+
<p>Content above</p>
|
|
132
|
+
</div>
|
|
133
|
+
<div>
|
|
134
|
+
<div>
|
|
135
|
+
<div>
|
|
136
|
+
${renderComponent('back-to-top', {})}
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
</div>
|
|
140
|
+
`,
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
await page.evaluate(() => {
|
|
144
|
+
window.scrollTo(0, window.innerHeight * 2 + 10);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
page.off('pageerror', handler);
|
|
148
|
+
expect(pageErrors).toHaveLength(0);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('does not throw errors when there is no content preceding the back-to-top component', async () => {
|
|
152
|
+
const pageErrors = [];
|
|
153
|
+
const handler = (err) => pageErrors.push(err.message);
|
|
154
|
+
page.on('pageerror', handler);
|
|
155
|
+
|
|
156
|
+
await setTestPage('/test', `${renderComponent('back-to-top', {})}`);
|
|
157
|
+
|
|
158
|
+
await page.evaluate(() => {
|
|
159
|
+
window.scrollTo(0, window.innerHeight * 2 + 10);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
page.off('pageerror', handler);
|
|
163
|
+
expect(pageErrors).toHaveLength(0);
|
|
164
|
+
});
|
|
165
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{% from "components/card/_macro.njk" import onsCard %}
|
|
2
2
|
|
|
3
3
|
<div class="ons-container">
|
|
4
|
-
<div class="ons-grid ons-grid-flex-gap ons-grid-flex
|
|
4
|
+
<div class="ons-grid ons-grid-flex-gap ons-grid-flex--vertical-top">
|
|
5
5
|
<div class="ons-grid__col ons-grid__col--flex-col ons-grid__col--stretch">
|
|
6
6
|
{{
|
|
7
7
|
onsCard({
|
|
@@ -42,6 +42,9 @@
|
|
|
42
42
|
{% if params.yAxis.customReferenceLineValue %}
|
|
43
43
|
data-highcharts-custom-reference-line-value="{{ params.yAxis.customReferenceLineValue }}"
|
|
44
44
|
{% endif %}
|
|
45
|
+
{% if params.dataLabelDecimalPoints >= 1 and params.dataLabelDecimalPoints <= 2 %}
|
|
46
|
+
data-highcharts-data-label-decimal-points="{{ params.dataLabelDecimalPoints }}"
|
|
47
|
+
{% endif %}
|
|
45
48
|
{% endif %}
|
|
46
49
|
>
|
|
47
50
|
{%
|
|
@@ -885,6 +885,55 @@ describe('Macro: Chart', () => {
|
|
|
885
885
|
});
|
|
886
886
|
});
|
|
887
887
|
|
|
888
|
+
describe('GIVEN: Params: dataLabelDecimalPoints', () => {
|
|
889
|
+
describe('WHEN: dataLabelDecimalPoints is provided', () => {
|
|
890
|
+
const $ = cheerio.load(
|
|
891
|
+
renderComponent('chart', {
|
|
892
|
+
...EXAMPLE_BAR_CHART_PARAMS,
|
|
893
|
+
dataLabelDecimalPoints: 2,
|
|
894
|
+
}),
|
|
895
|
+
);
|
|
896
|
+
|
|
897
|
+
test('THEN: it includes the data label decimal points data attribute', () => {
|
|
898
|
+
expect($('[data-highcharts-base-chart]').attr('data-highcharts-data-label-decimal-points')).toBe('2');
|
|
899
|
+
});
|
|
900
|
+
});
|
|
901
|
+
|
|
902
|
+
describe('WHEN: dataLabelDecimalPoints is not provided', () => {
|
|
903
|
+
const $ = cheerio.load(renderComponent('chart', EXAMPLE_BAR_CHART_PARAMS));
|
|
904
|
+
|
|
905
|
+
test('THEN: it does not include the data label decimal points data attribute', () => {
|
|
906
|
+
expect($('[data-highcharts-base-chart]').attr('data-highcharts-data-label-decimal-points')).toBe(undefined);
|
|
907
|
+
});
|
|
908
|
+
});
|
|
909
|
+
|
|
910
|
+
describe('WHEN: dataLabelDecimalPoints is greater than 2', () => {
|
|
911
|
+
const $ = cheerio.load(
|
|
912
|
+
renderComponent('chart', {
|
|
913
|
+
...EXAMPLE_BAR_CHART_PARAMS,
|
|
914
|
+
dataLabelDecimalPoints: 3,
|
|
915
|
+
}),
|
|
916
|
+
);
|
|
917
|
+
|
|
918
|
+
test('THEN: it does not include the data label decimal points data attribute', () => {
|
|
919
|
+
expect($('[data-highcharts-base-chart]').attr('data-highcharts-data-label-decimal-points')).toBe(undefined);
|
|
920
|
+
});
|
|
921
|
+
});
|
|
922
|
+
|
|
923
|
+
describe('WHEN: dataLabelDecimalPoints is less than 1', () => {
|
|
924
|
+
const $ = cheerio.load(
|
|
925
|
+
renderComponent('chart', {
|
|
926
|
+
...EXAMPLE_BAR_CHART_PARAMS,
|
|
927
|
+
dataLabelDecimalPoints: 0,
|
|
928
|
+
}),
|
|
929
|
+
);
|
|
930
|
+
|
|
931
|
+
test('THEN: it does not include the data label decimal points data attribute', () => {
|
|
932
|
+
expect($('[data-highcharts-base-chart]').attr('data-highcharts-data-label-decimal-points')).toBe(undefined);
|
|
933
|
+
});
|
|
934
|
+
});
|
|
935
|
+
});
|
|
936
|
+
|
|
888
937
|
describe('GIVEN: Params: caption', () => {
|
|
889
938
|
describe('WHEN: caption is provided', () => {
|
|
890
939
|
const $ = cheerio.load(
|
|
@@ -5,7 +5,23 @@ class BarChart {
|
|
|
5
5
|
this.constants = ChartConstants.constants();
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
getBarChartOptions = (useStackedLayout) => {
|
|
8
|
+
getBarChartOptions = (useStackedLayout, dataLabelDecimalPoints) => {
|
|
9
|
+
const dataLabels = {
|
|
10
|
+
enabled: true,
|
|
11
|
+
inside: false,
|
|
12
|
+
style: {
|
|
13
|
+
textOutline: 'none',
|
|
14
|
+
// The design system does not include a semibold font weight, so we use 700 (bold) as an alternative.
|
|
15
|
+
fontWeight: '700',
|
|
16
|
+
color: this.constants.labelColor,
|
|
17
|
+
fontSize: this.constants.defaultFontSize,
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
if (dataLabelDecimalPoints !== undefined) {
|
|
21
|
+
dataLabels.formatter = function () {
|
|
22
|
+
return Number(this.y).toFixed(dataLabelDecimalPoints);
|
|
23
|
+
};
|
|
24
|
+
}
|
|
9
25
|
return {
|
|
10
26
|
plotOptions: {
|
|
11
27
|
bar: {
|
|
@@ -18,17 +34,7 @@ class BarChart {
|
|
|
18
34
|
borderRadius: 0,
|
|
19
35
|
// Set the data labels to be enabled and positioned outside the bars
|
|
20
36
|
// We can add custom formatting on each chart to move the labels inside the bars if the bar is wide enough
|
|
21
|
-
dataLabels
|
|
22
|
-
enabled: true,
|
|
23
|
-
inside: false,
|
|
24
|
-
style: {
|
|
25
|
-
textOutline: 'none',
|
|
26
|
-
// The design system does not include a semibold font weight, so we use 700 (bold) as an alternative.
|
|
27
|
-
fontWeight: '700',
|
|
28
|
-
color: this.constants.labelColor,
|
|
29
|
-
fontSize: this.constants.defaultFontSize,
|
|
30
|
-
},
|
|
31
|
-
},
|
|
37
|
+
dataLabels,
|
|
32
38
|
},
|
|
33
39
|
series: {
|
|
34
40
|
stacking: useStackedLayout ? 'normal' : null,
|
|
@@ -73,6 +73,9 @@ class HighchartsBaseChart {
|
|
|
73
73
|
this.customReferenceLineValue = this.node.dataset.highchartsCustomReferenceLineValue
|
|
74
74
|
? parseFloat(this.node.dataset.highchartsCustomReferenceLineValue)
|
|
75
75
|
: undefined;
|
|
76
|
+
this.dataLabelDecimalPoints = this.node.dataset.highchartsDataLabelDecimalPoints
|
|
77
|
+
? parseInt(this.node.dataset.highchartsDataLabelDecimalPoints, 10)
|
|
78
|
+
: undefined;
|
|
76
79
|
this.specificChartOptions = new SpecificChartOptions(
|
|
77
80
|
this.theme,
|
|
78
81
|
this.chartType,
|
|
@@ -153,7 +156,7 @@ class HighchartsBaseChart {
|
|
|
153
156
|
setSpecificChartOptions = () => {
|
|
154
157
|
const specificChartOptions = this.specificChartOptions.getOptions();
|
|
155
158
|
const lineChartOptions = this.lineChart.getLineChartOptions();
|
|
156
|
-
const barChartOptions = this.barChart.getBarChartOptions(this.useStackedLayout);
|
|
159
|
+
const barChartOptions = this.barChart.getBarChartOptions(this.useStackedLayout, this.dataLabelDecimalPoints);
|
|
157
160
|
const columnRangeChartOptions = this.columnRangeChart.getColumnRangeChartOptions();
|
|
158
161
|
const columnChartOptions = this.columnChart.getColumnChartOptions(this.config, this.useStackedLayout, this.extraLines);
|
|
159
162
|
const areaChartOptions = this.areaChart.getAreaChartOptions();
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{% from "components/chart/_macro.njk" import onsChart %}
|
|
2
|
+
{{
|
|
3
|
+
onsChart({
|
|
4
|
+
"chartType": "column",
|
|
5
|
+
"description": "Monthly percentage change in retail sales volume by store type, Great Britain, January to June 2025",
|
|
6
|
+
"theme": "primary",
|
|
7
|
+
"title": "Food stores showed a strong rise on the month, while non-food stores fell",
|
|
8
|
+
"subtitle": "Figure 6: Upward contribution to monthly percentage change in total retail sales",
|
|
9
|
+
"id": "uuid",
|
|
10
|
+
"useStackedLayout": true,
|
|
11
|
+
"caption": "Source: Monthly Business Survey, Retail Sales Inquiry from the Office for National Statistics",
|
|
12
|
+
"download": {
|
|
13
|
+
"title": "Download Figure 6 data",
|
|
14
|
+
"itemsList": [
|
|
15
|
+
{ "text": "Excel spreadsheet (XLSX format, 22KB)", "url": "#",
|
|
16
|
+
"download": "file" },
|
|
17
|
+
{ "text": "Simple text file (CSV format, 28KB)", "url": "#",
|
|
18
|
+
"download": "file" },
|
|
19
|
+
{ "text": "Image (PNG format, 32KB)", "url": "#",
|
|
20
|
+
"download": "file" }
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
"legend": true,
|
|
24
|
+
"series": [
|
|
25
|
+
{
|
|
26
|
+
"name": "Food stores",
|
|
27
|
+
"data": [1.5, 0.8, 1.2, 0.9, 1.1, 1.4]
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"name": "Non-food stores",
|
|
31
|
+
"data": [0.5, -0.2, 0.6, 0.8, 0.3, 0.4]
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"name": "Non-store retailing",
|
|
35
|
+
"data": [0.2, 0.1, 0.3, 0.2, 0.4, 0.3]
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"name": "Automotive fuel",
|
|
39
|
+
"data": [0.3, 0.2, -0.1, 0.4, 0.2, 0.5]
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"name": "Another test data source",
|
|
43
|
+
"data": [1.5, 0.8, 1.5, 0.2, 0.8, 1.3],
|
|
44
|
+
"type": "line"
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
"xAxis": {
|
|
48
|
+
"categories": [
|
|
49
|
+
"Jan 2025",
|
|
50
|
+
"Feb 2025",
|
|
51
|
+
"Mar 2025",
|
|
52
|
+
"Apr 2025",
|
|
53
|
+
"May 2025",
|
|
54
|
+
"Jun 2025"
|
|
55
|
+
],
|
|
56
|
+
"title": "Month"
|
|
57
|
+
},
|
|
58
|
+
"yAxis": {
|
|
59
|
+
"title": "Monthly percentage change (%)"
|
|
60
|
+
},
|
|
61
|
+
"percentageHeightDesktop": 40,
|
|
62
|
+
"percentageHeightMobile": 90
|
|
63
|
+
})
|
|
64
|
+
}}
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { setViewport } from '../../tests/helpers/puppeteer';
|
|
1
|
+
import { iPhoneX, setViewport } from '../../tests/helpers/puppeteer';
|
|
3
2
|
import { renderComponent, renderTemplate, setTestPage } from '../../tests/helpers/rendering';
|
|
4
3
|
|
|
5
|
-
const iPhoneX = KnownDevices['iPhone X'];
|
|
6
|
-
|
|
7
4
|
/* eslint-disable indent */
|
|
8
5
|
const EXAMPLE_PAGE = `
|
|
9
6
|
<div class="ons-page">
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
@use 'sass:math';
|
|
2
2
|
|
|
3
3
|
.ons-message {
|
|
4
|
-
border-radius: math.div($grid-
|
|
4
|
+
border-radius: math.div($grid-gutter-standard, 2);
|
|
5
5
|
margin-bottom: 2rem;
|
|
6
6
|
outline: 1px solid transparent; // Add transparent outline because Windows High Contrast Mode doesn't show background
|
|
7
7
|
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
|
|
24
24
|
&__head {
|
|
25
25
|
border-bottom: 1px solid var(--ons-color-borders);
|
|
26
|
-
padding: $grid-
|
|
26
|
+
padding: $grid-gutter-standard;
|
|
27
27
|
position: relative;
|
|
28
28
|
}
|
|
29
29
|
|
|
@@ -50,6 +50,6 @@
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
&__body {
|
|
53
|
-
padding: $grid-
|
|
53
|
+
padding: $grid-gutter-standard;
|
|
54
54
|
}
|
|
55
55
|
}
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { setViewport } from '../../tests/helpers/puppeteer';
|
|
1
|
+
import { iPhoneX, setViewport } from '../../tests/helpers/puppeteer';
|
|
3
2
|
import { renderComponent, setTestPage } from '../../tests/helpers/rendering';
|
|
4
3
|
|
|
5
|
-
const iPhoneX = KnownDevices['iPhone X'];
|
|
6
|
-
|
|
7
4
|
const EXAMPLE_TABS = {
|
|
8
5
|
title: 'Example tabs',
|
|
9
6
|
titleClasses: 'ons-u-fs-m',
|