-
-
-
-
-
-
-
-
-
-
+
+
{% for _option in _options %}
-
+ {% endfor %}
+
+ {% else %}
+
{% endif %}
- {% if _option.disabled %}
- disabled
- {% endif %}
- >
- {{- _option.label -}}
-
{% endfor %}
diff --git a/src/implementations/vanilla/components/select/_select.scss b/src/implementations/vanilla/components/select/_select.scss
index 6a0cf07db0a..946c371f907 100644
--- a/src/implementations/vanilla/components/select/_select.scss
+++ b/src/implementations/vanilla/components/select/_select.scss
@@ -18,6 +18,9 @@ $_border-width: 1px;
$_border-width-focus: null !default;
$_color-input: null !default;
$_color-placeholder: null !default;
+$_group-separator-color: null !default;
+$_group-title-font: null !default;
+$_group-title-color: null !default;
$_shadow: null !default;
$_shadow-hover: null !default;
$_arrow-background-invalid-focus: null !default;
@@ -250,6 +253,7 @@ $_multiple_counter_background: null !default;
background-color: $_multiple-dropdown-background-color;
border: $_multiple-dropdown-border;
border-radius: $_multiple-dropdown-border-radius;
+ cursor: default;
box-shadow: $_multiple-dropdown-shadow;
box-sizing: border-box;
position: absolute;
@@ -266,28 +270,19 @@ $_multiple_counter_background: null !default;
}
.ecl-select__multiple-options {
+ box-sizing: border-box;
max-height: $_multiple-dropdown-container-max-height;
overflow-y: auto;
- }
-
- .ecl-select__multiple-no-results {
- align-items: center;
- color: map.get(theme.$color, 'grey-100');
- display: flex;
- font: map.get(theme.$font, 'm');
- height: 100%;
- justify-content: center;
- min-height: 100px;
- width: 100%;
+ padding: map.get(theme.$spacing, 's') 0;
}
.ecl-checkbox__label {
padding-bottom: $_multiple-checkbox-label-vertical-padding;
- padding-inline-start: map.get(theme.$spacing, 'm');
- padding-inline-end: map.get(theme.$spacing, 'm');
+ padding-inline-start: map.get(theme.$spacing, 's');
+ padding-inline-end: map.get(theme.$spacing, 's');
padding-top: $_multiple-checkbox-label-vertical-padding;
width: calc(
- 100% - #{map.get(theme.$spacing, 'm')} - #{map.get(theme.$spacing, 'm')}
+ 100% - #{map.get(theme.$spacing, 's')} - #{map.get(theme.$spacing, 's')}
);
}
@@ -296,6 +291,44 @@ $_multiple_counter_background: null !default;
background-color: $_multiple-checkbox-background-hover-color;
}
+ .ecl-select__multiple-group {
+ border-bottom: 1px solid $_group-separator-color;
+ margin: 0 map.get(theme.$spacing, 's');
+ padding: map.get(theme.$spacing, 's') 0;
+
+ &:first-child {
+ padding-top: 0;
+ }
+
+ .ecl-checkbox__label {
+ margin-inline-start: -#{map.get(theme.$spacing, 's')};
+ margin-inline-end: -#{map.get(theme.$spacing, 's')};
+ width: 100%;
+ }
+ }
+
+ .ecl-select__multiple-group + .ecl-checkbox {
+ margin-top: map.get(theme.$spacing, 's');
+ }
+
+ .ecl-select__multiple-group__title {
+ color: $_group-title-color;
+ font: $_group-title-font;
+ font-weight: map.get(theme.$font-weight, 'bold');
+ margin: map.get(theme.$spacing, 'xs') 0;
+ }
+
+ .ecl-select__multiple-no-results {
+ align-items: center;
+ color: map.get(theme.$color, 'grey-100');
+ display: flex;
+ font: map.get(theme.$font, 'm');
+ height: 100%;
+ justify-content: center;
+ min-height: 100px;
+ width: 100%;
+ }
+
.ecl-select-multiple-toolbar {
border-top: 1px solid $_multiple-dropdown-separator-color;
display: flex;
diff --git a/src/implementations/vanilla/components/select/select-ec.scss b/src/implementations/vanilla/components/select/select-ec.scss
index ffa7f67d65e..000ff1f46c3 100644
--- a/src/implementations/vanilla/components/select/select-ec.scss
+++ b/src/implementations/vanilla/components/select/select-ec.scss
@@ -10,6 +10,9 @@
$_border-width-focus: 3px,
$_color-input: map.get(theme.$color, 'grey-100'),
$_color-placeholder: map.get(theme.$color, 'grey-50'),
+ $_group-separator-color: map.get(theme.$color, 'grey-25'),
+ $_group-title-font: map.get(theme.$font-prolonged, 'm'),
+ $_group-title-color: map.get(theme.$color, 'grey-75'),
$_shadow: none,
$_shadow-hover: none,
$_arrow-background-color: map.get(theme.$color, 'grey-100'),
@@ -23,8 +26,8 @@
$_multiple-dropdown-shadow: none,
$_multiple-dropdown-input-margin: 0,
$_multiple-dropdown-input-width: 100%,
- $_multiple-dropdown-container-max-height: 280px,
+ $_multiple-dropdown-container-max-height: 252px,
$_multiple-checkbox-background-hover-color: map.get(theme.$color, 'grey-15'),
- $_multiple-checkbox-label-vertical-padding: map.get(theme.$spacing, 'm'),
+ $_multiple-checkbox-label-vertical-padding: map.get(theme.$spacing, 's'),
$_multiple_counter_background: #707070
);
diff --git a/src/implementations/vanilla/components/select/select-eu.scss b/src/implementations/vanilla/components/select/select-eu.scss
index bcc3bc66dbc..74aed63cf38 100644
--- a/src/implementations/vanilla/components/select/select-eu.scss
+++ b/src/implementations/vanilla/components/select/select-eu.scss
@@ -10,6 +10,9 @@
$_border-width-focus: 2px,
$_color-input: map.get(theme.$color, 'grey-140'),
$_color-placeholder: map.get(theme.$color, 'grey-40'),
+ $_group-separator-color: map.get(theme.$color, 'blue-20'),
+ $_group-title-font: map.get(theme.$font, 'm'),
+ $_group-title-color: map.get(theme.$color, 'grey-80'),
$_shadow: map.get(theme.$shadow-inner, '1'),
$_shadow-hover: map.get(theme.$shadow-inner, '2'),
$_arrow-background-invalid-focus: map.get(theme.$color, 'red-100'),
@@ -27,7 +30,7 @@
calc(
100% - #{map.get(theme.$spacing, 'xs')} - #{map.get(theme.$spacing, 'xs')}
),
- $_multiple-dropdown-container-max-height: 240px,
+ $_multiple-dropdown-container-max-height: 252px,
$_multiple-checkbox-background-hover-color: map.get(theme.$color, 'blue-5'),
$_multiple-checkbox-label-vertical-padding: map.get(theme.$spacing, 's'),
$_multiple_counter_background: map.get(theme.$color, 'blue-100')
diff --git a/src/implementations/vanilla/components/select/select.js b/src/implementations/vanilla/components/select/select.js
index 2824f85ebf5..380cb662128 100644
--- a/src/implementations/vanilla/components/select/select.js
+++ b/src/implementations/vanilla/components/select/select.js
@@ -370,13 +370,43 @@ export class Select {
if (this.select.options && this.select.options.length > 0) {
this.checkboxes = Array.from(this.select.options).map((option) => {
+ let optgroup = '';
+ let checkbox = '';
+ if (option.parentNode.tagName === 'OPTGROUP') {
+ if (
+ !this.optionsContainer.querySelector(
+ `div[data-ecl-multiple-group="${option.parentNode.getAttribute(
+ 'label'
+ )}"]`
+ )
+ ) {
+ optgroup = document.createElement('div');
+ const title = document.createElement('h5');
+ title.classList.add('ecl-select__multiple-group__title');
+ title.innerHTML = option.parentNode.getAttribute('label');
+ optgroup.appendChild(title);
+ optgroup.setAttribute(
+ 'data-ecl-multiple-group',
+ option.parentNode.getAttribute('label')
+ );
+ optgroup.classList.add('ecl-select__multiple-group');
+ this.optionsContainer.appendChild(optgroup);
+ } else {
+ optgroup = this.optionsContainer.querySelector(
+ `div[data-ecl-multiple-group="${option.parentNode.getAttribute(
+ 'label'
+ )}"]`
+ );
+ }
+ }
+
if (option.selected) {
this.updateSelectionsCount(1);
if (this.dropDownToolbar) {
this.dropDownToolbar.style.display = 'flex';
}
}
- const checkbox = Select.createCheckbox(
+ checkbox = Select.createCheckbox(
{
// spread operator does not work in storybook context so we map 1:1
id: option.value,
@@ -386,12 +416,18 @@ export class Select {
},
this.selectMultipleId
);
+
checkbox.setAttribute('data-visible', true);
if (!checkbox.classList.contains('ecl-checkbox--disabled')) {
checkbox.addEventListener('click', this.handleClickOption);
checkbox.addEventListener('keydown', this.handleKeyboardOnOption);
}
- this.optionsContainer.appendChild(checkbox);
+ if (optgroup) {
+ optgroup.appendChild(checkbox);
+ } else {
+ this.optionsContainer.appendChild(checkbox);
+ }
+
return checkbox;
});
}
@@ -623,7 +659,7 @@ export class Select {
.toLocaleLowerCase()
.includes(keyword)
) {
- checkbox.setAttribute('data-visible', false);
+ checkbox.removeAttribute('data-visible');
checkbox.style.display = 'none';
} else {
checkbox.setAttribute('data-visible', true);
@@ -656,6 +692,23 @@ export class Select {
const noResultsElement = this.searchContainer.querySelector(
'.ecl-select__multiple-no-results'
);
+ const groups = this.optionsContainer.getElementsByClassName(
+ 'ecl-select__multiple-group'
+ );
+ // eslint-disable-next-line no-restricted-syntax
+ for (const group of groups) {
+ group.style.display = 'none';
+ // eslint-disable-next-line no-restricted-syntax
+ const groupedCheckboxes = [...group.children].filter((node) =>
+ node.classList.contains('ecl-checkbox')
+ );
+ groupedCheckboxes.forEach((single) => {
+ if (single.hasAttribute('data-visible')) {
+ single.closest('.ecl-select__multiple-group').style.display = 'block';
+ }
+ });
+ }
+
if (visible.length === 0 && !noResultsElement) {
// Create no-results element.
const noResultsContainer = document.createElement('div');
@@ -860,11 +913,20 @@ export class Select {
*/
moveFocus(upOrDown) {
const activeEl = document.activeElement;
- const options = Array.from(
- activeEl.parentElement.parentElement.querySelectorAll(
- '.ecl-checkbox__input'
- )
+ const hasGroups = activeEl.parentElement.parentElement.classList.contains(
+ 'ecl-select__multiple-group'
);
+ const options = !hasGroups
+ ? Array.from(
+ activeEl.parentElement.parentElement.querySelectorAll(
+ '.ecl-checkbox__input'
+ )
+ )
+ : Array.from(
+ activeEl.parentElement.parentElement.parentElement.querySelectorAll(
+ '.ecl-checkbox__input'
+ )
+ );
const activeIndex = options.indexOf(activeEl);
if (upOrDown === 'down') {
const nextSiblings = options
diff --git a/src/specs/components/select/demo/data-multiple.js b/src/specs/components/select/demo/data-multiple.js
index eecea4f7f55..1651f53da01 100644
--- a/src/specs/components/select/demo/data-multiple.js
+++ b/src/specs/components/select/demo/data-multiple.js
@@ -15,45 +15,67 @@ module.exports = {
width: 'm',
options: [
{
- value: '1',
- label: 'Belgium',
+ optgroup: {
+ label: 'European countries',
+ options: [
+ {
+ value: '1',
+ label: 'Belgium',
+ },
+ {
+ value: '2',
+ label: 'France',
+ },
+ {
+ value: '3',
+ label: 'Luxembourg',
+ disabled: true,
+ },
+ {
+ value: '4',
+ label: 'Germany',
+ },
+ {
+ value: '5',
+ label: 'Bulgaria',
+ },
+ {
+ value: '6',
+ label: 'Italy',
+ },
+ {
+ value: '7',
+ label: 'Romania',
+ },
+ {
+ value: '8',
+ label: 'Greece',
+ },
+ {
+ value: '9',
+ label: 'Hungary',
+ },
+ {
+ value: '10',
+ label: 'Portugal',
+ },
+ ],
+ },
},
{
- value: '2',
- label: 'France',
+ optgroup: {
+ label: 'Non European countries',
+ options: [
+ {
+ value: '11',
+ label: 'China',
+ },
+ ],
+ },
},
{
- value: '3',
- label: 'Luxembourg',
- disabled: true,
- },
- {
- value: '4',
- label: 'Germany',
- },
- {
- value: '5',
- label: 'Bulgaria',
- },
- {
- value: '6',
- label: 'Italy',
- },
- {
- value: '7',
- label: 'Romania',
- },
- {
- value: '8',
- label: 'Greece',
- },
- {
- value: '9',
- label: 'Democratic Republic of the Congo',
- },
- {
- value: '10',
- label: 'Portugal',
+ value: '12',
+ label: 'standalone option',
},
],
multiple: true,
diff --git a/src/specs/components/select/demo/data-single.js b/src/specs/components/select/demo/data-single.js
index d42d675e9de..aa858258832 100644
--- a/src/specs/components/select/demo/data-single.js
+++ b/src/specs/components/select/demo/data-single.js
@@ -15,46 +15,68 @@ module.exports = {
width: 'm',
options: [
{
- value: '1',
- label: 'Belgium',
+ optgroup: {
+ label: 'European countries',
+ options: [
+ {
+ value: '1',
+ label: 'Belgium',
+ },
+ {
+ value: '2',
+ label: 'France',
+ },
+ {
+ value: '3',
+ label: 'Luxembourg',
+ disabled: true,
+ },
+ {
+ value: '4',
+ label: 'Germany',
+ },
+ {
+ value: '5',
+ label: 'Bulgaria',
+ selected: true,
+ },
+ {
+ value: '6',
+ label: 'Italy',
+ },
+ {
+ value: '7',
+ label: 'Romania',
+ },
+ {
+ value: '8',
+ label: 'Greece',
+ },
+ {
+ value: '9',
+ label: 'Hungary',
+ },
+ {
+ value: '10',
+ label: 'Portugal',
+ },
+ ],
+ },
},
{
- value: '2',
- label: 'France',
+ optgroup: {
+ label: 'Non European countries',
+ options: [
+ {
+ value: '11',
+ label: 'China',
+ },
+ ],
+ },
},
{
- value: '3',
- label: 'Luxembourg',
- disabled: true,
- },
- {
- value: '4',
- label: 'Germany',
- },
- {
- value: '5',
- label: 'Bulgaria',
- selected: true,
- },
- {
- value: '6',
- label: 'Italy',
- },
- {
- value: '7',
- label: 'Romania',
- },
- {
- value: '8',
- label: 'Greece',
- },
- {
- value: '9',
- label: 'Hungary',
- },
- {
- value: '10',
- label: 'Portugal',
+ value: '12',
+ label: 'standalone option',
},
],
};