@madgex/design-system 13.8.0 → 14.0.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/dist/assets/icons.json +1 -1
- package/dist/css/index.css +1 -1
- package/package.json +1 -1
- package/src/components/inputs/button-checkbox/button-checkbox.config.js +12 -0
- package/src/components/inputs/button-checkbox/button-checkbox.scss +2 -1
- package/src/components/inputs/combobox/README.md +160 -32
- package/src/components/inputs/combobox/_template.njk +37 -14
- package/src/components/inputs/combobox/combobox.config.js +74 -24
- package/src/components/inputs/combobox/combobox.njk +5 -19
- package/src/components/inputs/combobox/combobox.scss +59 -27
- package/src/components/scroll-spy/scroll-spy.njk +19 -1
- package/src/scss/core/_defaults.scss +1 -1
- package/src/scss/core/_lists.scss +28 -4
package/package.json
CHANGED
|
@@ -37,5 +37,17 @@ module.exports = {
|
|
|
37
37
|
},
|
|
38
38
|
},
|
|
39
39
|
},
|
|
40
|
+
{
|
|
41
|
+
name: 'No Description',
|
|
42
|
+
context: {
|
|
43
|
+
name: 'no-description',
|
|
44
|
+
value: 'no-description',
|
|
45
|
+
i18n: {
|
|
46
|
+
title: 'No Description',
|
|
47
|
+
description: '',
|
|
48
|
+
price: '£7',
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
},
|
|
40
52
|
],
|
|
41
53
|
};
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
cursor: pointer;
|
|
7
7
|
border: #{$regular-border};
|
|
8
8
|
border-radius: $border-radius;
|
|
9
|
-
justify-content: space-
|
|
9
|
+
justify-content: space-evenly;
|
|
10
10
|
padding-left: ($constant-size-baseline * 4);
|
|
11
11
|
|
|
12
12
|
& > * {
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
width: 100px;
|
|
34
34
|
max-width: 30%;
|
|
35
35
|
white-space: nowrap;
|
|
36
|
+
margin-left: auto;
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
// Selected (checked) state
|
|
@@ -1,23 +1,34 @@
|
|
|
1
|
+
# MdsCombobox
|
|
2
|
+
|
|
3
|
+
This component provides autocomplete search functionality to select an option from a list of options.
|
|
4
|
+
|
|
5
|
+
Options can be provided via the `options` parameter, or obtained from an API using the `apiUrl` parameter.
|
|
6
|
+
|
|
7
|
+
`value` is an Object or Array of Objects representing the selected option or options.
|
|
8
|
+
|
|
1
9
|
## Parameters - Nunjucks
|
|
2
10
|
|
|
3
|
-
- `id`: the id of your combobox
|
|
4
|
-
- `name`: the name of the input for form submission. Uses ID unless specified -
|
|
5
|
-
- `labelText`: the text used in the label
|
|
6
|
-
- `
|
|
7
|
-
- `
|
|
8
|
-
- `
|
|
9
|
-
- `
|
|
10
|
-
- `
|
|
11
|
-
- `
|
|
12
|
-
- `
|
|
13
|
-
- `
|
|
14
|
-
- `
|
|
15
|
-
- `
|
|
16
|
-
- `
|
|
17
|
-
- `
|
|
18
|
-
- `
|
|
19
|
-
- `
|
|
20
|
-
- `
|
|
11
|
+
- `id`: the id of your combobox **required**
|
|
12
|
+
- `name`: the name of the input for form submission. Uses ID unless specified - **recommended**
|
|
13
|
+
- `labelText`: the text used in the label **required**
|
|
14
|
+
- `value`: the populated option `object` ( `{ label: 'Orange', value: 45 }`) or `array` of option `objects` ( `[{ label: 'Orange', value: 45 }, { label: 'Green', value: 33 }]`)
|
|
15
|
+
- `searchText`: _Not_ the value, but the current text inside the search input.
|
|
16
|
+
- `options`: an `array`, e.g `[{ label: 'Orange', value: 45 }]`. Populates both mds-combobox, and fallback select options
|
|
17
|
+
- `apiUrl`: when populated, `options` is ignored and data is fetched from an API URL instead
|
|
18
|
+
- `apiQueryKey`: the query parameter name added to `apiUrl` - (defaults to 'searchText')
|
|
19
|
+
- `apiOptionsPath`: where to grab an array of options on api response, e.g. `data.options` would be an array of options. leave undefined to use root api response as array
|
|
20
|
+
- `optionLabelPath`: where to grab the visual label from the option object e.g. 'label' or 'title' or 'nested.object.label' (defaults to `label`)
|
|
21
|
+
- `optionValuePath`: where to grab the value from the option object e.g. `value` or `nested.object.value` (defaults to `value`)
|
|
22
|
+
- `multiple`: Boolean, whether to treat `value` input and output as an Array, or a singular. Also to display pills. default `false`
|
|
23
|
+
- `fallbackTo`: the form element to use as a fallback. Should be either 'select' or 'input' **recommended**
|
|
24
|
+
- `placeholder`: the placeholder for your input (defaults to 'Please select') **recommended**
|
|
25
|
+
- `classes`: add extra classes to the trigger
|
|
26
|
+
- `helpText`: Helper text to display under the label
|
|
27
|
+
- `tooltipMessage`: Toggles a tooltip with this message to appear on the input
|
|
28
|
+
- `validationError`: The error message provided by validation
|
|
29
|
+
- `state`: The current state of the input, currently the only allowed value is `error`
|
|
30
|
+
- `type`: applied as data-type` attribute, the name of the options api e.g "location-lookup"
|
|
31
|
+
- `i18n`: an `object`, Text to translate/customise
|
|
21
32
|
- `minSearchCharacters`: The minimum number of characters inside the input before a search is performed to avoid low specificity searches. This should be matched by your implementation's search handler.
|
|
22
33
|
|
|
23
34
|
```
|
|
@@ -30,41 +41,158 @@ i18n: {
|
|
|
30
41
|
resultsMessage: '{count} result available.', // announce number of results - note the use of `{count}` to get the number of results
|
|
31
42
|
resultsMessage_plural: '{count} results available.', // announce number of results (plural) - note the use of `{count}` to get the number of results
|
|
32
43
|
clearInput: 'clear input', // text for screen readers explaining what the clear control in combobox does
|
|
44
|
+
removePill: 'Remove {label}', // remove button aria label for pill, if using `multiple:true`
|
|
45
|
+
selectedOptionsLabel: 'Selected options:' // visually hidden text introducing the list of selected options, if using `multiple:true`
|
|
33
46
|
}
|
|
34
47
|
```
|
|
35
48
|
|
|
36
|
-
##
|
|
49
|
+
## Usage
|
|
37
50
|
|
|
38
|
-
|
|
51
|
+
MdsCombobox usage revolves around either options provided by `params.options` or an API (`apiUrl` in use), and being in `multiple` mode via `params.multiple`.
|
|
52
|
+
If `multiple` mode is true,`params.value` must be undefined or an `array`, otherwise undefined or an `object`.
|
|
39
53
|
|
|
40
|
-
|
|
54
|
+
The params `value`, `options`, `optionLabelPath` and `optionValuePath` are tightly coupled and must be compatible with each other:
|
|
41
55
|
|
|
42
|
-
|
|
56
|
+
- `options`: an array of objects, each object has the property stated by `optionLabelPath` and `optionValuePath`
|
|
57
|
+
- `value`: an object ( or array of objects if `multiple:true`), object is the same shape as the ones in `options`, each object has the property stated by `optionLabelPath` and `optionValuePath`
|
|
58
|
+
|
|
59
|
+
### Example - Single mode - no API - default option object shape
|
|
60
|
+
|
|
61
|
+
As our options object uses the default property names, we don't need to specify them.
|
|
43
62
|
|
|
44
63
|
```njk
|
|
45
|
-
{\% call MdsCombobox({
|
|
46
|
-
|
|
64
|
+
{\% call MdsCombobox({
|
|
65
|
+
id:'my-id',
|
|
66
|
+
name: 'my-combo',
|
|
67
|
+
labelText:'My Combo',
|
|
68
|
+
options: [{label: 'my-label-1', value: 'value-1'},{label: 'my-label-2', value: 'value-2'} ]
|
|
69
|
+
}) \%}
|
|
47
70
|
{\% endcall \%}
|
|
71
|
+
|
|
48
72
|
```
|
|
49
73
|
|
|
50
|
-
|
|
74
|
+
#### with prefilled value
|
|
51
75
|
|
|
52
|
-
|
|
76
|
+
```njk
|
|
77
|
+
{\% call MdsCombobox({
|
|
78
|
+
id:'my-id',
|
|
79
|
+
name: 'my-combo',
|
|
80
|
+
labelText:'My Combo',
|
|
81
|
+
value: {value: 'value-2', label: 'my-label-2'},
|
|
82
|
+
options: [{label: 'my-label-1', value: 'value-1'},{label: 'my-label-2', value: 'value-2'} ]
|
|
83
|
+
}) \%}
|
|
84
|
+
{\% endcall \%}
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Example - Multiple mode - no API - default option object shape
|
|
53
89
|
|
|
54
90
|
```njk
|
|
55
|
-
{\% call MdsCombobox({
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
91
|
+
{\% call MdsCombobox({
|
|
92
|
+
id:'my-id',
|
|
93
|
+
name: 'my-combo',
|
|
94
|
+
labelText:'My Combo',
|
|
95
|
+
options: [{label: 'my-label-1', value: 'value-1'},{label: 'my-label-2', value: 'value-2'} ],
|
|
96
|
+
multiple: true
|
|
97
|
+
}) \%}
|
|
59
98
|
{\% endcall \%}
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
#### with prefilled value
|
|
103
|
+
|
|
104
|
+
Note the value should be an array when using multiple mode.
|
|
105
|
+
|
|
106
|
+
```njk
|
|
107
|
+
{\% call MdsCombobox({
|
|
108
|
+
id:'my-id',
|
|
109
|
+
name: 'my-combo',
|
|
110
|
+
labelText:'My Combo',
|
|
111
|
+
value: [{value: 'value-2', label: 'my-label-2'}],
|
|
112
|
+
options: [{label: 'my-label-1', value: 'value-1'},{label: 'my-label-2', value: 'value-2'} ],
|
|
113
|
+
multiple: true
|
|
114
|
+
}) \%}
|
|
115
|
+
{\% endcall \%}
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Example - Single mode - API usage - custom option object shape
|
|
120
|
+
|
|
121
|
+
API response options have a custom shape with `word` and `score` properties,
|
|
122
|
+
like so `[{word: 'something', score: 12},...]`. It also used `?keyword` for the query param on the request.
|
|
123
|
+
|
|
124
|
+
```njk
|
|
125
|
+
{\% call MdsCombobox({
|
|
126
|
+
id:'my-id',
|
|
127
|
+
name: 'my-combo',
|
|
128
|
+
labelText:'My Combo',
|
|
129
|
+
apiUrl: '/api/location-lookup',
|
|
130
|
+
apiQueryKey: 'keyword',
|
|
131
|
+
optionLabelPath: 'word',
|
|
132
|
+
optionValuePath: 'score'
|
|
133
|
+
}) \%}
|
|
134
|
+
{\% endcall \%}
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
#### with prefilled value
|
|
139
|
+
|
|
140
|
+
```njk
|
|
141
|
+
{\% call MdsCombobox({
|
|
142
|
+
id:'my-id',
|
|
143
|
+
name: 'my-combo',
|
|
144
|
+
labelText:'My Combo',
|
|
145
|
+
value: {word: 'my-label-2', score: 'value-2'},
|
|
146
|
+
apiUrl: '/api/location-lookup',
|
|
147
|
+
apiQueryKey: 'keyword',
|
|
148
|
+
optionLabelPath: 'word',
|
|
149
|
+
optionValuePath: 'score'
|
|
150
|
+
}) \%}
|
|
151
|
+
{\% endcall \%}
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Example - Multiple mode - API usage - default option object shape
|
|
156
|
+
|
|
157
|
+
API response had a root object property called `data`, like so `{data:[{label: 'something', value: 12},...]}`.
|
|
158
|
+
|
|
159
|
+
```njk
|
|
160
|
+
{\% call MdsCombobox({
|
|
161
|
+
id:'my-id',
|
|
162
|
+
name: 'my-combo',
|
|
163
|
+
labelText:'My Combo',
|
|
164
|
+
apiUrl: '/api/location-lookup',
|
|
165
|
+
apiOptionsPath: 'data',
|
|
166
|
+
multiple: true
|
|
167
|
+
}) \%}
|
|
168
|
+
{\% endcall \%}
|
|
169
|
+
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
options:
|
|
173
|
+
|
|
174
|
+
#### with prefilled value
|
|
175
|
+
|
|
176
|
+
Note the value is an array for multiple mode.
|
|
177
|
+
|
|
178
|
+
```njk
|
|
179
|
+
{\% call MdsCombobox({
|
|
180
|
+
id:'my-id',
|
|
181
|
+
name: 'my-combo',
|
|
182
|
+
labelText:'My Combo',
|
|
183
|
+
value: [{label: 'my-label-1', value: 'value-1'},{label: 'my-label-2', value: 'value-2'} ],
|
|
184
|
+
apiUrl: '/api/location-lookup',
|
|
185
|
+
apiOptionsPath: 'data',
|
|
186
|
+
multiple: true
|
|
187
|
+
}) \%}
|
|
188
|
+
{\% endcall \%}
|
|
189
|
+
|
|
60
190
|
```
|
|
61
191
|
|
|
62
192
|
## Accessibility
|
|
63
193
|
|
|
64
194
|
The Vue component is a [WAI-ARIA 1.0 combobox](https://www.w3.org/TR/wai-aria-practices/#combobox).
|
|
65
195
|
|
|
66
|
-
NB. The AJAX demo above currently only works in browsers, not <= IE11. Fetch will be polyfilled or replaced in due course.
|
|
67
|
-
|
|
68
196
|
When Javascript is not available, either a native combobox or native input will be available as a fallback.
|
|
69
197
|
|
|
70
198
|
aria-describedBy has been added to notify screen reader users how to interact with the autocomplete suggestions.
|
|
@@ -55,57 +55,80 @@
|
|
|
55
55
|
}) }}
|
|
56
56
|
{# Leave the custom element at the bottom so it has access to the above elements on render #}
|
|
57
57
|
<mds-combobox
|
|
58
|
-
|
|
58
|
+
combobox-id="{{ comboboxId }}"
|
|
59
|
+
name="{{ comboboxName }}"
|
|
59
60
|
placeholder="{{ params.placeholder }}"
|
|
60
61
|
iconpath="{{ defaultIconPath }}"
|
|
61
|
-
{% if params.options.length %}options="{{params.options | dump}}"{% endif %}
|
|
62
|
+
{% if params.options and params.options.length %}options="{{params.options | dump }}"{% endif %}
|
|
62
63
|
{% if params.apiUrl %}api-url="{{params.apiUrl}}"{% endif%}
|
|
63
64
|
{% if params.apiQueryKey %}api-query-key="{{params.apiQueryKey}}"{% endif%}
|
|
64
65
|
{% if params.apiOptionsPath %}api-options-path="{{params.apiOptionsPath}}"{% endif%}
|
|
65
66
|
{% if params.optionLabelPath %}option-label-path="{{params.optionLabelPath}}"{% endif%}
|
|
67
|
+
{% if params.optionValuePath %}option-value-path="{{params.optionValuePath}}"{% endif%}
|
|
66
68
|
i18n="{{ params.i18n | dump }}"
|
|
67
69
|
data-aria-invalid="{{ params.validationError }}"
|
|
68
70
|
{% if params.minSearchCharacters %}min-search-characters="{{ params.minSearchCharacters }}"{% endif %}
|
|
69
|
-
{% if params.
|
|
70
|
-
{% if params.
|
|
71
|
+
{% if params.value %}value="{{ params.value | dump }}"{% endif %}
|
|
72
|
+
{% if params.searchText %}search-text="{{ params.searchText }}"{% endif %}
|
|
73
|
+
{% if params.multiple %}multiple{% endif %}
|
|
71
74
|
{% if ariaDescribedBy %} describedby-id="{{ariaDescribedBy}}"{% endif -%}
|
|
72
75
|
{{- MdsAttributes(params.attributes) -}}
|
|
73
76
|
>
|
|
77
|
+
{# all 'default slot' fallback content is removed from DOM when vue component loads #}
|
|
74
78
|
<div class="mds-form-element__fallback">
|
|
75
|
-
|
|
79
|
+
{# matches Combobox Vue component #}
|
|
80
|
+
{% set _optionValuePath = params.optionValuePath or "value" %}
|
|
81
|
+
{% set _optionLabelPath = params.optionLabelPath or "label" %}
|
|
82
|
+
{# if no provided options, at least try to render select input with value's options #}
|
|
83
|
+
{% set _options = params.options or (params.multiple and params.value) %}
|
|
84
|
+
|
|
85
|
+
{% if params.fallbackTo === 'select' and _options %}
|
|
76
86
|
<select
|
|
77
87
|
class="mds-form-control"
|
|
78
88
|
id="{{ comboboxId }}"
|
|
79
89
|
name="{{ comboboxName }}"
|
|
80
|
-
|
|
90
|
+
{% if params.multiple %}multiple{% endif %}
|
|
81
91
|
{% if ariaDescribedBy %}aria-describedby="{{ariaDescribedBy}}"{% endif %}
|
|
82
92
|
>
|
|
83
93
|
<option>{{ placeholder }}</option>
|
|
84
|
-
{%- if
|
|
85
|
-
{%- for option in
|
|
86
|
-
<option
|
|
94
|
+
{%- if _options -%}
|
|
95
|
+
{%- for option in _options -%}
|
|
96
|
+
<option
|
|
97
|
+
value="{{ option[_optionValuePath] }}"
|
|
98
|
+
{% if not params.multiple and params.value %}
|
|
99
|
+
{# not multiple mode, see if value #}
|
|
100
|
+
{% if params.value[_optionValuePath] === option[_optionValuePath] %}selected{% endif %}
|
|
101
|
+
{% elseif params.value %}
|
|
102
|
+
{# multiple mode, so we assume params.value is an array #}
|
|
103
|
+
{% for valOpt in params.value %}
|
|
104
|
+
{%if valOpt[_optionValuePath] === option[_optionValuePath] %} selected {% endif %}
|
|
105
|
+
{% endfor %}
|
|
106
|
+
{% endif %}
|
|
107
|
+
>{{ option[_optionLabelPath] }}</option>
|
|
87
108
|
{%- endfor -%}
|
|
88
109
|
{%- endif -%}
|
|
89
110
|
</select>
|
|
90
|
-
|
|
111
|
+
{# we cant have multiple mode and use input #}
|
|
112
|
+
{% elseif not params.multiple and params.fallbackTo === 'input' %}
|
|
91
113
|
<input
|
|
92
114
|
class="mds-form-control"
|
|
93
115
|
type="text"
|
|
94
116
|
name="{{ comboboxName }}"
|
|
95
117
|
autocomplete="off"
|
|
96
118
|
id="{{ comboboxId }}"
|
|
97
|
-
value="{{
|
|
119
|
+
{% if params.value %} value="{{params.value[_optionValuePath]}}"{% endif %}
|
|
98
120
|
placeholder="{{ placeholder }}"
|
|
99
121
|
{% if params.validationError %}aria-invalid="true"{% endif %}
|
|
100
122
|
{% if ariaDescribedBy %}aria-describedby="{{ariaDescribedBy}}"{% endif %}
|
|
101
123
|
/>
|
|
124
|
+
{% elseif params.multiple and params.fallbackTo === 'input' %}
|
|
125
|
+
<strong>YOU MUST USE `select` AS `fallbackTo` WHEN USING `multiple` MODE</strong>
|
|
102
126
|
{% endif %}
|
|
103
127
|
</div>
|
|
104
128
|
{% if caller %}
|
|
105
|
-
|
|
106
|
-
{{- caller() -}}
|
|
107
|
-
</span>
|
|
129
|
+
{{- caller() -}}
|
|
108
130
|
{% endif %}
|
|
109
131
|
</mds-combobox>
|
|
132
|
+
<br><br>
|
|
110
133
|
</div>
|
|
111
134
|
{%- endif -%}
|
|
@@ -23,31 +23,16 @@ module.exports = {
|
|
|
23
23
|
classes: 'im-a-custom-class',
|
|
24
24
|
},
|
|
25
25
|
},
|
|
26
|
-
|
|
27
|
-
{
|
|
28
|
-
name: 'default',
|
|
29
|
-
context: {
|
|
30
|
-
variantTitle: 'Multi select',
|
|
31
|
-
name: 'multi',
|
|
32
|
-
id: 'multiselect',
|
|
33
|
-
optional: 'true',
|
|
34
|
-
labelText: 'How far are you willing to travel?',
|
|
35
|
-
options: optionsDistance,
|
|
36
|
-
fallbackTo: 'select',
|
|
37
|
-
multiple: true,
|
|
38
|
-
placeholder: 'eg. Within 5 miles',
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
26
|
{
|
|
42
|
-
name: '
|
|
27
|
+
name: 'Search text pre-populated, option *not* selected',
|
|
43
28
|
context: {
|
|
44
|
-
variantTitle: '
|
|
29
|
+
variantTitle: 'Search text pre-populated, option *not* selected',
|
|
45
30
|
name: 'Salary',
|
|
46
31
|
id: 'salary-selection',
|
|
47
32
|
optional: 'true',
|
|
48
33
|
labelText: 'Salary expectations?',
|
|
49
34
|
options: optionsSalary,
|
|
50
|
-
|
|
35
|
+
searchText: 'Up to',
|
|
51
36
|
fallbackTo: 'select',
|
|
52
37
|
},
|
|
53
38
|
},
|
|
@@ -66,6 +51,7 @@ module.exports = {
|
|
|
66
51
|
apiQueryKey: 's',
|
|
67
52
|
apiOptionsPath: undefined,
|
|
68
53
|
optionLabelPath: 'word',
|
|
54
|
+
optionValuePath: 'score',
|
|
69
55
|
i18n: {
|
|
70
56
|
requiredIcon: 'Required (test i18n)',
|
|
71
57
|
loadingText: 'Loading (test i18n)',
|
|
@@ -82,18 +68,18 @@ module.exports = {
|
|
|
82
68
|
context: {
|
|
83
69
|
useAutocomplete: true,
|
|
84
70
|
variantTitle: 'AJAX autocomplete prefilled',
|
|
85
|
-
name: 'keywords',
|
|
71
|
+
name: 'keywords-prefilled',
|
|
86
72
|
id: 'keywords-lookup-prefilled',
|
|
87
73
|
labelText: 'Keywords:',
|
|
88
74
|
placeholder: 'eg. Testimonials',
|
|
89
|
-
value: 'Initial Value',
|
|
90
|
-
vModel: 'Initial Value',
|
|
75
|
+
value: { word: 'Initial Value', score: 'the-value' },
|
|
91
76
|
fallbackTo: 'input',
|
|
92
77
|
minSearchCharacters: 3,
|
|
93
78
|
apiUrl: 'https://api.datamuse.com/sug',
|
|
94
79
|
apiQueryKey: 's',
|
|
95
80
|
apiOptionsPath: undefined,
|
|
96
81
|
optionLabelPath: 'word',
|
|
82
|
+
optionValuePath: 'score',
|
|
97
83
|
},
|
|
98
84
|
},
|
|
99
85
|
{
|
|
@@ -101,14 +87,78 @@ module.exports = {
|
|
|
101
87
|
context: {
|
|
102
88
|
useAutocomplete: true,
|
|
103
89
|
variantTitle: 'AJAX autocomplete prefilled with validation error',
|
|
104
|
-
name: '
|
|
90
|
+
name: 'keywordsprefilled-error',
|
|
105
91
|
id: 'keywords-lookup-prefilled-validation-error',
|
|
106
92
|
labelText: 'Keywords:',
|
|
107
93
|
placeholder: 'eg. Testimonials',
|
|
108
|
-
value: 'Initial Value',
|
|
109
|
-
vModel: 'Initial Value',
|
|
94
|
+
value: { word: 'Initial Value', score: 'the-value' },
|
|
110
95
|
fallbackTo: 'input',
|
|
111
96
|
validationError: 'There was an error',
|
|
97
|
+
apiQueryKey: 's',
|
|
98
|
+
apiOptionsPath: undefined,
|
|
99
|
+
optionLabelPath: 'word',
|
|
100
|
+
optionValuePath: 'score',
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
name: 'AJAX multiselect - multiple attr',
|
|
105
|
+
context: {
|
|
106
|
+
useAutocomplete: true,
|
|
107
|
+
variantTitle: 'AJAX multiselect',
|
|
108
|
+
name: 'keywords-multiple',
|
|
109
|
+
id: 'keywords-lookup-multiselect-preselected',
|
|
110
|
+
labelText: 'Keywords:',
|
|
111
|
+
placeholder: 'eg. Web developer',
|
|
112
|
+
fallbackTo: 'select',
|
|
113
|
+
minSearchCharacters: 3,
|
|
114
|
+
apiUrl: 'https://api.datamuse.com/sug',
|
|
115
|
+
apiQueryKey: 's',
|
|
116
|
+
apiOptionsPath: undefined,
|
|
117
|
+
optionLabelPath: 'word',
|
|
118
|
+
optionValuePath: 'score',
|
|
119
|
+
multiple: true,
|
|
120
|
+
i18n: {
|
|
121
|
+
requiredIcon: 'Required (test i18n)',
|
|
122
|
+
loadingText: 'Loading (test i18n)',
|
|
123
|
+
describedByText:
|
|
124
|
+
'When autocomplete results are available, use up and down arrows to review and enter to select. (test i18n)',
|
|
125
|
+
resultsMessage: '{count} result available (test i18n)',
|
|
126
|
+
resultsMessage_plural: '{count} results available (test i18n)',
|
|
127
|
+
clearInput: 'clear input (test i18n)',
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
name: 'AJAX multiselect - prefilled',
|
|
133
|
+
context: {
|
|
134
|
+
useAutocomplete: true,
|
|
135
|
+
variantTitle: 'AJAX multiselect-prefilled',
|
|
136
|
+
name: 'keywords-multiple-prefilled',
|
|
137
|
+
id: 'keywords-lookup-multiselect-prefilled',
|
|
138
|
+
labelText: 'Keywords:',
|
|
139
|
+
placeholder: 'eg. Web developer',
|
|
140
|
+
value: [
|
|
141
|
+
{ word: 'Initial Value 1', score: 'the-value-1' },
|
|
142
|
+
{ word: 'Initial Value 2', score: 'the-value-2' },
|
|
143
|
+
],
|
|
144
|
+
fallbackTo: 'select',
|
|
145
|
+
minSearchCharacters: 3,
|
|
146
|
+
apiUrl: 'https://api.datamuse.com/sug',
|
|
147
|
+
apiQueryKey: 's',
|
|
148
|
+
apiOptionsPath: undefined,
|
|
149
|
+
optionLabelPath: 'word',
|
|
150
|
+
optionValuePath: 'score',
|
|
151
|
+
multiple: true,
|
|
152
|
+
i18n: {
|
|
153
|
+
requiredIcon: 'Required (test i18n)',
|
|
154
|
+
loadingText: 'Loading (test i18n)',
|
|
155
|
+
describedByText:
|
|
156
|
+
'When autocomplete results are available, use up and down arrows to review and enter to select. (test i18n)',
|
|
157
|
+
resultsMessage: '{count} result available (test i18n)',
|
|
158
|
+
resultsMessage_plural: '{count} results available (test i18n)',
|
|
159
|
+
clearInput: 'clear input (test i18n)',
|
|
160
|
+
selectedOptionsLabel: 'Selected options: (test i18n)',
|
|
161
|
+
},
|
|
112
162
|
},
|
|
113
163
|
},
|
|
114
164
|
],
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{% from "./inputs/combobox/_macro.njk" import MdsCombobox %}
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
<div class="mds-grid-row">
|
|
3
|
+
<form class="mds-grid-row">
|
|
5
4
|
<div class="mds-grid-col-6">
|
|
6
5
|
<h3>{{ variantTitle }}</h3>
|
|
7
6
|
|
|
@@ -12,6 +11,7 @@
|
|
|
12
11
|
options: options,
|
|
13
12
|
optional: optional,
|
|
14
13
|
value: value,
|
|
14
|
+
searchText: searchText,
|
|
15
15
|
fallbackTo: fallbackTo,
|
|
16
16
|
classes: classes,
|
|
17
17
|
placeholder: placeholder,
|
|
@@ -24,25 +24,11 @@
|
|
|
24
24
|
apiQueryKey: apiQueryKey,
|
|
25
25
|
apiOptionsPath: apiOptionsPath,
|
|
26
26
|
optionLabelPath: optionLabelPath,
|
|
27
|
+
optionValuePath: optionValuePath,
|
|
28
|
+
multiple: multiple
|
|
27
29
|
attributes: attributes
|
|
28
30
|
}) %}
|
|
29
|
-
{#
|
|
30
|
-
The below demonstrates how a target input value can be set on option selection, or on clear of combobox
|
|
31
|
-
#}
|
|
32
|
-
{% if id === 'salary-selection' %}
|
|
33
|
-
<input disabled data-key="value" placeholder="normally hidden target" style="position:absolute; left: 100%; top: 0;" />
|
|
34
|
-
{% endif %}
|
|
35
|
-
{% if id === 'keywords-lookup' or id === 'keywords-lookup-prefilled' %}
|
|
36
|
-
<input disabled data-key="word" placeholder="normally hidden target" style="position:absolute; left: 100%; top: 0;" />
|
|
37
|
-
{% endif %}
|
|
38
31
|
{% endcall %}
|
|
39
|
-
|
|
40
|
-
{% if id === 'salary-selection' %}
|
|
41
|
-
<p class="mds-margin-top-b3">A hidden input is cleared when combobox is cleared.
|
|
42
|
-
{% endif %}
|
|
43
|
-
|
|
44
|
-
<br><br>
|
|
45
32
|
</div>
|
|
46
|
-
</
|
|
47
|
-
{% endif %}
|
|
33
|
+
</form>
|
|
48
34
|
|
|
@@ -1,39 +1,29 @@
|
|
|
1
1
|
.mds-combobox {
|
|
2
2
|
display: block;
|
|
3
3
|
position: relative;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
.mds-combobox--multiple {
|
|
11
|
-
background-color: #fff;
|
|
12
|
-
@extend .mds-form-control;
|
|
13
|
-
padding: 0;
|
|
14
|
-
& input[type='text'] {
|
|
15
|
-
width: 100%;
|
|
16
|
-
border: 0;
|
|
17
|
-
padding: $constant-size-baseline * 3; // match .mds-form-control
|
|
18
|
-
font-size: inherit;
|
|
19
|
-
line-height: inherit;
|
|
20
|
-
padding-right: $constant-size-baseline * 14;
|
|
21
|
-
appearance: none;
|
|
22
|
-
&:focus {
|
|
23
|
-
outline: 0;
|
|
24
|
-
}
|
|
4
|
+
.mds-form-control {
|
|
5
|
+
display: flex;
|
|
6
|
+
flex-wrap: wrap;
|
|
7
|
+
cursor: text;
|
|
8
|
+
gap: $constant-size-baseline;
|
|
25
9
|
}
|
|
26
10
|
}
|
|
27
|
-
.mds-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
11
|
+
.mds-combobox__search-input {
|
|
12
|
+
flex: 1;
|
|
13
|
+
min-width: 180px;
|
|
14
|
+
border: 0;
|
|
15
|
+
outline: 0;
|
|
16
|
+
font-size: inherit;
|
|
17
|
+
line-height: inherit;
|
|
18
|
+
background: transparent;
|
|
19
|
+
appearance: none;
|
|
20
|
+
padding-right: $constant-size-baseline * 10;
|
|
33
21
|
}
|
|
22
|
+
|
|
34
23
|
.mds-combobox__clear {
|
|
35
24
|
position: absolute;
|
|
36
25
|
top: 0;
|
|
26
|
+
bottom: 0;
|
|
37
27
|
right: 0;
|
|
38
28
|
cursor: pointer;
|
|
39
29
|
&:focus {
|
|
@@ -88,3 +78,45 @@
|
|
|
88
78
|
}
|
|
89
79
|
}
|
|
90
80
|
}
|
|
81
|
+
.mds-combobox__pills {
|
|
82
|
+
display: inline-flex;
|
|
83
|
+
flex-wrap: wrap;
|
|
84
|
+
gap: $constant-size-baseline;
|
|
85
|
+
margin-bottom: 0;
|
|
86
|
+
}
|
|
87
|
+
.mds-combobox__pill {
|
|
88
|
+
font-size: var(--mds-font-type-s-1-size);
|
|
89
|
+
display: inline-flex;
|
|
90
|
+
align-items: center;
|
|
91
|
+
border-radius: $border-radius;
|
|
92
|
+
padding: $constant-size-baseline ($constant-size-baseline * 2);
|
|
93
|
+
max-width: 100%;
|
|
94
|
+
background-color: $constant-color-neutral-lightest;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.mds-combobox__pill-text {
|
|
98
|
+
flex: 1 1 0;
|
|
99
|
+
overflow: hidden;
|
|
100
|
+
text-overflow: ellipsis;
|
|
101
|
+
white-space: nowrap;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.mds-combobox__pill-icon {
|
|
105
|
+
background: none;
|
|
106
|
+
border: none;
|
|
107
|
+
padding: 0 0 0 ($constant-size-baseline);
|
|
108
|
+
margin: 0;
|
|
109
|
+
cursor: pointer;
|
|
110
|
+
display: inline-flex;
|
|
111
|
+
align-items: center;
|
|
112
|
+
flex-shrink: 0;
|
|
113
|
+
|
|
114
|
+
.mds-icon {
|
|
115
|
+
top: 0;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
&:focus {
|
|
119
|
+
@include inputFocusStyle();
|
|
120
|
+
border-radius: $border-radius;
|
|
121
|
+
}
|
|
122
|
+
}
|