diff --git a/src/documentation/views/ui-components/autocomplete/examples.vue b/src/documentation/views/ui-components/autocomplete/examples.vue index 8f8742ad7..a7cd4dfb3 100644 --- a/src/documentation/views/ui-components/autocomplete/examples.vue +++ b/src/documentation/views/ui-components/autocomplete/examples.vue @@ -58,15 +58,16 @@ div app.use(WaveUI) app.mount('#app') - title-link(h2) Placeholder + title-link(h2) Groups / Multiselect example(content-class="py12" :blank-codepen="['js']") - w-autocomplete.mb12(:items="chemicalElement" placeholder="select an element") + w-autocomplete.mb12(:groups="animalGroups" :items="animals" multiple placeholder="select an animal") template(#pug). - w-autocomplete.mb12(:items="chemicalElement" placeholder="select an element") + w-autocomplete.mb12(:groups="animalGroups" :items="animals" multiple placeholder="select an animal") template(#html). <w-autocomplete - :items="chemicalElement" - placeholder="select an element" + :groups="animalGroups" + :items="animals" + placeholder="select an animal" class="mb12"> </w-autocomplete> template(#js). @@ -74,13 +75,19 @@ div const app = Vue.createApp({ data: () => ({ - chemicalElement: faker.definitions.science.chemicalElement.map(element => { + animals: [ 'dog', 'cat', 'bear' ].map(animal => faker.definitions.animal[animal].map(name => { return { - value: element.symbol, - label: element.name, - searchable: `${element.symbol}, ${element.name}, ${element.atomicNumber}` + value: name, + label: name, + searchable: name, + group: animal, } - }) + })).flat(), + animalGroups: [ + { group: 'dog', label: 'Dog' }, + { group: 'cat', label: 'Cat' }, + { group: 'bear', label: 'Bear' }, + ] }) }) @@ -97,9 +104,23 @@ export default { return { value: element.symbol, label: element.name, - searchable: `${element.symbol}, ${element.name}, ${element.atomicNumber}` + searchable: `${element.symbol}, ${element.name}, ${element.atomicNumber}`, + group: `row-${element.atomicNumber}` + } + }), + animals: [ 'dog', 'cat', 'bear' ].map(animal => faker.definitions.animal[animal].map(name => { + return { + value: name, + label: name, + searchable: name, + group: animal, } - }) + })).flat(), + animalGroups: [ + { group: 'dog', label: 'Dog' }, + { group: 'cat', label: 'Cat' }, + { group: 'bear', label: 'Bear' }, + ] }) } diff --git a/src/wave-ui/components/w-autocomplete.vue b/src/wave-ui/components/w-autocomplete.vue index 87809ed82..1d8225977 100644 --- a/src/wave-ui/components/w-autocomplete.vue +++ b/src/wave-ui/components/w-autocomplete.vue @@ -20,7 +20,21 @@ @mouseup="setEndOfMenuClick" @touchstart="menuIsBeingClicked = true" @touchend="setEndOfMenuClick") + template(v-if="groups" v-for="(group, g) in groups" :key="g") + slot(name="group" :group="group") + li.w-autocomplete__group.title5 {{ group[groupLabelKey] }} + template(v-for="(item, i) in filteredItems" :key="i") + li.w-autocomplete__group-item.ml2( + v-if="item.group === group[groupKey]" + @click.stop="selectItem(item), $emit('item-click', item)" + :class="{ highlighted: highlightedItem === item.uid }") + slot( + name="item" + :item="item" + :highlighted="highlightedItem === item.uid") + span(v-html="item[itemLabelKey]") li( + v-else v-for="(item, i) in filteredItems" :key="i" @click.stop="selectItem(item), $emit('item-click', item)" @@ -45,6 +59,7 @@ export default { props: { items: { type: Array, required: true }, + groups: { type: Array }, modelValue: { type: [String, Number, Array] }, // String or Number if single selections, Array if multiple. placeholder: { type: String }, openOnKeydown: { type: Boolean }, // By default the menu is always open for selection. @@ -59,7 +74,12 @@ export default { itemLabelKey: { type: String, default: 'label' }, // Contains the string to search keywords into for each item. // This can for instance be an aggregation of multiple fields (outside of Wave UI). - itemSearchableKey: { type: String, default: 'searchable' } + itemSearchableKey: { type: String, default: 'searchable' }, + // Contains the key for the group on each item. + // Also is the key within groups for the group label. + groupKey: { type: String, default: 'group' }, + // The label within the groups for the group name. + groupLabelKey: { type: String, default: 'label' } }, // item-select is also from keyboard, 'item-click' may be useful for mouseenter mouseleave events.