@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.
Files changed (38) hide show
  1. package/dist/assets/icons-inline.svg +1 -1
  2. package/dist/assets/icons.json +1 -1
  3. package/dist/assets/icons.svg +1 -1
  4. package/dist/js/index.js +1 -1
  5. package/package.json +4 -4
  6. package/src/components/accordion/_template.njk +35 -33
  7. package/src/components/accordion/accordion.config.js +0 -81
  8. package/src/components/accordion/accordion.js +54 -43
  9. package/src/components/accordion/accordion.njk +1 -24
  10. package/src/components/accordion/accordion.spec.js +170 -0
  11. package/src/components/button/button.config.js +1 -42
  12. package/src/components/button/button.njk +1 -14
  13. package/src/components/card/card.config.js +0 -93
  14. package/src/components/card/card.njk +1 -22
  15. package/src/components/icons/icons.njk +1 -161
  16. package/src/components/inputs/combobox/README.md +22 -1
  17. package/src/components/inputs/combobox/combobox.njk +26 -2
  18. package/src/js/index.js +5 -2
  19. package/src/layout/containers/index.njk +1 -0
  20. package/src/typography/index.njk +1 -0
  21. package/tasks/svgsprite.js +62 -49
  22. package/src/components/accordion/README.md +0 -46
  23. package/src/components/button/README.md +0 -27
  24. package/src/components/card/README.md +0 -114
  25. package/src/components/icons/README.md +0 -62
  26. package/src/layout/containers/01-base-containers.njk +0 -30
  27. package/src/layout/containers/02-branded-containers.njk +0 -13
  28. package/src/layout/containers/03-ad-containers.njk +0 -6
  29. package/src/layout/containers/04-highlighted-containers.njk +0 -3
  30. package/src/layout/containers/README.md +0 -30
  31. package/src/layout/containers/ad-containers.config.json +0 -3
  32. package/src/layout/containers/base-containers.config.json +0 -3
  33. package/src/layout/containers/branded-containers.config.json +0 -3
  34. package/src/layout/containers/highlighted-containers.config.json +0 -3
  35. package/src/typography/font-types.config.json +0 -3
  36. package/src/typography/font-types.njk +0 -43
  37. package/src/typography/headings.njk +0 -9
  38. package/src/typography/lists.njk +0 -111
@@ -1,161 +1 @@
1
- {# NUNJUCKS VERSION #}
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 &lt;form&gt; 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>
@@ -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 filepath = path.resolve(__dirname, '../src/icons/');
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
- cleanupIDs: {
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
- let files = [];
33
- const icons = [];
34
- const sprites = svgstore();
35
- const inlineSprites = svgstore({
36
- inline: true,
37
- svgAttrs: {
38
- id: 'spritesheet',
39
- style: 'display: none',
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
- async function createSvgStack() {
44
- return new Promise((resolve, reject) => {
45
- files = fs.readdirSync(filepath);
46
- files.forEach((file) => {
47
- // eslint-disable-next-line promise/param-names
48
- new Promise((res) => {
49
- const svgdata = fs.readFileSync(`${path.resolve(__dirname, filepath, file)}`, { encoding: 'utf8' });
50
- const result = optimize(svgdata, {
51
- path: `${path.resolve(__dirname, filepath, file)}`,
52
- ...svgoOptions,
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
- res(result);
56
- })
57
- .then((icon) => {
58
- const fileName = path.parse(file).name;
59
- const prefixedName = `icon-${fileName}`;
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
- sprites.add(prefixedName, icon.data);
62
- inlineSprites.add(prefixedName, icon.data);
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
- return fs.mkdir(path.resolve(__dirname, '../dist/assets'), { recursive: true }, async () => {
65
- icons.push({ name: fileName });
66
- fs.writeFileSync(`${path.resolve(__dirname, '../dist/assets', 'icons.svg')}`, sprites.toString());
67
- fs.writeFileSync(
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.