@madgex/design-system 3.0.8 → 3.0.9

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 (57) hide show
  1. package/coverage/cobertura-coverage.xml +126 -96
  2. package/coverage/components/accordion/accordion.js.html +1 -1
  3. package/coverage/components/accordion/index.html +1 -1
  4. package/coverage/components/button/button.js.html +1 -1
  5. package/coverage/components/button/index.html +1 -1
  6. package/coverage/components/inputs/combobox/combobox.js.html +1 -1
  7. package/coverage/components/inputs/combobox/index.html +1 -1
  8. package/coverage/components/inputs/combobox/vue-components/Combobox.vue.html +120 -36
  9. package/coverage/components/inputs/combobox/vue-components/ListBoxOption.vue.html +1 -1
  10. package/coverage/components/inputs/combobox/vue-components/index.html +19 -19
  11. package/coverage/components/inputs/file-upload/file-upload.js.html +1 -1
  12. package/coverage/components/inputs/file-upload/index.html +1 -1
  13. package/coverage/components/inputs/textarea/character-count.js.html +1 -1
  14. package/coverage/components/inputs/textarea/index.html +1 -1
  15. package/coverage/components/modal/index.html +1 -1
  16. package/coverage/components/modal/modal.js.html +1 -1
  17. package/coverage/components/notification/index.html +1 -1
  18. package/coverage/components/notification/notification.js.html +1 -1
  19. package/coverage/components/popover/index.html +1 -1
  20. package/coverage/components/popover/popover.js.html +1 -1
  21. package/coverage/components/switch-state/index.html +1 -1
  22. package/coverage/components/switch-state/switch-state.js.html +1 -1
  23. package/coverage/components/tabs/index.html +1 -1
  24. package/coverage/components/tabs/tabs.js.html +1 -1
  25. package/coverage/index.html +19 -19
  26. package/coverage/js/common.js.html +1 -1
  27. package/coverage/js/fractal-scripts/combobox.js.html +1 -1
  28. package/coverage/js/fractal-scripts/index.html +1 -1
  29. package/coverage/js/fractal-scripts/notification.js.html +1 -1
  30. package/coverage/js/fractal-scripts/switch-state.js.html +1 -1
  31. package/coverage/js/index-fractal.js.html +1 -1
  32. package/coverage/js/index-polyfills.js.html +1 -1
  33. package/coverage/js/index-vue.js.html +1 -1
  34. package/coverage/js/index.html +1 -1
  35. package/coverage/js/index.js.html +1 -1
  36. package/coverage/js/polyfills/arrayPrototypeFind.js.html +1 -1
  37. package/coverage/js/polyfills/closest.js.html +1 -1
  38. package/coverage/js/polyfills/index.html +1 -1
  39. package/coverage/js/polyfills/objectAssign.js.html +1 -1
  40. package/coverage/js/polyfills/remove.js.html +1 -1
  41. package/coverage/tokens/_config.js.html +1 -1
  42. package/coverage/tokens/index.html +1 -1
  43. package/dist/_tokens/css/_tokens.css +1 -1
  44. package/dist/_tokens/js/_tokens-module.js +1 -1
  45. package/dist/_tokens/scss/_tokens.scss +1 -1
  46. package/dist/js/index.js +1 -1
  47. package/package.json +1 -1
  48. package/src/components/inputs/_form-elements.scss +1 -1
  49. package/src/components/inputs/combobox/README.md +2 -2
  50. package/src/components/inputs/combobox/_template.njk +2 -10
  51. package/src/components/inputs/combobox/combobox.config.js +12 -2
  52. package/src/components/inputs/combobox/combobox.njk +0 -1
  53. package/src/components/inputs/combobox/vue-components/Combobox.vue +42 -14
  54. package/src/scss/core/_containers.scss +1 -1
  55. package/src/scss/functions/_px2rem.scss +1 -1
  56. package/src/scss/import.scss +1 -0
  57. package/src/scss/vendor/_sass-mq.scss +1 -1
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@madgex/design-system",
3
3
  "author": "Madgex",
4
4
  "license": "UNLICENSED",
5
- "version": "3.0.8",
5
+ "version": "3.0.9",
6
6
  "scripts": {
7
7
  "clean": "rimraf dist public tokens/build",
8
8
  "commit": "commit",
@@ -23,7 +23,7 @@
23
23
  .mds-form-label__required {
24
24
  color: $mds-color-status-error-dark;
25
25
  top: 0;
26
- width: $mds-font-size-base / 2;
26
+ width: math.div($mds-font-size-base, 2);
27
27
  margin-left: $mds-size-baseline;
28
28
  }
29
29
  .mds-form-label__tooltip {
@@ -2,7 +2,6 @@
2
2
 
3
3
  - `id`: the id of your combobox
4
4
  - `name`: the name of the input for form submission. Uses ID unless specified - _optional_
5
- - `resultMessage`: to be used as a prop for the Vue component below, will not be used if Javascript is not available
6
5
  - `labelText`: the text used in the label
7
6
  - `options`: a json object of key, value pairs e.g { 45: 'Orange' }. To be used when falling back to a native select if Javascript is not available
8
7
  - `value`: a default selected value for the input - _optional_
@@ -20,7 +19,6 @@
20
19
  - `comboboxid`: the id of your combobox. Populated automatically from Nunjucks parameters
21
20
  - `labeltext`: the text used in the label. Populated automatically from Nunjucks parameters
22
21
  - `placeholder`: the placeholder for your input. Populated automatically from Nunjucks parameters
23
- - `resultmessage`: the visually hidden message to inform screenreader users when the options in the listbox have changed. Can either be a string which will be prefixed with the number of options, or a function which takes the number of options as its parameter and which should return a string. Defaults to 'options available', populated automatically from Nunjucks parameters if passed in
24
22
  - `name`: the name of the input for form submission. Will only be populated automatically if fallbackTo is 'input'
25
23
  - `value`: a default value for the combobox input. Populated automatically from Nunjucks parameters
26
24
  - `options`: an array of options, which should be objects with a `label` and a `value`. The array should be provided externally by selecting the custom `<mds-combobox>` element and setting it as an attribute
@@ -33,3 +31,5 @@ The Vue component is a [WAI-ARIA 1.0 combobox](https://www.w3.org/TR/wai-aria-pr
33
31
  NB. The AJAX demo above currently only works in browsers, not <= IE11. Fetch will be polyfilled or replaced in due course.
34
32
 
35
33
  When Javascript is not available, either a native combobox or native input will be available as a fallback.
34
+
35
+ aria-describedBy has been added to notify screen reader users how to interact with the autocomplete suggestions.
@@ -20,14 +20,6 @@
20
20
  {% set comboboxName = comboboxId %}
21
21
  {% endif %}
22
22
 
23
- {%- set placeholder %}
24
- {%- if params.placeholder -%}
25
- {{ params.placeholder }}
26
- {%- else -%}
27
- Please select
28
- {%- endif -%}
29
- {% endset -%}
30
-
31
23
  {%- set labelId %}{{comboboxId}}-label{% endset -%}
32
24
 
33
25
  {%- if comboboxId -%}
@@ -60,8 +52,8 @@
60
52
  {% endif %}
61
53
  </div>
62
54
  {# Leave the custom element at the bottom so it has access to the above elements on render #}
63
- <mds-combobox comboboxid="{{ comboboxId }}" placeholder="{{ placeholder }}" iconpath="{{ defaultIconPath }}" data-aria-invalid="{{ params.validationError }}"
64
- {% if params.fallbackTo === 'input' %}name="{{ comboboxName }}"{% endif %} {% if params.resultMessage %}resultmessage="{{ params.resultMessage }}"{% endif %}
55
+ <mds-combobox comboboxid="{{ comboboxId }}" placeholder="{{ params.placeholder }}" iconpath="{{ defaultIconPath }}" data-aria-invalid="{{ params.validationError }}"
56
+ {% if params.fallbackTo === 'input' %}name="{{ comboboxName }}"{% endif %}
65
57
  {% if params.value %}value="{{ params.value }}"{% endif %}
66
58
  ></mds-combobox>
67
59
  </div>
@@ -22,12 +22,22 @@ module.exports = {
22
22
  variantTitle: 'AJAX autocomplete',
23
23
  name: 'keywords',
24
24
  id: 'keywords-lookup',
25
- resultMessage: 'suggestions',
26
25
  labelText: 'Keywords:',
27
- value: 'Initial value',
28
26
  placeholder: 'eg. Web developer',
29
27
  fallbackTo: 'input',
30
28
  },
31
29
  },
30
+ {
31
+ name: 'AJAX autocomplete prefilled',
32
+ context: {
33
+ variantTitle: 'AJAX autocomplete prefilled',
34
+ name: 'keywords',
35
+ id: 'keywords-lookup',
36
+ labelText: 'Keywords:',
37
+ placeholder: 'eg. Testimonials',
38
+ value: 'Initial Value',
39
+ fallbackTo: 'input',
40
+ },
41
+ },
32
42
  ],
33
43
  };
@@ -6,7 +6,6 @@
6
6
  {{ MdsCombobox({
7
7
  id: id,
8
8
  name: name,
9
- resultMessage: resultMessage,
10
9
  labelText: labelText,
11
10
  options: options,
12
11
  optional: optional,
@@ -12,6 +12,7 @@
12
12
  <ComboboxInput
13
13
  @change="handleChange"
14
14
  @blur="onInputBlur"
15
+ @focus="handleFocus"
15
16
  :id="comboboxid"
16
17
  :name="name"
17
18
  :placeholder="placeholder"
@@ -19,6 +20,7 @@
19
20
  :aria-expanded="ariaExpanded"
20
21
  :activeDescendent="selectedOptionId"
21
22
  :ariaInvalid="ariaInvalid"
23
+ :aria-describedby="describedBy"
22
24
  v-model="inputValue"
23
25
  />
24
26
  <ListBox :id="listBoxId" :hidden="listBoxHidden" :isLoading="isLoading" :comboboxid="comboboxid">
@@ -34,7 +36,10 @@
34
36
  />
35
37
  </template>
36
38
  </ListBox>
37
- <div aria-live="polite" role="status" class="mds-visually-hidden">{{ resultCount }}</div>
39
+ <div aria-live="polite" role="status" class="mds-visually-hidden">{{ resultCountMessage }}</div>
40
+ <span :id="describedBy" style="display: none">
41
+ When autocomplete results are available use up and down arrows to review and enter to select.
42
+ </span>
38
43
  </div>
39
44
  </template>
40
45
 
@@ -57,11 +62,7 @@ export default {
57
62
  },
58
63
  placeholder: {
59
64
  type: String,
60
- default: 'Please combobox',
61
- },
62
- resultmessage: {
63
- type: [String, Function],
64
- default: 'options available',
65
+ default: '',
65
66
  },
66
67
  name: {
67
68
  type: [String, Boolean],
@@ -94,6 +95,9 @@ export default {
94
95
  selected: null,
95
96
  chosen: null,
96
97
  searchValue: this.$props.value,
98
+ resultCountMessage: null,
99
+ resultMessage: 'result available',
100
+ resultMessage_plural: 'results available',
97
101
  };
98
102
  },
99
103
  provide() {
@@ -107,6 +111,7 @@ export default {
107
111
  if (this.chosenOption) {
108
112
  return this.chosenOption.label;
109
113
  }
114
+
110
115
  return this.searchValue;
111
116
  },
112
117
  set(event) {
@@ -115,6 +120,9 @@ export default {
115
120
  this.searchValue = event.target ? event.target.value : '';
116
121
  this.handleChange();
117
122
  this.$emit('search', this.searchValue);
123
+ if (this.visibleOptions.length > 0) {
124
+ this.updateCount();
125
+ }
118
126
  },
119
127
  },
120
128
  selectedOption: {
@@ -139,6 +147,7 @@ export default {
139
147
  if (this.filterOptions) {
140
148
  return this.options.filter((opt) => opt.label.toLowerCase().includes(this.searchValue.toLowerCase()));
141
149
  }
150
+
142
151
  return this.options;
143
152
  },
144
153
  listBoxId() {
@@ -147,14 +156,19 @@ export default {
147
156
  optionId() {
148
157
  return `${this.comboboxid}-option`;
149
158
  },
159
+ describedBy() {
160
+ return `${this.comboboxid}-assistiveHint`;
161
+ },
150
162
  isLoading() {
151
163
  return this.options.length === 0 && this.expanded;
152
164
  },
153
165
  selectedOptionId() {
154
166
  const index = this.visibleOptions.indexOf(this.selectedOption);
167
+
155
168
  if (index > -1) {
156
169
  return `${this.optionId}-${index}`;
157
170
  }
171
+
158
172
  return false;
159
173
  },
160
174
  listBoxHidden() {
@@ -163,12 +177,6 @@ export default {
163
177
  lastOptionIndex() {
164
178
  return this.visibleOptions.length - 1;
165
179
  },
166
- resultCount() {
167
- if (typeof this.resultmessage === 'function') {
168
- return this.resultmessage(this.visibleOptions.length);
169
- }
170
- return `${this.visibleOptions.length} ${this.resultmessage}`;
171
- },
172
180
  ariaExpanded() {
173
181
  // These must be strings to apply as an aria attribute of the same name
174
182
  return this.expanded ? 'true' : 'false';
@@ -191,6 +199,12 @@ export default {
191
199
  this.makeInactive();
192
200
  }
193
201
  },
202
+ handleFocus() {
203
+ this.handleChange();
204
+ if (this.visibleOptions.length > 1) {
205
+ this.updateCount();
206
+ }
207
+ },
194
208
  clickOption(option = this.selectedOption) {
195
209
  this.chosenOption = option;
196
210
  this.makeInactive();
@@ -198,6 +212,7 @@ export default {
198
212
  chooseOption() {
199
213
  this.chosenOption = this.selectedOption;
200
214
  this.makeInactive();
215
+ this.clearCount();
201
216
  },
202
217
  hiddenGuard(fn) {
203
218
  if (this.listBoxHidden) return;
@@ -205,11 +220,13 @@ export default {
205
220
  },
206
221
  onInputBlur() {
207
222
  this.makeInactive();
223
+ this.clearCount();
208
224
  },
209
225
  onKeyDown() {
210
226
  if (this.selectedOption) {
211
227
  const currentIndex = this.visibleOptions.indexOf(this.selectedOption);
212
- const nextIndex = currentIndex === this.lastOptionIndex ? 0 : currentIndex + 1;
228
+ const nextIndex = currentIndex === this.lastOptionIndex ? currentIndex : currentIndex + 1;
229
+
213
230
  this.selectedOption = this.visibleOptions[nextIndex];
214
231
  } else {
215
232
  [this.selectedOption] = this.visibleOptions;
@@ -218,7 +235,8 @@ export default {
218
235
  onKeyUp() {
219
236
  if (this.selectedOption) {
220
237
  const currentIndex = this.visibleOptions.indexOf(this.selectedOption);
221
- const nextIndex = currentIndex === 0 ? this.lastOptionIndex : currentIndex - 1;
238
+ const nextIndex = currentIndex === 0 ? currentIndex : currentIndex - 1;
239
+
222
240
  this.selectedOption = this.visibleOptions[nextIndex];
223
241
  } else {
224
242
  this.selectedOption = this.visibleOptions[this.lastOptionIndex];
@@ -230,6 +248,16 @@ export default {
230
248
  onKeyEnd() {
231
249
  this.selectedOption = this.visibleOptions[this.lastOptionIndex];
232
250
  },
251
+ updateCount() {
252
+ setTimeout(() => {
253
+ const message = this.visibleOptions.length === 1 ? this.resultMessage_plural : this.resultMessage;
254
+
255
+ this.resultCountMessage = `${this.visibleOptions.length} ${message}`;
256
+ }, 1400);
257
+ },
258
+ clearCount() {
259
+ this.resultCountMessage = null;
260
+ },
233
261
  },
234
262
  };
235
263
  </script>
@@ -92,7 +92,7 @@ $mds-half-gutter-width: $mds-size-gutter-width * 0.5;
92
92
  // Calculate space left between the wrapper and the edge of the screen on each side
93
93
  // so we can stretch the sticky container to make it appear full screen
94
94
  // I added 0.01 to stretch the container slightly more to avoid a tiny gap between the edge of the screen and the container
95
- $space-between-wrapper-and-edge: (100% - $mds-size-wrapper-width) / 2 + 0.01;
95
+ $space-between-wrapper-and-edge: math.div(100% - $mds-size-wrapper-width, 2) + 0.01;
96
96
 
97
97
  .mds-fixed-container--sticky {
98
98
  position: sticky;
@@ -16,5 +16,5 @@
16
16
  } @else if unit($px) == rem {
17
17
  @return $px;
18
18
  }
19
- @return ($px / $base-size) * 1rem;
19
+ @return math.div($px, $base-size) * 1rem;
20
20
  }
@@ -1,3 +1,4 @@
1
+ @use "sass:math";
1
2
  @import 'vendor/normalize';
2
3
  @import 'resets/_index';
3
4
  @import 'functions/_index';
@@ -94,7 +94,7 @@ $mq-media-type: all !default;
94
94
  } @else if unit($px) == em {
95
95
  @return $px;
96
96
  }
97
- @return ($px / $base-font-size) * 1em;
97
+ @return math.div($px, $base-font-size) * 1em;
98
98
  }
99
99
 
100
100
  /// Get a breakpoint's width