@madgex/design-system 14.3.1 → 14.4.1
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/dist/assets/icons-inline.svg +1 -1
- package/dist/assets/icons.json +1 -1
- package/dist/assets/icons.svg +1 -1
- package/dist/js/index.js +1 -1
- package/package.json +4 -4
- package/src/components/accordion/_template.njk +35 -33
- package/src/components/accordion/accordion.config.js +0 -81
- package/src/components/accordion/accordion.js +54 -43
- package/src/components/accordion/accordion.njk +1 -24
- package/src/components/accordion/accordion.spec.js +170 -0
- package/src/components/button/button.config.js +1 -42
- package/src/components/button/button.njk +1 -14
- package/src/components/card/card.config.js +0 -93
- package/src/components/card/card.njk +1 -22
- package/src/components/icons/icons.njk +1 -161
- package/src/components/inputs/combobox/README.md +22 -1
- package/src/components/inputs/combobox/combobox.njk +26 -2
- package/src/js/index.js +5 -2
- package/src/layout/containers/index.njk +1 -0
- package/src/typography/index.njk +1 -0
- package/tasks/svgsprite.js +62 -49
- package/src/components/accordion/README.md +0 -46
- package/src/components/button/README.md +0 -27
- package/src/components/card/README.md +0 -114
- package/src/components/icons/README.md +0 -62
- package/src/layout/containers/01-base-containers.njk +0 -30
- package/src/layout/containers/02-branded-containers.njk +0 -13
- package/src/layout/containers/03-ad-containers.njk +0 -6
- package/src/layout/containers/04-highlighted-containers.njk +0 -3
- package/src/layout/containers/README.md +0 -30
- package/src/layout/containers/ad-containers.config.json +0 -3
- package/src/layout/containers/base-containers.config.json +0 -3
- package/src/layout/containers/branded-containers.config.json +0 -3
- package/src/layout/containers/highlighted-containers.config.json +0 -3
- package/src/typography/font-types.config.json +0 -3
- package/src/typography/font-types.njk +0 -43
- package/src/typography/headings.njk +0 -9
- package/src/typography/lists.njk +0 -111
|
@@ -1,161 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
{% from "./icons/_macro.njk" import MdsIcon %}
|
|
4
|
-
|
|
5
|
-
<h2>Different sizes</h2>
|
|
6
|
-
|
|
7
|
-
<p>{{ MdsIcon({
|
|
8
|
-
iconName: 'star-fill',
|
|
9
|
-
classes: 'mds-icon--sm',
|
|
10
|
-
visuallyHiddenLabel: 'Shortlisted'
|
|
11
|
-
}) }} : small (16px)</p>
|
|
12
|
-
<p>{{ MdsIcon({
|
|
13
|
-
iconName: 'star-fill',
|
|
14
|
-
classes: 'mds-icon--md'
|
|
15
|
-
}) }} : medium (24px)</p>
|
|
16
|
-
<p>{{ MdsIcon({
|
|
17
|
-
iconName: 'star-fill',
|
|
18
|
-
classes: 'mds-icon--lg'
|
|
19
|
-
}) }} : large (32px)</p>
|
|
20
|
-
<p>{{ MdsIcon({
|
|
21
|
-
iconName: 'star-fill',
|
|
22
|
-
classes: 'mds-icon--xl'
|
|
23
|
-
}) }} : extra large (48px)</p>
|
|
24
|
-
<p>{{ MdsIcon({
|
|
25
|
-
iconName: 'star-fill',
|
|
26
|
-
classes: 'mds-icon--xxl'
|
|
27
|
-
}) }} : extra extra large (72px)</p>
|
|
28
|
-
|
|
29
|
-
<br><hr><br>
|
|
30
|
-
|
|
31
|
-
<h2>Icon with text</h2>
|
|
32
|
-
|
|
33
|
-
<p>{{- MdsIcon({
|
|
34
|
-
iconName: 'email',
|
|
35
|
-
classes: 'mds-icon--before'
|
|
36
|
-
}) -}}Email me</p>
|
|
37
|
-
|
|
38
|
-
<p><a href="#">Apply{{- MdsIcon({
|
|
39
|
-
iconName: 'chevron-right',
|
|
40
|
-
classes: 'mds-icon--after'
|
|
41
|
-
}) -}}</a></p>
|
|
42
|
-
|
|
43
|
-
<div>
|
|
44
|
-
<span>Share this job</span>
|
|
45
|
-
<ul class="mds-list mds-list--inline mds-display-inline-block">
|
|
46
|
-
<li class="mds-list__item">
|
|
47
|
-
<a href="#">
|
|
48
|
-
{{- MdsIcon({
|
|
49
|
-
iconName: 'social-facebook',
|
|
50
|
-
visuallyHiddenLabel: 'Facebook'
|
|
51
|
-
}) -}}
|
|
52
|
-
</a>
|
|
53
|
-
</li>
|
|
54
|
-
<li class="mds-list__item">
|
|
55
|
-
<a href="#">
|
|
56
|
-
{{- MdsIcon({
|
|
57
|
-
iconName: 'social-twitter',
|
|
58
|
-
visuallyHiddenLabel: 'Twitter'
|
|
59
|
-
}) -}}
|
|
60
|
-
</a>
|
|
61
|
-
</li>
|
|
62
|
-
<li class="mds-list__item">
|
|
63
|
-
<a href="#">
|
|
64
|
-
{{- MdsIcon({
|
|
65
|
-
iconName: 'social-linkedin',
|
|
66
|
-
visuallyHiddenLabel: 'LinkedIn'
|
|
67
|
-
}) -}}
|
|
68
|
-
</a>
|
|
69
|
-
</li>
|
|
70
|
-
<li class="mds-list__item">
|
|
71
|
-
<a href="#">
|
|
72
|
-
{{- MdsIcon({
|
|
73
|
-
iconName: 'social-pinterest',
|
|
74
|
-
visuallyHiddenLabel: 'Pinterest'
|
|
75
|
-
}) -}}
|
|
76
|
-
</a>
|
|
77
|
-
</li>
|
|
78
|
-
<li class="mds-list__item">
|
|
79
|
-
<a href="#">
|
|
80
|
-
{{- MdsIcon({
|
|
81
|
-
iconName: 'social-reddit',
|
|
82
|
-
visuallyHiddenLabel: 'Reddit'
|
|
83
|
-
}) -}}
|
|
84
|
-
</a>
|
|
85
|
-
</li>
|
|
86
|
-
</ul>
|
|
87
|
-
</div>
|
|
88
|
-
|
|
89
|
-
<br><hr><br>
|
|
90
|
-
|
|
91
|
-
<h2>Spinner</h2>
|
|
92
|
-
{{- MdsIcon({
|
|
93
|
-
iconName: 'spinner',
|
|
94
|
-
visuallyHiddenLabel: 'Loading...'
|
|
95
|
-
}) -}}
|
|
96
|
-
|
|
97
|
-
<br><hr><br>
|
|
98
|
-
|
|
99
|
-
<h2>Has container</h2>
|
|
100
|
-
{{- MdsIcon({
|
|
101
|
-
iconName: 'cross',
|
|
102
|
-
visuallyHiddenLabel: 'Error',
|
|
103
|
-
classes: 'mds-icon--md',
|
|
104
|
-
hasContainer: true,
|
|
105
|
-
containerClasses: 'mds-icon-container--circle mds-icon-container--error'
|
|
106
|
-
}) -}}
|
|
107
|
-
|
|
108
|
-
<br><hr><br>
|
|
109
|
-
|
|
110
|
-
<h2>Icons using inline SVG</h2>
|
|
111
|
-
|
|
112
|
-
<div>
|
|
113
|
-
<span>Share this job</span>
|
|
114
|
-
<ul class="mds-list mds-list--inline mds-display-inline-block">
|
|
115
|
-
<li class="mds-list__item">
|
|
116
|
-
<a href="#">
|
|
117
|
-
{{- MdsIcon({
|
|
118
|
-
iconName: 'social-facebook',
|
|
119
|
-
visuallyHiddenLabel: 'Facebook',
|
|
120
|
-
path: ''
|
|
121
|
-
}) -}}
|
|
122
|
-
</a>
|
|
123
|
-
</li>
|
|
124
|
-
<li class="mds-list__item">
|
|
125
|
-
<a href="#">
|
|
126
|
-
{{- MdsIcon({
|
|
127
|
-
iconName: 'social-twitter',
|
|
128
|
-
visuallyHiddenLabel: 'Twitter',
|
|
129
|
-
path: ''
|
|
130
|
-
}) -}}
|
|
131
|
-
</a>
|
|
132
|
-
</li>
|
|
133
|
-
<li class="mds-list__item">
|
|
134
|
-
<a href="#">
|
|
135
|
-
{{- MdsIcon({
|
|
136
|
-
iconName: 'social-linkedin',
|
|
137
|
-
visuallyHiddenLabel: 'LinkedIn',
|
|
138
|
-
path: ''
|
|
139
|
-
}) -}}
|
|
140
|
-
</a>
|
|
141
|
-
</li>
|
|
142
|
-
<li class="mds-list__item">
|
|
143
|
-
<a href="#">
|
|
144
|
-
{{- MdsIcon({
|
|
145
|
-
iconName: 'social-pinterest',
|
|
146
|
-
visuallyHiddenLabel: 'Pinterest',
|
|
147
|
-
path: ''
|
|
148
|
-
}) -}}
|
|
149
|
-
</a>
|
|
150
|
-
</li>
|
|
151
|
-
<li class="mds-list__item">
|
|
152
|
-
<a href="#">
|
|
153
|
-
{{- MdsIcon({
|
|
154
|
-
iconName: 'social-reddit',
|
|
155
|
-
visuallyHiddenLabel: 'Reddit',
|
|
156
|
-
path: ''
|
|
157
|
-
}) -}}
|
|
158
|
-
</a>
|
|
159
|
-
</li>
|
|
160
|
-
</ul>
|
|
161
|
-
</div>
|
|
1
|
+
<a href="/storybook/" target="_top">Moved to Storybook</a>
|
|
@@ -4,6 +4,8 @@ This component provides autocomplete search functionality to select an option fr
|
|
|
4
4
|
|
|
5
5
|
Options can be provided via `<option value="value">label</option>` children, or obtained from an API using the `apiUrl` parameter.
|
|
6
6
|
|
|
7
|
+
MdsCombobox reports its values to a parent `<form>` wrapping it.
|
|
8
|
+
|
|
7
9
|
## Parameters - Nunjucks
|
|
8
10
|
|
|
9
11
|
- `id`: the id of your combobox **required**
|
|
@@ -50,6 +52,12 @@ i18n: {
|
|
|
50
52
|
|
|
51
53
|
MdsCombobox usage revolves around options provided by `<option value="">label</option>` child elements as available options and the initial value comes from `<option selected>` children, and optionally an API (`apiUrl` in use), and being in `multiple` mode via `params.multiple`.
|
|
52
54
|
|
|
55
|
+
### What is reported to parent `<form>` element?
|
|
56
|
+
|
|
57
|
+
- Selected value(s) will be reported to the parent `<form>` using the `name` given to MdsCombobox. Multiple may exist.
|
|
58
|
+
- Search text (**not** the label of the selected option) will be reported to the parent `<form>` using the `name` given to MdsCombobox with `_search` as the suffix, e.g. `${name}_search`. Only a single instance will exist
|
|
59
|
+
- Fallback will be reported to the parent `<form>` using the `name` given to MdsCombobox with `_fallback` as the suffix, e.g. `${name}_fallback`. Only a single instance will exist
|
|
60
|
+
|
|
53
61
|
## Fallback
|
|
54
62
|
|
|
55
63
|
When JavaScript is unavailable, the combobox will gracefully degrade to a native form element. Use the `fallbackTo` parameter to specify which fallback element to use: either a native `select` dropdown or a text `input`.
|
|
@@ -65,6 +73,7 @@ Both fallback elements share the same `id` as the combobox to ensure the label r
|
|
|
65
73
|
### Example - Single mode - no API - no option selected
|
|
66
74
|
|
|
67
75
|
```njk
|
|
76
|
+
<form>
|
|
68
77
|
{\% call MdsCombobox({
|
|
69
78
|
id:'my-id',
|
|
70
79
|
name: 'my-combo',
|
|
@@ -73,12 +82,13 @@ Both fallback elements share the same `id` as the combobox to ensure the label r
|
|
|
73
82
|
<option value="value-1">My label 1</option>
|
|
74
83
|
<option value="value-2">My label 2</option>
|
|
75
84
|
{\% endcall \%}
|
|
76
|
-
|
|
85
|
+
</form>
|
|
77
86
|
```
|
|
78
87
|
|
|
79
88
|
#### with pre-selected value
|
|
80
89
|
|
|
81
90
|
```njk
|
|
91
|
+
<form>
|
|
82
92
|
{\% call MdsCombobox({
|
|
83
93
|
id:'my-id',
|
|
84
94
|
name: 'my-combo',
|
|
@@ -89,12 +99,14 @@ Both fallback elements share the same `id` as the combobox to ensure the label r
|
|
|
89
99
|
<option value="value-1">My label 1</option>
|
|
90
100
|
<option value="value-2" selected>My label 2</option>
|
|
91
101
|
{\% endcall \%}
|
|
102
|
+
</form>
|
|
92
103
|
|
|
93
104
|
```
|
|
94
105
|
|
|
95
106
|
### Example - Multiple mode - no API
|
|
96
107
|
|
|
97
108
|
```njk
|
|
109
|
+
<form>
|
|
98
110
|
{\% call MdsCombobox({
|
|
99
111
|
id:'my-id',
|
|
100
112
|
name: 'my-combo',
|
|
@@ -104,6 +116,7 @@ Both fallback elements share the same `id` as the combobox to ensure the label r
|
|
|
104
116
|
<option value="value-1">My label 1</option>
|
|
105
117
|
<option value="value-2">My label 2</option>
|
|
106
118
|
{\% endcall \%}
|
|
119
|
+
</form>
|
|
107
120
|
|
|
108
121
|
```
|
|
109
122
|
|
|
@@ -113,6 +126,7 @@ API response options have a custom shape with `word` and `score` properties,
|
|
|
113
126
|
like so `[{word: 'something', score: 12},...]`. It also used `?keyword` for the query param on the request.
|
|
114
127
|
|
|
115
128
|
```njk
|
|
129
|
+
<form>
|
|
116
130
|
{\% call MdsCombobox({
|
|
117
131
|
id:'my-id',
|
|
118
132
|
name: 'my-combo',
|
|
@@ -123,12 +137,14 @@ like so `[{word: 'something', score: 12},...]`. It also used `?keyword` for the
|
|
|
123
137
|
apiOptionValuePath: 'score'
|
|
124
138
|
}) \%}
|
|
125
139
|
{\% endcall \%}
|
|
140
|
+
</form>
|
|
126
141
|
|
|
127
142
|
```
|
|
128
143
|
|
|
129
144
|
#### with prefilled value
|
|
130
145
|
|
|
131
146
|
```njk
|
|
147
|
+
<form>
|
|
132
148
|
{\% call MdsCombobox({
|
|
133
149
|
id:'my-id',
|
|
134
150
|
name: 'my-combo',
|
|
@@ -141,6 +157,7 @@ like so `[{word: 'something', score: 12},...]`. It also used `?keyword` for the
|
|
|
141
157
|
{# we can render selected options on the server even when using API #}
|
|
142
158
|
<option value="value-2" selected>My label 2</option>
|
|
143
159
|
{\% endcall \%}
|
|
160
|
+
</form>
|
|
144
161
|
|
|
145
162
|
```
|
|
146
163
|
|
|
@@ -149,6 +166,7 @@ like so `[{word: 'something', score: 12},...]`. It also used `?keyword` for the
|
|
|
149
166
|
API response had a root object property called `data`, like so `{data:[{label: 'something', value: 12},...]}`.
|
|
150
167
|
|
|
151
168
|
```njk
|
|
169
|
+
<form>
|
|
152
170
|
{\% call MdsCombobox({
|
|
153
171
|
id:'my-id',
|
|
154
172
|
name: 'my-combo',
|
|
@@ -158,6 +176,7 @@ API response had a root object property called `data`, like so `{data:[{label: '
|
|
|
158
176
|
multiple: true
|
|
159
177
|
}) \%}
|
|
160
178
|
{\% endcall \%}
|
|
179
|
+
</form>
|
|
161
180
|
|
|
162
181
|
```
|
|
163
182
|
|
|
@@ -166,6 +185,7 @@ options:
|
|
|
166
185
|
#### with prefilled value
|
|
167
186
|
|
|
168
187
|
```njk
|
|
188
|
+
<form>
|
|
169
189
|
{\% call MdsCombobox({
|
|
170
190
|
id:'my-id',
|
|
171
191
|
name: 'my-combo',
|
|
@@ -178,6 +198,7 @@ options:
|
|
|
178
198
|
<option value="value-1" selected>My label 1</option>
|
|
179
199
|
<option value="value-2" selected>My label 2</option>
|
|
180
200
|
{\% endcall \%}
|
|
201
|
+
</form>
|
|
181
202
|
|
|
182
203
|
```
|
|
183
204
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{% from "./inputs/combobox/_macro.njk" import MdsCombobox %}
|
|
2
2
|
|
|
3
|
-
<form class="mds-grid-row">
|
|
4
|
-
<div class="mds-grid-col-6 mds-margin-bottom-b10">
|
|
5
3
|
<h3>{{ variantTitle }}</h3>
|
|
4
|
+
<form class="mds-grid-row mds-border-bottom mds-margin-bottom-b10 mds-padding-bottom-b10" id="{{name}}_demo-form">
|
|
5
|
+
<div class="mds-grid-col-6 ">
|
|
6
6
|
|
|
7
7
|
{% call MdsCombobox({
|
|
8
8
|
id: id,
|
|
@@ -29,6 +29,30 @@
|
|
|
29
29
|
{# this will be `<option>` elements #}
|
|
30
30
|
{{ content | safe }}
|
|
31
31
|
{% endcall %}
|
|
32
|
+
|
|
33
|
+
</div>
|
|
34
|
+
<div class="mds-grid-col-6 mds-font-s-1 mds-highlighted-container mds-padding-b1">
|
|
35
|
+
<span>Visualised <form> FormData</span>
|
|
36
|
+
<br><ul class="mds-list mds-list--bullet" id="{{name}}_demo-form__visual"></ul>
|
|
32
37
|
</div>
|
|
33
38
|
</form>
|
|
34
39
|
|
|
40
|
+
{# Cheeky visualise FormData #}
|
|
41
|
+
<script type="module">
|
|
42
|
+
const form = document.querySelector('#{{name}}_demo-form');
|
|
43
|
+
|
|
44
|
+
setTimeout(() => {
|
|
45
|
+
const combobox = document.querySelector('[name={{name}}]');
|
|
46
|
+
combobox.addEventListener('change', updateFormDataVisual);
|
|
47
|
+
const comboboxSearch = document.querySelector('[name={{name}}_search]');
|
|
48
|
+
comboboxSearch.addEventListener('input', updateFormDataVisual);
|
|
49
|
+
}, 500)
|
|
50
|
+
updateFormDataVisual();
|
|
51
|
+
function updateFormDataVisual() {
|
|
52
|
+
setTimeout(()=> {
|
|
53
|
+
const formVisual = document.querySelector('#{{name}}_demo-form__visual');
|
|
54
|
+
const text = Array.from(new FormData(form).entries()).map(([key,val]) => `<li class="mds-list__item"><strong>${key}</strong>=${val}</li>`).join('');
|
|
55
|
+
formVisual.innerHTML = text;
|
|
56
|
+
}, 500)
|
|
57
|
+
}
|
|
58
|
+
</script>
|
package/src/js/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import './common';
|
|
2
2
|
import tabs from '../components/tabs/tabs';
|
|
3
|
-
import accordion from '../components/accordion/accordion';
|
|
4
3
|
import subnavigation from '../components/subnavigation/subnavigation';
|
|
5
4
|
import checkboxList from '../components/inputs/checkbox-list/checkbox-list';
|
|
6
5
|
import popovers from '../components/popover/popover';
|
|
@@ -9,6 +8,7 @@ import { MdsFileUpload } from '../components/inputs/file-upload/file-upload';
|
|
|
9
8
|
import characterCount from '../components/inputs/character-count/character-count';
|
|
10
9
|
import button from '../components/button/button';
|
|
11
10
|
import prose from '../helpers/prose/prose';
|
|
11
|
+
import { MdsAccordion } from '../components/accordion/accordion';
|
|
12
12
|
import { MdsDropdownNav } from '../components/dropdown-nav/dropdown-nav';
|
|
13
13
|
import { MdsTimeoutDialog } from '../components/timeout-dialog/timeout-dialog';
|
|
14
14
|
import { MdsCardLink } from '../components/card/card-link';
|
|
@@ -19,6 +19,10 @@ import { MdsScrollSpy } from '../components/scroll-spy/scroll-spy';
|
|
|
19
19
|
import { MdsConsentGate } from '../components/consent-gate/consent-gate.js';
|
|
20
20
|
export { setConsentAdapter } from '../components/consent-gate/consent-gate.js';
|
|
21
21
|
|
|
22
|
+
if (!window.customElements.get('mds-accordion')) {
|
|
23
|
+
window.customElements.define('mds-accordion', MdsAccordion);
|
|
24
|
+
}
|
|
25
|
+
|
|
22
26
|
if (!window.customElements.get('mds-dropdown-nav')) {
|
|
23
27
|
window.customElements.define('mds-dropdown-nav', MdsDropdownNav);
|
|
24
28
|
}
|
|
@@ -49,7 +53,6 @@ if (!window.customElements.get('mds-consent-gate')) {
|
|
|
49
53
|
|
|
50
54
|
const initAll = () => {
|
|
51
55
|
tabs.init();
|
|
52
|
-
accordion.init();
|
|
53
56
|
subnavigation.init();
|
|
54
57
|
checkboxList.init();
|
|
55
58
|
modals.init();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<a href="/storybook/" target="_top">Moved to Storybook</a>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<a href="/storybook/" target="_top">Moved to Storybook</a>
|
package/tasks/svgsprite.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
const fs = require('fs');
|
|
3
|
+
const { createHash } = require('node:crypto');
|
|
3
4
|
const { optimize } = require('svgo');
|
|
4
5
|
const svgstore = require('svgstore');
|
|
5
6
|
|
|
6
|
-
const
|
|
7
|
-
const prefix = path.basename(filepath, path.extname(filepath));
|
|
7
|
+
const iconsDir = path.resolve(__dirname, '../src/icons/');
|
|
8
8
|
|
|
9
9
|
const svgoOptions = {
|
|
10
10
|
plugins: [
|
|
@@ -12,11 +12,9 @@ const svgoOptions = {
|
|
|
12
12
|
name: 'preset-default',
|
|
13
13
|
params: {
|
|
14
14
|
overrides: {
|
|
15
|
-
|
|
16
|
-
prefix: `${prefix}-`,
|
|
15
|
+
cleanupIds: {
|
|
17
16
|
minify: true,
|
|
18
17
|
},
|
|
19
|
-
removeViewBox: false,
|
|
20
18
|
},
|
|
21
19
|
},
|
|
22
20
|
},
|
|
@@ -26,57 +24,72 @@ const svgoOptions = {
|
|
|
26
24
|
attrs: 'fill',
|
|
27
25
|
},
|
|
28
26
|
},
|
|
27
|
+
// ensure `id` attributes of different .svg files are different
|
|
28
|
+
// so that when a spritesheet is created they wont clash (many same named ids, sprites using the wrong reference!)
|
|
29
|
+
{
|
|
30
|
+
name: 'prefixIds',
|
|
31
|
+
params: {
|
|
32
|
+
delim: '',
|
|
33
|
+
// base the unique id prefix on the svg file path, this way it will be consistent inside the file, but unique to that file
|
|
34
|
+
prefix: (_, opt) => createHash('md5').update(opt.path).digest('hex').substring(0, 6) + '-',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
29
37
|
],
|
|
30
38
|
};
|
|
31
39
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
/**
|
|
41
|
+
* load all icons data into a map, keyed by file path
|
|
42
|
+
*
|
|
43
|
+
* @returns {Map<string,string>} Map<iconFilePath, svgString>
|
|
44
|
+
*/
|
|
45
|
+
async function getIcons() {
|
|
46
|
+
const iconFilePaths = await Array.fromAsync(fs.promises.glob(path.join(iconsDir, '*.svg')));
|
|
47
|
+
const icons = new Map();
|
|
48
|
+
for (const iconFilePath of iconFilePaths) {
|
|
49
|
+
const svgString = await fs.promises.readFile(iconFilePath, 'utf8');
|
|
50
|
+
icons.set(iconFilePath, svgString);
|
|
51
|
+
}
|
|
52
|
+
return icons;
|
|
53
|
+
}
|
|
54
|
+
exports.getIcons = getIcons;
|
|
42
55
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
56
|
+
/**
|
|
57
|
+
* @param {Map<string,string>} icons
|
|
58
|
+
* @returns {{spritesheet:object, inlineSpritesheet:object, jsonSpritesheet:object}}
|
|
59
|
+
*/
|
|
60
|
+
async function generateSpritesheets(icons) {
|
|
61
|
+
// load all icon data
|
|
62
|
+
const spritesheet = svgstore();
|
|
63
|
+
const inlineSpritesheet = svgstore({ inline: true, svgAttrs: { id: 'spritesheet', style: 'display: none' } });
|
|
64
|
+
const jsonSpritesheet = {};
|
|
65
|
+
for (const [iconFilePath, svgString] of icons.entries()) {
|
|
66
|
+
// optimize icons - overwrite svgString data in icons map
|
|
67
|
+
const optimizedIcon = optimize(svgString, { path: iconFilePath, ...svgoOptions }).data;
|
|
68
|
+
|
|
69
|
+
// add icons to spritesheets
|
|
70
|
+
const nameFromFilename = path.basename(iconFilePath).replace(/.svg/i, '');
|
|
71
|
+
const prefixedName = `icon-${nameFromFilename}`;
|
|
54
72
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
73
|
+
spritesheet.add(prefixedName, optimizedIcon);
|
|
74
|
+
inlineSpritesheet.add(prefixedName, optimizedIcon);
|
|
75
|
+
jsonSpritesheet[prefixedName] = optimizedIcon;
|
|
76
|
+
}
|
|
77
|
+
return { spritesheet, inlineSpritesheet, jsonSpritesheet };
|
|
78
|
+
}
|
|
79
|
+
exports.generateSpritesheets = generateSpritesheets;
|
|
60
80
|
|
|
61
|
-
|
|
62
|
-
|
|
81
|
+
/**
|
|
82
|
+
* generate spritesheets, and write to disk
|
|
83
|
+
*/
|
|
84
|
+
async function createSvgStack() {
|
|
85
|
+
const icons = await getIcons();
|
|
86
|
+
const { spritesheet, inlineSpritesheet, jsonSpritesheet } = await generateSpritesheets(icons);
|
|
87
|
+
const ourDir = path.resolve(__dirname, '../dist/assets');
|
|
63
88
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
`${path.resolve(__dirname, '../dist/assets', 'icons-inline.svg')}`,
|
|
69
|
-
inlineSprites.toString()
|
|
70
|
-
);
|
|
71
|
-
fs.writeFileSync(`${path.resolve(__dirname, '../dist/assets', 'icons.json')}`, JSON.stringify(icons));
|
|
72
|
-
});
|
|
73
|
-
})
|
|
74
|
-
.catch((err) => {
|
|
75
|
-
reject(err);
|
|
76
|
-
});
|
|
77
|
-
resolve('SVG Stack compiled');
|
|
78
|
-
});
|
|
79
|
-
});
|
|
89
|
+
await fs.promises.mkdir(ourDir, { recursive: true });
|
|
90
|
+
await fs.promises.writeFile(path.join(ourDir, 'icons.svg'), spritesheet.toString(), 'utf-8');
|
|
91
|
+
await fs.promises.writeFile(path.join(ourDir, 'icons-inline.svg'), inlineSpritesheet.toString(), 'utf-8');
|
|
92
|
+
await fs.promises.writeFile(path.join(ourDir, 'icons.json'), JSON.stringify(jsonSpritesheet), 'utf-8');
|
|
80
93
|
}
|
|
81
94
|
|
|
82
95
|
async function svgsprite() {
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
## Callable
|
|
2
|
-
|
|
3
|
-
Use the [callable](https://mozilla.github.io/nunjucks/templating.html#call) syntax to populate the main content
|
|
4
|
-
|
|
5
|
-
## Parameters
|
|
6
|
-
|
|
7
|
-
- `label`: The text inside the trigger button. Be as descriptive as you can as it will help for a11y. **required**
|
|
8
|
-
- `labelOpen`: The text inside of the trigger button when accordion is expanded
|
|
9
|
-
- `labelClasses`: class will be added to the trigger (useful to change the font size)
|
|
10
|
-
- `icon`: override the default icon for the closed state
|
|
11
|
-
- `iconOpen`: override the default icon for the open state
|
|
12
|
-
- `noIcon`: Boolean, removes the icon from the accordion completely
|
|
13
|
-
- `startsOpen`: if `true`, the accordion will be expanded by default. This will be overridden in JS when used as part of a checkbox list with pills, but is still recommended
|
|
14
|
-
as it will auto open the component for people not using JS surfacing the categories.
|
|
15
|
-
- `nonClosing`: boolean to visually hide (for accessibility) the trigger and keep the accordion expanded
|
|
16
|
-
- `breakpoint`: if a value (in px, em, rem) is passed, the accordion will be enabled only when screen size is smaller than the breakpoint
|
|
17
|
-
- `leftAligned`: This will determine if the icon should sit on the left or the right of the trigger (default: false) - See design usage guidelines
|
|
18
|
-
- `contentFirst`: Boolean, places the content above the trigger, pushing the trigger down below the content when open
|
|
19
|
-
|
|
20
|
-
**Note:** Checkbox list with pills is a dependent component and should be checked and updated if any changes to this component are made.
|
|
21
|
-
|
|
22
|
-
## Accessibility
|
|
23
|
-
|
|
24
|
-
When using the non closing accordion, the trigger will be disabled and hidden from view so screenreaders can inform that the content has been expanded. The trigger is also removed from the navigation flow to make sure that it can't be tabbed into when using a keyboard.
|
|
25
|
-
|
|
26
|
-
## Design usage guidelines
|
|
27
|
-
|
|
28
|
-
Where possible, the defaults should remain as they are to ensure we remain consistent across the platform, though there are a few areas where you may need to step
|
|
29
|
-
outside these guidelines, this offers an insight into the design decisions to best ensure you understand context and usage.
|
|
30
|
-
|
|
31
|
-
- `icon`: Where possible, we should ensure that this remains unchanged as the triangles are a universal indicator of collapsable content. However, there are scenarios where this may not work for you. In these scenarios, it is suggested you use one of the following icons: `minus`
|
|
32
|
-
- `iconOpen`: Where possible, we should ensure that this remains unchanged as the triangles are a universal indicator of expandable content. However, there are scenarios where this may not work for you. In these scenarios, it is suggested you use one of the following icons: `plus-small` (Plus is a little too big to align nicely with the content of the trigger)
|
|
33
|
-
- `leftAligned`: Usage for this parameter depends largely on the content surrounding it. There are some cases where we have a list where some items are expandable while others are not so to avoid a misalignment due to the presence of icons or not, we've decided that when in a list the accordions would have the icons on the right. When used as a single component on the page, the icon is on the left instead.
|
|
34
|
-
|
|
35
|
-
## Notes
|
|
36
|
-
|
|
37
|
-
- 15/08/24 - Move to `details` broswer native accordion type component.
|
|
38
|
-
|
|
39
|
-
- 09/12/20 - Non closing accordion - Moved `mds-visually-hidden` to trigger's parent. We noticed an issue on NVDA in Chrome, where the changes on the button like `aria-expanded` or `aria-disabled` were not announced when the button itself was visually hidden.
|
|
40
|
-
|
|
41
|
-
- 02/11/20 - `aria-controls` attribute has been removed from the accordion as it is poorly supported and doesn't work as expected.
|
|
42
|
-
|
|
43
|
-
References:
|
|
44
|
-
|
|
45
|
-
- https://heydonworks.com/article/aria-controls-is-poop/ (that article's title says it all)
|
|
46
|
-
- https://a11ysupport.io/tech/aria/aria-controls_attribute
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
## Callable
|
|
2
|
-
|
|
3
|
-
Use the [callable](https://mozilla.github.io/nunjucks/templating.html#call) syntax to populate the main content
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
## Parameters
|
|
7
|
-
|
|
8
|
-
- `href`: this sets the href and changes the button to an anchor element
|
|
9
|
-
- `classes`: css classes to add on the button (for example `mds-width-full`)
|
|
10
|
-
- `attributes`: you can add extra attributes by passing an object to the parameter. Example: `attributes: { attribute-name: 'attribute-value' }`
|
|
11
|
-
|
|
12
|
-
## Full width button
|
|
13
|
-
|
|
14
|
-
We have 2 helpers classes that can help you achieve full width buttons at different sizes.
|
|
15
|
-
`.mds-width-full` and `.mds-width-auto`.
|
|
16
|
-
|
|
17
|
-
For example, if you would like your button to be full width at mobile size and have `width: auto` at any wider size, add the following classes on the button (using the `classes` parameter): `mds-width-full mds-width-md-auto`.
|
|
18
|
-
|
|
19
|
-
`mds-button--icon` can be used to adjust the padding to better fit around an icon button.
|
|
20
|
-
|
|
21
|
-
Both helper classes are set with breakpoints. Just add the name of the class followed by the breakpoint name (`sm`, `md`, `lg`, `xl`) and the value (`full` or `auto`).
|
|
22
|
-
|
|
23
|
-
## Prevent Double Submit
|
|
24
|
-
|
|
25
|
-
Helper class `.js-mds-button-double-submit`
|
|
26
|
-
|
|
27
|
-
If you click the form button twice in a row (slower than dobule click but faster than submitting), the browser can submit the form twice. Adding this class will disable the button for 1 second to prevent a double submission.
|